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 gridctrl.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 -isystem /usr/include/libxml2 -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 SVXCORE_DLLIMPLEMENTATION -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium/public -D COMPONENT_BUILD -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/svx/inc -I /home/maarten/src/libreoffice/core/svx/source/inc -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/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/svx/sdi -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/svx/source/fmcomp/gridctrl.cxx

/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.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
20#include <sal/log.hxx>
21#include <helpids.h>
22#include <svx/gridctrl.hxx>
23#include <gridcell.hxx>
24#include <svx/fmtools.hxx>
25#include <svtools/stringtransfer.hxx>
26#include <connectivity/dbtools.hxx>
27#include <connectivity/dbconversion.hxx>
28
29#include <fmprop.hxx>
30#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
31#include <com/sun/star/accessibility/XAccessible.hpp>
32#include <com/sun/star/sdb/XResultSetAccess.hpp>
33#include <com/sun/star/sdb/RowChangeAction.hpp>
34#include <com/sun/star/sdb/XRowsChangeBroadcaster.hpp>
35#include <com/sun/star/sdbc/SQLException.hpp>
36#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
37#include <com/sun/star/sdbc/XRowSet.hpp>
38#include <com/sun/star/sdbcx/Privilege.hpp>
39#include <com/sun/star/util/NumberFormatter.hpp>
40#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
41#include <com/sun/star/beans/XPropertySet.hpp>
42#include <com/sun/star/beans/PropertyChangeEvent.hpp>
43#include <com/sun/star/container/XIndexAccess.hpp>
44#include <tools/diagnose_ex.h>
45#include <tools/debug.hxx>
46#include <tools/fract.hxx>
47#include <vcl/builder.hxx>
48#include <vcl/menu.hxx>
49#include <vcl/settings.hxx>
50#include <vcl/commandevent.hxx>
51#include <vcl/svapp.hxx>
52
53#include <svx/strings.hrc>
54
55#include <svx/dialmgr.hxx>
56#include <sdbdatacolumn.hxx>
57
58#include <comphelper/property.hxx>
59#include <comphelper/types.hxx>
60#include <cppuhelper/implbase.hxx>
61
62#include <algorithm>
63#include <cstdlib>
64#include <map>
65#include <memory>
66
67using namespace ::dbtools;
68using namespace ::dbtools::DBTypeConversion;
69using namespace ::svxform;
70using namespace ::svt;
71using namespace ::com::sun::star::beans;
72using namespace ::com::sun::star::lang;
73using namespace ::com::sun::star::uno;
74using namespace ::com::sun::star::sdbc;
75using namespace ::com::sun::star::sdbcx;
76using namespace ::com::sun::star::sdb;
77using namespace ::com::sun::star::datatransfer;
78using namespace ::com::sun::star::container;
79using namespace com::sun::star::accessibility;
80
81#define ROWSTATUS(row)(!row.is() ? "NULL" : row->GetStatus() == GridRowStatus::Clean
? "CLEAN" : row->GetStatus() == GridRowStatus::Modified ?
"MODIFIED" : row->GetStatus() == GridRowStatus::Deleted ?
"DELETED" : "INVALID")
(!row.is() ? "NULL" : row->GetStatus() == GridRowStatus::Clean ? "CLEAN" : row->GetStatus() == GridRowStatus::Modified ? "MODIFIED" : row->GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID")
82
83constexpr auto DEFAULT_BROWSE_MODE =
84 BrowserMode::COLUMNSELECTION
85 | BrowserMode::MULTISELECTION
86 | BrowserMode::KEEPHIGHLIGHT
87 | BrowserMode::TRACKING_TIPS
88 | BrowserMode::HLINES
89 | BrowserMode::VLINES
90 | BrowserMode::HEADERBAR_NEW;
91
92class RowSetEventListener : public ::cppu::WeakImplHelper<XRowsChangeListener>
93{
94 VclPtr<DbGridControl> m_pControl;
95public:
96 explicit RowSetEventListener(DbGridControl* i_pControl) : m_pControl(i_pControl)
97 {
98 }
99
100private:
101 // XEventListener
102 virtual void SAL_CALL disposing(const css::lang::EventObject& /*i_aEvt*/) override
103 {
104 }
105 virtual void SAL_CALL rowsChanged(const css::sdb::RowsChangeEvent& i_aEvt) override
106 {
107 if ( i_aEvt.Action != RowChangeAction::UPDATE )
108 return;
109
110 ::DbGridControl::GrantControlAccess aAccess;
111 CursorWrapper* pSeek = m_pControl->GetSeekCursor(aAccess);
112 const DbGridRowRef& rSeekRow = m_pControl->GetSeekRow(aAccess);
113 for(const Any& rBookmark : i_aEvt.Bookmarks)
114 {
115 pSeek->moveToBookmark(rBookmark);
116 // get the data
117 rSeekRow->SetState(pSeek, true);
118 sal_Int32 nSeekPos = pSeek->getRow() - 1;
119 m_pControl->SetSeekPos(nSeekPos,aAccess);
120 m_pControl->RowModified(nSeekPos);
121 }
122 }
123};
124
125class GridFieldValueListener;
126typedef std::map<sal_uInt16, GridFieldValueListener*> ColumnFieldValueListeners;
127
128class GridFieldValueListener : protected ::comphelper::OPropertyChangeListener
129{
130 osl::Mutex m_aMutex;
131 DbGridControl& m_rParent;
132 rtl::Reference<::comphelper::OPropertyChangeMultiplexer> m_pRealListener;
133 sal_uInt16 m_nId;
134 sal_Int16 m_nSuspended;
135 bool m_bDisposed : 1;
136
137public:
138 GridFieldValueListener(DbGridControl& _rParent, const Reference< XPropertySet >& xField, sal_uInt16 _nId);
139 virtual ~GridFieldValueListener() override;
140
141 virtual void _propertyChanged(const PropertyChangeEvent& evt) override;
142
143 void suspend() { ++m_nSuspended; }
144 void resume() { --m_nSuspended; }
145
146 void dispose();
147};
148
149GridFieldValueListener::GridFieldValueListener(DbGridControl& _rParent, const Reference< XPropertySet >& _rField, sal_uInt16 _nId)
150 :OPropertyChangeListener(m_aMutex)
151 ,m_rParent(_rParent)
152 ,m_nId(_nId)
153 ,m_nSuspended(0)
154 ,m_bDisposed(false)
155{
156 if (_rField.is())
157 {
158 m_pRealListener = new ::comphelper::OPropertyChangeMultiplexer(this, _rField);
159 m_pRealListener->addProperty(FM_PROP_VALUE"Value");
160 }
161}
162
163GridFieldValueListener::~GridFieldValueListener()
164{
165 dispose();
166}
167
168void GridFieldValueListener::_propertyChanged(const PropertyChangeEvent& /*_evt*/)
169{
170 DBG_ASSERT(m_nSuspended>=0, "GridFieldValueListener::_propertyChanged : resume > suspend !")do { if (true && (!(m_nSuspended>=0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "170" ": "), "%s", "GridFieldValueListener::_propertyChanged : resume > suspend !"
); } } while (false)
;
171 if (m_nSuspended <= 0)
172 m_rParent.FieldValueChanged(m_nId);
173}
174
175void GridFieldValueListener::dispose()
176{
177 if (m_bDisposed)
178 {
179 DBG_ASSERT(!m_pRealListener, "GridFieldValueListener::dispose : inconsistent !")do { if (true && (!(!m_pRealListener))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "179" ": "), "%s", "GridFieldValueListener::dispose : inconsistent !"
); } } while (false)
;
180 return;
181 }
182
183 if (m_pRealListener.is())
184 {
185 m_pRealListener->dispose();
186 m_pRealListener.clear();
187 }
188
189 m_bDisposed = true;
190 m_rParent.FieldListenerDisposing(m_nId);
191}
192
193class DisposeListenerGridBridge : public FmXDisposeListener
194{
195 DbGridControl& m_rParent;
196 rtl::Reference<FmXDisposeMultiplexer> m_xRealListener;
197
198public:
199 DisposeListenerGridBridge( DbGridControl& _rParent, const Reference< XComponent >& _rxObject);
200 virtual ~DisposeListenerGridBridge() override;
201
202 virtual void disposing(sal_Int16 _nId) override { m_rParent.disposing(_nId); }
203};
204
205DisposeListenerGridBridge::DisposeListenerGridBridge(DbGridControl& _rParent, const Reference< XComponent >& _rxObject)
206 :FmXDisposeListener()
207 ,m_rParent(_rParent)
208{
209
210 if (_rxObject.is())
211 {
212 m_xRealListener = new FmXDisposeMultiplexer(this, _rxObject);
213 }
214}
215
216DisposeListenerGridBridge::~DisposeListenerGridBridge()
217{
218 if (m_xRealListener.is())
219 {
220 m_xRealListener->dispose();
221 }
222}
223
224const DbGridControlNavigationBarState ControlMap[] =
225 {
226 DbGridControlNavigationBarState::Text,
227 DbGridControlNavigationBarState::Absolute,
228 DbGridControlNavigationBarState::Of,
229 DbGridControlNavigationBarState::Count,
230 DbGridControlNavigationBarState::First,
231 DbGridControlNavigationBarState::Next,
232 DbGridControlNavigationBarState::Prev,
233 DbGridControlNavigationBarState::Last,
234 DbGridControlNavigationBarState::New,
235 DbGridControlNavigationBarState::NONE
236 };
237
238bool CompareBookmark(const Any& aLeft, const Any& aRight)
239{
240 return aLeft == aRight;
241}
242
243class FmXGridSourcePropListener : public ::comphelper::OPropertyChangeListener
244{
245 VclPtr<DbGridControl> m_pParent;
246
247 // a DbGridControl has no mutex, so we use our own as the base class expects one
248 osl::Mutex m_aMutex;
249 sal_Int16 m_nSuspended;
250
251public:
252 explicit FmXGridSourcePropListener(DbGridControl* _pParent);
253
254 void suspend() { ++m_nSuspended; }
255 void resume() { --m_nSuspended; }
256
257 virtual void _propertyChanged(const PropertyChangeEvent& evt) override;
258};
259
260FmXGridSourcePropListener::FmXGridSourcePropListener(DbGridControl* _pParent)
261 :OPropertyChangeListener(m_aMutex)
262 ,m_pParent(_pParent)
263 ,m_nSuspended(0)
264{
265 DBG_ASSERT(m_pParent, "FmXGridSourcePropListener::FmXGridSourcePropListener : invalid parent !")do { if (true && (!(m_pParent))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "265" ": "), "%s", "FmXGridSourcePropListener::FmXGridSourcePropListener : invalid parent !"
); } } while (false)
;
266}
267
268void FmXGridSourcePropListener::_propertyChanged(const PropertyChangeEvent& evt)
269{
270 DBG_ASSERT(m_nSuspended>=0, "FmXGridSourcePropListener::_propertyChanged : resume > suspend !")do { if (true && (!(m_nSuspended>=0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "270" ": "), "%s", "FmXGridSourcePropListener::_propertyChanged : resume > suspend !"
); } } while (false)
;
271 if (m_nSuspended <= 0)
272 m_pParent->DataSourcePropertyChanged(evt);
273}
274
275const int nReserveNumDigits = 7;
276
277NavigationBar::AbsolutePos::AbsolutePos(std::unique_ptr<weld::Entry> xEntry, NavigationBar* pBar)
278 : RecordItemWindowBase(std::move(xEntry))
279 , m_xParent(pBar)
280{
281}
282
283bool NavigationBar::AbsolutePos::DoKeyInput(const KeyEvent& rEvt)
284{
285 if (rEvt.GetKeyCode() == KEY_TAB)
286 {
287 m_xParent->GetParent()->GrabFocus();
288 return true;
289 }
290 return RecordItemWindowBase::DoKeyInput(rEvt);
291}
292
293void NavigationBar::AbsolutePos::PositionFired(sal_Int64 nRecord)
294{
295 m_xParent->PositionDataSource(nRecord);
296 m_xParent->InvalidateState(DbGridControlNavigationBarState::Absolute);
297}
298
299void NavigationBar::PositionDataSource(sal_Int32 nRecord)
300{
301 if (m_bPositioning)
302 return;
303 // the MoveToPosition may cause a LoseFocus which would lead to a second MoveToPosition,
304 // so protect against this recursion
305 m_bPositioning = true;
306 static_cast<DbGridControl*>(GetParent())->MoveToPosition(nRecord - 1);
307 m_bPositioning = false;
308}
309
310NavigationBar::NavigationBar(vcl::Window* pParent)
311 : InterimItemWindow(pParent, "svx/ui/navigationbar.ui", "NavigationBar")
312 , m_xRecordText(m_xBuilder->weld_label("recordtext"))
313 , m_xAbsolute(new NavigationBar::AbsolutePos(m_xBuilder->weld_entry("entry-noframe"), this))
314 , m_xRecordOf(m_xBuilder->weld_label("recordof"))
315 , m_xRecordCount(m_xBuilder->weld_label("recordcount"))
316 , m_xFirstBtn(m_xBuilder->weld_button("first"))
317 , m_xPrevBtn(m_xBuilder->weld_button("prev"))
318 , m_xNextBtn(m_xBuilder->weld_button("next"))
319 , m_xLastBtn(m_xBuilder->weld_button("last"))
320 , m_xNewBtn(m_xBuilder->weld_button("new"))
321 , m_nCurrentPos(-1)
322 , m_bPositioning(false)
323{
324 vcl::Font aApplFont(Application::GetSettings().GetStyleSettings().GetToolFont());
325 m_xAbsolute->set_font(aApplFont);
326 aApplFont.SetTransparent(true);
327 m_xRecordText->set_font(aApplFont);
328 m_xRecordOf->set_font(aApplFont);
329 m_xRecordCount->set_font(aApplFont);
330
331 m_xFirstBtn->set_help_id(HID_GRID_TRAVEL_FIRST"SVX_HID_GRID_TRAVEL_FIRST");
332 m_xPrevBtn->set_help_id(HID_GRID_TRAVEL_PREV"SVX_HID_GRID_TRAVEL_PREV");
333 m_xNextBtn->set_help_id(HID_GRID_TRAVEL_NEXT"SVX_HID_GRID_TRAVEL_NEXT");
334 m_xLastBtn->set_help_id(HID_GRID_TRAVEL_LAST"SVX_HID_GRID_TRAVEL_LAST");
335 m_xNewBtn->set_help_id(HID_GRID_TRAVEL_NEW"SVX_HID_GRID_TRAVEL_NEW");
336 m_xAbsolute->set_help_id(HID_GRID_TRAVEL_ABSOLUTE"SVX_HID_GRID_TRAVEL_ABSOLUTE");
337 m_xRecordCount->set_help_id(HID_GRID_NUMBEROFRECORDS"SVX_HID_GRID_NUMBEROFRECORDS");
338
339 // set handlers for buttons
340 m_xFirstBtn->connect_clicked(LINK(this,NavigationBar,OnClick)::tools::detail::makeLink( ::tools::detail::castTo<NavigationBar
*>(this), &NavigationBar::LinkStubOnClick)
);
341 m_xLastBtn->connect_clicked(LINK(this,NavigationBar,OnClick)::tools::detail::makeLink( ::tools::detail::castTo<NavigationBar
*>(this), &NavigationBar::LinkStubOnClick)
);
342 m_xNewBtn->connect_clicked(LINK(this,NavigationBar,OnClick)::tools::detail::makeLink( ::tools::detail::castTo<NavigationBar
*>(this), &NavigationBar::LinkStubOnClick)
);
343
344 // instead of connect_clicked because we want a button held down to
345 // repeat the next/prev
346 m_xPrevBtn->connect_mouse_press(LINK(this, NavigationBar, PrevMousePressHdl)::tools::detail::makeLink( ::tools::detail::castTo<NavigationBar
*>(this), &NavigationBar::LinkStubPrevMousePressHdl)
);
347 m_xNextBtn->connect_mouse_press(LINK(this, NavigationBar, NextMousePressHdl)::tools::detail::makeLink( ::tools::detail::castTo<NavigationBar
*>(this), &NavigationBar::LinkStubNextMousePressHdl)
);
348 m_xPrevBtn->connect_mouse_release(LINK(this, NavigationBar, PrevMouseReleaseHdl)::tools::detail::makeLink( ::tools::detail::castTo<NavigationBar
*>(this), &NavigationBar::LinkStubPrevMouseReleaseHdl
)
);
349 m_xNextBtn->connect_mouse_release(LINK(this, NavigationBar, NextMouseReleaseHdl)::tools::detail::makeLink( ::tools::detail::castTo<NavigationBar
*>(this), &NavigationBar::LinkStubNextMouseReleaseHdl
)
);
350
351 auto nRepeatTime = Application::GetSettings().GetMouseSettings().GetButtonRepeat();
352 m_aNextRepeat.SetTimeout(nRepeatTime);
353 m_aNextRepeat.SetInvokeHandler(LINK(this, NavigationBar, NextRepeatTimerHdl)::tools::detail::makeLink( ::tools::detail::castTo<NavigationBar
*>(this), &NavigationBar::LinkStubNextRepeatTimerHdl)
);
354 m_aPrevRepeat.SetTimeout(nRepeatTime);
355 m_aPrevRepeat.SetInvokeHandler(LINK(this, NavigationBar, PrevRepeatTimerHdl)::tools::detail::makeLink( ::tools::detail::castTo<NavigationBar
*>(this), &NavigationBar::LinkStubPrevRepeatTimerHdl)
);
356
357 m_xRecordText->set_label(SvxResId(RID_STR_REC_TEXTreinterpret_cast<char const *>("RID_STR_REC_TEXT" "\004"
u8"Record")
));
358 m_xRecordOf->set_label(SvxResId(RID_STR_REC_FROM_TEXTreinterpret_cast<char const *>("RID_STR_REC_FROM_TEXT" "\004"
u8"of")
));
359 m_xRecordCount->set_label(OUString('?'));
360
361 auto nReserveWidth = m_xRecordCount->get_approximate_digit_width() * nReserveNumDigits;
362 m_xAbsolute->GetWidget()->set_size_request(nReserveWidth, -1);
363 m_xRecordCount->set_size_request(nReserveWidth, -1);
364}
365
366NavigationBar::~NavigationBar()
367{
368 disposeOnce();
369}
370
371void NavigationBar::dispose()
372{
373 m_xRecordText.reset();
374 m_xAbsolute.reset();
375 m_xRecordOf.reset();
376 m_xRecordCount.reset();
377 m_xFirstBtn.reset();
378 m_xPrevBtn.reset();
379 m_xNextBtn.reset();
380 m_xLastBtn.reset();
381 m_xNewBtn.reset();
382 InterimItemWindow::dispose();
383}
384
385sal_uInt16 NavigationBar::ArrangeControls()
386{
387 return m_xContainer->get_preferred_size().Width();
388}
389
390IMPL_LINK_NOARG(NavigationBar, PrevRepeatTimerHdl, Timer*, void)void NavigationBar::LinkStubPrevRepeatTimerHdl(void * instance
, Timer* data) { return static_cast<NavigationBar *>(instance
)->PrevRepeatTimerHdl(data); } void NavigationBar::PrevRepeatTimerHdl
(__attribute__ ((unused)) Timer*)
391{
392 OnClick(*m_xPrevBtn);
393}
394
395IMPL_LINK_NOARG(NavigationBar, NextRepeatTimerHdl, Timer*, void)void NavigationBar::LinkStubNextRepeatTimerHdl(void * instance
, Timer* data) { return static_cast<NavigationBar *>(instance
)->NextRepeatTimerHdl(data); } void NavigationBar::NextRepeatTimerHdl
(__attribute__ ((unused)) Timer*)
396{
397 OnClick(*m_xNextBtn);
398}
399
400IMPL_LINK_NOARG(NavigationBar, PrevMousePressHdl, const MouseEvent&, bool)bool NavigationBar::LinkStubPrevMousePressHdl(void * instance
, const MouseEvent& data) { return static_cast<NavigationBar
*>(instance)->PrevMousePressHdl(data); } bool NavigationBar
::PrevMousePressHdl(__attribute__ ((unused)) const MouseEvent
&)
401{
402 if (!m_xPrevBtn->get_sensitive())
403 return false;
404 PrevRepeatTimerHdl(nullptr);
405 if (!m_xPrevBtn->get_sensitive())
406 return false;
407 m_aPrevRepeat.Start();
408 return false;
409}
410
411IMPL_LINK_NOARG(NavigationBar, PrevMouseReleaseHdl, const MouseEvent&, bool)bool NavigationBar::LinkStubPrevMouseReleaseHdl(void * instance
, const MouseEvent& data) { return static_cast<NavigationBar
*>(instance)->PrevMouseReleaseHdl(data); } bool NavigationBar
::PrevMouseReleaseHdl(__attribute__ ((unused)) const MouseEvent
&)
412{
413 m_aPrevRepeat.Stop();
414 return false;
415}
416
417IMPL_LINK_NOARG(NavigationBar, NextMousePressHdl, const MouseEvent&, bool)bool NavigationBar::LinkStubNextMousePressHdl(void * instance
, const MouseEvent& data) { return static_cast<NavigationBar
*>(instance)->NextMousePressHdl(data); } bool NavigationBar
::NextMousePressHdl(__attribute__ ((unused)) const MouseEvent
&)
418{
419 if (m_xNextBtn->get_sensitive())
420 {
421 NextRepeatTimerHdl(nullptr);
422 m_aNextRepeat.Start();
423 }
424 return false;
425}
426
427IMPL_LINK_NOARG(NavigationBar, NextMouseReleaseHdl, const MouseEvent&, bool)bool NavigationBar::LinkStubNextMouseReleaseHdl(void * instance
, const MouseEvent& data) { return static_cast<NavigationBar
*>(instance)->NextMouseReleaseHdl(data); } bool NavigationBar
::NextMouseReleaseHdl(__attribute__ ((unused)) const MouseEvent
&)
428{
429 m_aNextRepeat.Stop();
430 return false;
431}
432
433IMPL_LINK(NavigationBar, OnClick, weld::Button&, rButton, void)void NavigationBar::LinkStubOnClick(void * instance, weld::Button
& data) { return static_cast<NavigationBar *>(instance
)->OnClick(data); } void NavigationBar::OnClick(weld::Button
& rButton)
434{
435 DbGridControl* pParent = static_cast<DbGridControl*>(GetParent());
436
437 if (pParent->m_aMasterSlotExecutor.IsSet())
438 {
439 bool lResult = false;
440 if (&rButton == m_xFirstBtn.get())
441 lResult = pParent->m_aMasterSlotExecutor.Call(DbGridControlNavigationBarState::First);
442 else if( &rButton == m_xPrevBtn.get() )
443 lResult = pParent->m_aMasterSlotExecutor.Call(DbGridControlNavigationBarState::Prev);
444 else if( &rButton == m_xNextBtn.get() )
445 lResult = pParent->m_aMasterSlotExecutor.Call(DbGridControlNavigationBarState::Next);
446 else if( &rButton == m_xLastBtn.get() )
447 lResult = pParent->m_aMasterSlotExecutor.Call(DbGridControlNavigationBarState::Last);
448 else if( &rButton == m_xNewBtn.get() )
449 lResult = pParent->m_aMasterSlotExecutor.Call(DbGridControlNavigationBarState::New);
450
451 if (lResult)
452 // the link already handled it
453 return;
454 }
455
456 if (&rButton == m_xFirstBtn.get())
457 pParent->MoveToFirst();
458 else if( &rButton == m_xPrevBtn.get() )
459 pParent->MoveToPrev();
460 else if( &rButton == m_xNextBtn.get() )
461 pParent->MoveToNext();
462 else if( &rButton == m_xLastBtn.get() )
463 pParent->MoveToLast();
464 else if( &rButton == m_xNewBtn.get() )
465 pParent->AppendNew();
466}
467
468void NavigationBar::InvalidateAll(sal_Int32 nCurrentPos, bool bAll)
469{
470 if (!(m_nCurrentPos != nCurrentPos || nCurrentPos < 0 || bAll))
471 return;
472
473 DbGridControl* pParent = static_cast<DbGridControl*>(GetParent());
474
475 sal_Int32 nAdjustedRowCount = pParent->GetRowCount() - ((pParent->GetOptions() & DbGridControlOptions::Insert) ? 2 : 1);
476
477 // check if everything needs to be invalidated
478 bAll = bAll || m_nCurrentPos <= 0;
479 bAll = bAll || nCurrentPos <= 0;
480 bAll = bAll || m_nCurrentPos >= nAdjustedRowCount;
481 bAll = bAll || nCurrentPos >= nAdjustedRowCount;
482
483 if ( bAll )
484 {
485 m_nCurrentPos = nCurrentPos;
486 int i = 0;
487 while (ControlMap[i] != DbGridControlNavigationBarState::NONE)
488 SetState(ControlMap[i++]);
489 }
490 else // is in the center
491 {
492 m_nCurrentPos = nCurrentPos;
493 SetState(DbGridControlNavigationBarState::Count);
494 SetState(DbGridControlNavigationBarState::Absolute);
495 }
496}
497
498bool NavigationBar::GetState(DbGridControlNavigationBarState nWhich) const
499{
500 DbGridControl* pParent = static_cast<DbGridControl*>(GetParent());
501
502 if (!pParent->IsOpen() || pParent->IsDesignMode() || !pParent->IsEnabled()
503 || pParent->IsFilterMode() )
504 return false;
505 else
506 {
507 // check if we have a master state provider
508 if (pParent->m_aMasterStateProvider.IsSet())
509 {
510 long nState = pParent->m_aMasterStateProvider.Call( nWhich );
511 if (nState>=0)
512 return (nState>0);
513 }
514
515 bool bAvailable = true;
516
517 switch (nWhich)
518 {
519 case DbGridControlNavigationBarState::First:
520 case DbGridControlNavigationBarState::Prev:
521 bAvailable = m_nCurrentPos > 0;
522 break;
523 case DbGridControlNavigationBarState::Next:
524 if(pParent->m_bRecordCountFinal)
525 {
526 bAvailable = m_nCurrentPos < pParent->GetRowCount() - 1;
527 if (!bAvailable && pParent->GetOptions() & DbGridControlOptions::Insert)
528 bAvailable = (m_nCurrentPos == pParent->GetRowCount() - 2) && pParent->IsModified();
529 }
530 break;
531 case DbGridControlNavigationBarState::Last:
532 if(pParent->m_bRecordCountFinal)
533 {
534 if (pParent->GetOptions() & DbGridControlOptions::Insert)
535 bAvailable = pParent->IsCurrentAppending() ? pParent->GetRowCount() > 1 :
536 m_nCurrentPos != pParent->GetRowCount() - 2;
537 else
538 bAvailable = m_nCurrentPos != pParent->GetRowCount() - 1;
539 }
540 break;
541 case DbGridControlNavigationBarState::New:
542 bAvailable = (pParent->GetOptions() & DbGridControlOptions::Insert) && pParent->GetRowCount() && m_nCurrentPos < pParent->GetRowCount() - 1;
543 break;
544 case DbGridControlNavigationBarState::Absolute:
545 bAvailable = pParent->GetRowCount() > 0;
546 break;
547 default: break;
548 }
549 return bAvailable;
550 }
551}
552
553void NavigationBar::SetState(DbGridControlNavigationBarState nWhich)
554{
555 bool bAvailable = GetState(nWhich);
556 DbGridControl* pParent = static_cast<DbGridControl*>(GetParent());
557 weld::Widget* pWnd = nullptr;
558 switch (nWhich)
559 {
560 case DbGridControlNavigationBarState::First:
561 pWnd = m_xFirstBtn.get();
562 break;
563 case DbGridControlNavigationBarState::Prev:
564 pWnd = m_xPrevBtn.get();
565 break;
566 case DbGridControlNavigationBarState::Next:
567 pWnd = m_xNextBtn.get();
568 break;
569 case DbGridControlNavigationBarState::Last:
570 pWnd = m_xLastBtn.get();
571 break;
572 case DbGridControlNavigationBarState::New:
573 pWnd = m_xNewBtn.get();
574 break;
575 case DbGridControlNavigationBarState::Absolute:
576 pWnd = m_xAbsolute->GetWidget();
577 if (bAvailable)
578 m_xAbsolute->set_text(OUString::number(m_nCurrentPos + 1));
579 else
580 m_xAbsolute->set_text(OUString());
581 break;
582 case DbGridControlNavigationBarState::Text:
583 pWnd = m_xRecordText.get();
584 break;
585 case DbGridControlNavigationBarState::Of:
586 pWnd = m_xRecordOf.get();
587 break;
588 case DbGridControlNavigationBarState::Count:
589 {
590 pWnd = m_xRecordCount.get();
591 OUString aText;
592 if (bAvailable)
593 {
594 if (pParent->GetOptions() & DbGridControlOptions::Insert)
595 {
596 if (pParent->IsCurrentAppending() && !pParent->IsModified())
597 aText = OUString::number(pParent->GetRowCount());
598 else
599 aText = OUString::number(pParent->GetRowCount() - 1);
600 }
601 else
602 aText = OUString::number(pParent->GetRowCount());
603 if(!pParent->m_bRecordCountFinal)
604 aText += " *";
605 }
606 else
607 aText.clear();
608
609 // add the number of selected rows, if applicable
610 if (pParent->GetSelectRowCount())
611 {
612 OUString aExtendedInfo = aText + " (" +
613 OUString::number(pParent->GetSelectRowCount()) + ")";
614 m_xRecordCount->set_label(aExtendedInfo);
615 }
616 else
617 m_xRecordCount->set_label(aText);
618
619 pParent->SetRealRowCount(aText);
620 } break;
621 default: break;
622 }
623 DBG_ASSERT(pWnd, "no window")do { if (true && (!(pWnd))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "623" ": "), "%s", "no window"); } } while (false)
;
624 if (!(pWnd && (pWnd->get_sensitive() != bAvailable)))
625 return;
626
627 // this "pWnd->IsEnabled() != bAvailable" is a little hack : Window::Enable always generates a user
628 // event (ImplGenerateMouseMove) even if nothing happened. This may lead to some unwanted effects, so we
629 // do this check.
630 // For further explanation see Bug 69900.
631 pWnd->set_sensitive(bAvailable);
632 if (!bAvailable)
633 {
634 if (pWnd == m_xNextBtn.get())
635 m_aNextRepeat.Stop();
636 else if (pWnd == m_xPrevBtn.get())
637 m_aPrevRepeat.Stop();
638 }
639}
640
641DbGridRow::DbGridRow():m_eStatus(GridRowStatus::Clean), m_bIsNew(true)
642{}
643
644DbGridRow::DbGridRow(CursorWrapper* pCur, bool bPaintCursor)
645 :m_bIsNew(false)
646{
647
648 if (pCur && pCur->Is())
649 {
650 Reference< XIndexAccess > xColumns(pCur->getColumns(), UNO_QUERY);
651 for (sal_Int32 i = 0; i < xColumns->getCount(); ++i)
652 {
653 Reference< XPropertySet > xColSet(
654 xColumns->getByIndex(i), css::uno::UNO_QUERY);
655 m_aVariants.emplace_back( new DataColumn(xColSet) );
656 }
657
658 if (pCur->rowDeleted())
659 m_eStatus = GridRowStatus::Deleted;
660 else
661 {
662 if (bPaintCursor)
663 m_eStatus = (pCur->isAfterLast() || pCur->isBeforeFirst()) ? GridRowStatus::Invalid : GridRowStatus::Clean;
664 else
665 {
666 const Reference< XPropertySet >& xSet = pCur->getPropertySet();
667 if (xSet.is())
668 {
669 m_bIsNew = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISNEW"IsNew"));
670 if (!m_bIsNew && (pCur->isAfterLast() || pCur->isBeforeFirst()))
671 m_eStatus = GridRowStatus::Invalid;
672 else if (::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISMODIFIED"IsModified")))
673 m_eStatus = GridRowStatus::Modified;
674 else
675 m_eStatus = GridRowStatus::Clean;
676 }
677 else
678 m_eStatus = GridRowStatus::Invalid;
679 }
680 }
681 if (!m_bIsNew && IsValid())
682 m_aBookmark = pCur->getBookmark();
683 else
684 m_aBookmark = Any();
685 }
686 else
687 m_eStatus = GridRowStatus::Invalid;
688}
689
690DbGridRow::~DbGridRow()
691{
692}
693
694void DbGridRow::SetState(CursorWrapper* pCur, bool bPaintCursor)
695{
696 if (pCur && pCur->Is())
697 {
698 if (pCur->rowDeleted())
699 {
700 m_eStatus = GridRowStatus::Deleted;
701 m_bIsNew = false;
702 }
703 else
704 {
705 m_eStatus = GridRowStatus::Clean;
706 if (!bPaintCursor)
707 {
708 const Reference< XPropertySet >& xSet = pCur->getPropertySet();
709 DBG_ASSERT(xSet.is(), "DbGridRow::SetState : invalid cursor !")do { if (true && (!(xSet.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "709" ": "), "%s", "DbGridRow::SetState : invalid cursor !"
); } } while (false)
;
710
711 if (::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISMODIFIED"IsModified")))
712 m_eStatus = GridRowStatus::Modified;
713 m_bIsNew = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISNEW"IsNew"));
714 }
715 else
716 m_bIsNew = false;
717 }
718
719 try
720 {
721 if (!m_bIsNew && IsValid())
722 m_aBookmark = pCur->getBookmark();
723 else
724 m_aBookmark = Any();
725 }
726 catch(SQLException&)
727 {
728 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "728" ": ", "svx" );
;
729 m_aBookmark = Any();
730 m_eStatus = GridRowStatus::Invalid;
731 m_bIsNew = false;
732 }
733 }
734 else
735 {
736 m_aBookmark = Any();
737 m_eStatus = GridRowStatus::Invalid;
738 m_bIsNew = false;
739 }
740}
741
742DbGridControl::DbGridControl(
743 Reference< XComponentContext > const & _rxContext,
744 vcl::Window* pParent,
745 WinBits nBits)
746 :EditBrowseBox(pParent, EditBrowseBoxFlags::NONE, nBits, DEFAULT_BROWSE_MODE )
747 ,m_xContext(_rxContext)
748 ,m_aBar(VclPtr<NavigationBar>::Create(this))
749 ,m_nAsynAdjustEvent(nullptr)
750 ,m_pDataSourcePropListener(nullptr)
751 ,m_pFieldListeners(nullptr)
752 ,m_pGridListener(nullptr)
753 ,m_nSeekPos(-1)
754 ,m_nTotalCount(-1)
755 ,m_aNullDate(::dbtools::DBTypeConversion::getStandardDate())
756 ,m_nMode(DEFAULT_BROWSE_MODE)
757 ,m_nCurrentPos(-1)
758 ,m_nDeleteEvent(nullptr)
759 ,m_nOptions(DbGridControlOptions::Readonly)
760 ,m_nOptionMask(DbGridControlOptions::Insert | DbGridControlOptions::Update | DbGridControlOptions::Delete)
761 ,m_nLastColId(sal_uInt16(-1))
762 ,m_nLastRowId(-1)
763 ,m_bDesignMode(false)
764 ,m_bRecordCountFinal(false)
765 ,m_bNavigationBar(true)
766 ,m_bSynchDisplay(true)
767 ,m_bHandle(true)
768 ,m_bFilterMode(false)
769 ,m_bWantDestruction(false)
770 ,m_bPendingAdjustRows(false)
771 ,m_bHideScrollbars( false )
772 ,m_bUpdating(false)
773{
774
775 OUString sName(SvxResId(RID_STR_NAVIGATIONBARreinterpret_cast<char const *>("RID_STR_NAVIGATIONBAR" "\004"
u8"Navigation bar")
));
776 m_aBar->SetAccessibleName(sName);
777 m_aBar->Show();
778 ImplInitWindow( InitWindowFacet::All );
779}
780
781void DbGridControl::InsertHandleColumn()
782{
783 // BrowseBox has problems when painting without a handleColumn (hide it here)
784 if (HasHandle())
785 BrowseBox::InsertHandleColumn(GetDefaultColumnWidth(OUString()));
786 else
787 BrowseBox::InsertHandleColumn(0);
788}
789
790void DbGridControl::Init()
791{
792 VclPtr<BrowserHeader> pNewHeader = CreateHeaderBar(this);
793 pHeader->SetMouseTransparent(false);
794
795 SetHeaderBar(pNewHeader);
796 SetMode(m_nMode);
797 SetCursorColor(Color(0xFF, 0, 0));
798
799 InsertHandleColumn();
800}
801
802DbGridControl::~DbGridControl()
803{
804 disposeOnce();
805}
806
807void DbGridControl::dispose()
808{
809 if (!IsDisposed())
1
Assuming the condition is false
2
Taking false branch
810 {
811 RemoveColumns();
812
813 m_bWantDestruction = true;
814 osl::MutexGuard aGuard(m_aDestructionSafety);
815 if (m_pFieldListeners)
816 DisconnectFromFields();
817 m_pCursorDisposeListener.reset();
818 }
819
820 if (m_nDeleteEvent)
3
Assuming field 'm_nDeleteEvent' is null
4
Taking false branch
821 Application::RemoveUserEvent(m_nDeleteEvent);
822
823 if (m_pDataSourcePropMultiplexer.is())
5
Taking false branch
824 {
825 m_pDataSourcePropMultiplexer->dispose();
826 m_pDataSourcePropMultiplexer.clear(); // this should delete the multiplexer
827 delete m_pDataSourcePropListener;
828 m_pDataSourcePropListener = nullptr;
829 }
830 m_xRowSetListener.clear();
831
832 m_pDataCursor.reset();
833 m_pSeekCursor.reset();
834
835 m_aBar.disposeAndClear();
6
Calling 'VclPtr::disposeAndClear'
836
837 EditBrowseBox::dispose();
838}
839
840void DbGridControl::StateChanged( StateChangedType nType )
841{
842 EditBrowseBox::StateChanged( nType );
843
844 switch (nType)
845 {
846 case StateChangedType::Mirroring:
847 ImplInitWindow( InitWindowFacet::WritingMode );
848 Invalidate();
849 break;
850
851 case StateChangedType::Zoom:
852 {
853 ImplInitWindow( InitWindowFacet::Font );
854
855 // and give it a chance to rearrange
856 Point aPoint = GetControlArea().TopLeft();
857 sal_uInt16 nX = static_cast<sal_uInt16>(aPoint.X());
858 ArrangeControls(nX, static_cast<sal_uInt16>(aPoint.Y()));
859 ReserveControlArea(nX);
860 }
861 break;
862 case StateChangedType::ControlFont:
863 ImplInitWindow( InitWindowFacet::Font );
864 Invalidate();
865 break;
866 case StateChangedType::ControlForeground:
867 ImplInitWindow( InitWindowFacet::Foreground );
868 Invalidate();
869 break;
870 case StateChangedType::ControlBackground:
871 ImplInitWindow( InitWindowFacet::Background );
872 Invalidate();
873 break;
874 default:;
875 }
876}
877
878void DbGridControl::DataChanged( const DataChangedEvent& rDCEvt )
879{
880 EditBrowseBox::DataChanged( rDCEvt );
881 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS ) &&
882 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
883 {
884 ImplInitWindow( InitWindowFacet::All );
885 Invalidate();
886 }
887}
888
889void DbGridControl::Select()
890{
891 EditBrowseBox::Select();
892
893 // as the selected rows may have changed, update the according display in our navigation bar
894 m_aBar->InvalidateState(DbGridControlNavigationBarState::Count);
895
896 if (m_pGridListener)
897 m_pGridListener->selectionChanged();
898}
899
900void DbGridControl::ImplInitWindow( const InitWindowFacet _eInitWhat )
901{
902 for (auto const & pCol : m_aColumns)
903 {
904 pCol->ImplInitWindow( GetDataWindow(), _eInitWhat );
905 }
906
907 if ( _eInitWhat & InitWindowFacet::WritingMode )
908 {
909 if ( m_bNavigationBar )
910 {
911 m_aBar->EnableRTL( IsRTLEnabled() );
912 }
913 }
914
915 if ( _eInitWhat & InitWindowFacet::Font )
916 {
917 if ( m_bNavigationBar )
918 {
919 if ( IsControlFont() )
920 m_aBar->SetControlFont( GetControlFont() );
921 else
922 m_aBar->SetControlFont();
923
924 m_aBar->SetZoom( GetZoom() );
925 }
926 }
927
928 if ( !(_eInitWhat & InitWindowFacet::Background) )
929 return;
930
931 if (IsControlBackground())
932 {
933 GetDataWindow().SetBackground(GetControlBackground());
934 GetDataWindow().SetControlBackground(GetControlBackground());
935 GetDataWindow().SetFillColor(GetControlBackground());
936 }
937 else
938 {
939 GetDataWindow().SetControlBackground();
940 GetDataWindow().SetFillColor(GetFillColor());
941 }
942}
943
944void DbGridControl::RemoveRows(bool bNewCursor)
945{
946 // Did the data cursor change?
947 if (!bNewCursor)
948 {
949 m_pSeekCursor.reset();
950 m_xPaintRow = m_xDataRow = m_xEmptyRow = m_xCurrentRow = m_xSeekRow = nullptr;
951 m_nCurrentPos = m_nSeekPos = -1;
952 m_nOptions = DbGridControlOptions::Readonly;
953
954 RowRemoved(0, GetRowCount(), false);
955 m_nTotalCount = -1;
956 }
957 else
958 {
959 RemoveRows();
960 }
961}
962
963void DbGridControl::RemoveRows()
964{
965 // we're going to remove all columns and all row, so deactivate the current cell
966 if (IsEditing())
967 DeactivateCell();
968
969 // de-initialize all columns
970 // if there are columns, free all controllers
971 for (auto const & pColumn : m_aColumns)
972 pColumn->Clear();
973
974 m_pSeekCursor.reset();
975 m_pDataCursor.reset();
976
977 m_xPaintRow = m_xDataRow = m_xEmptyRow = m_xCurrentRow = m_xSeekRow = nullptr;
978 m_nCurrentPos = m_nSeekPos = m_nTotalCount = -1;
979 m_nOptions = DbGridControlOptions::Readonly;
980
981 // reset number of sentences to zero in the browser
982 EditBrowseBox::RemoveRows();
983 m_aBar->InvalidateAll(m_nCurrentPos, true);
984}
985
986void DbGridControl::ArrangeControls(sal_uInt16& nX, sal_uInt16 nY)
987{
988 // positioning of the controls
989 if (m_bNavigationBar)
990 {
991 tools::Rectangle aRect(GetControlArea());
992 m_aBar->SetPosSizePixel(Point(0, nY + 1), Size(aRect.GetSize().Width(), aRect.GetSize().Height() - 1));
993 nX = m_aBar->ArrangeControls();
994 }
995}
996
997void DbGridControl::EnableHandle(bool bEnable)
998{
999 if (m_bHandle == bEnable)
1000 return;
1001
1002 // HandleColumn is only hidden because there are a lot of problems while painting otherwise
1003 RemoveColumn( HandleColumnId );
1004 m_bHandle = bEnable;
1005 InsertHandleColumn();
1006}
1007
1008namespace
1009{
1010 bool adjustModeForScrollbars( BrowserMode& _rMode, bool _bNavigationBar, bool _bHideScrollbars )
1011 {
1012 BrowserMode nOldMode = _rMode;
1013
1014 if ( !_bNavigationBar )
1015 {
1016 _rMode &= ~BrowserMode::AUTO_HSCROLL;
1017 }
1018
1019 if ( _bHideScrollbars )
1020 {
1021 _rMode |= BrowserMode::NO_HSCROLL | BrowserMode::NO_VSCROLL;
1022 _rMode &= ~BrowserMode( BrowserMode::AUTO_HSCROLL | BrowserMode::AUTO_VSCROLL );
1023 }
1024 else
1025 {
1026 _rMode |= BrowserMode::AUTO_HSCROLL | BrowserMode::AUTO_VSCROLL;
1027 _rMode &= ~BrowserMode( BrowserMode::NO_HSCROLL | BrowserMode::NO_VSCROLL );
1028 }
1029
1030 // note: if we have a navigation bar, we always have an AUTO_HSCROLL. In particular,
1031 // _bHideScrollbars is ignored then
1032 if ( _bNavigationBar )
1033 {
1034 _rMode |= BrowserMode::AUTO_HSCROLL;
1035 _rMode &= ~BrowserMode::NO_HSCROLL;
1036 }
1037
1038 return nOldMode != _rMode;
1039 }
1040}
1041
1042void DbGridControl::EnableNavigationBar(bool bEnable)
1043{
1044 if (m_bNavigationBar == bEnable)
1045 return;
1046
1047 m_bNavigationBar = bEnable;
1048
1049 if (bEnable)
1050 {
1051 m_aBar->Show();
1052 m_aBar->Enable();
1053 m_aBar->InvalidateAll(m_nCurrentPos, true);
1054
1055 if ( adjustModeForScrollbars( m_nMode, m_bNavigationBar, m_bHideScrollbars ) )
1056 SetMode( m_nMode );
1057
1058 // get size of the reserved ControlArea
1059 Point aPoint = GetControlArea().TopLeft();
1060 sal_uInt16 nX = static_cast<sal_uInt16>(aPoint.X());
1061
1062 ArrangeControls(nX, static_cast<sal_uInt16>(aPoint.Y()));
1063 ReserveControlArea(nX);
1064 }
1065 else
1066 {
1067 m_aBar->Hide();
1068 m_aBar->Disable();
1069
1070 if ( adjustModeForScrollbars( m_nMode, m_bNavigationBar, m_bHideScrollbars ) )
1071 SetMode( m_nMode );
1072
1073 ReserveControlArea();
1074 }
1075}
1076
1077DbGridControlOptions DbGridControl::SetOptions(DbGridControlOptions nOpt)
1078{
1079 DBG_ASSERT(!m_xCurrentRow.is() || !m_xCurrentRow->IsModified(),do { if (true && (!(!m_xCurrentRow.is() || !m_xCurrentRow
->IsModified()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1080" ": "), "%s", "DbGridControl::SetOptions : please do not call when editing a record (things are much easier this way ;) !"
); } } while (false)
1080 "DbGridControl::SetOptions : please do not call when editing a record (things are much easier this way ;) !")do { if (true && (!(!m_xCurrentRow.is() || !m_xCurrentRow
->IsModified()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1080" ": "), "%s", "DbGridControl::SetOptions : please do not call when editing a record (things are much easier this way ;) !"
); } } while (false)
;
1081
1082 // for the next setDataSource (which is triggered by a refresh, for instance)
1083 m_nOptionMask = nOpt;
1084
1085 // normalize the new options
1086 Reference< XPropertySet > xDataSourceSet = m_pDataCursor->getPropertySet();
1087 if (xDataSourceSet.is())
1088 {
1089 // check what kind of options are available
1090 sal_Int32 nPrivileges = 0;
1091 xDataSourceSet->getPropertyValue(FM_PROP_PRIVILEGES"Privileges") >>= nPrivileges;
1092 if ((nPrivileges & Privilege::INSERT) == 0)
1093 nOpt &= ~DbGridControlOptions::Insert;
1094 if ((nPrivileges & Privilege::UPDATE) == 0)
1095 nOpt &= ~DbGridControlOptions::Update;
1096 if ((nPrivileges & Privilege::DELETE) == 0)
1097 nOpt &= ~DbGridControlOptions::Delete;
1098 }
1099 else
1100 nOpt = DbGridControlOptions::Readonly;
1101
1102 // need to do something after that ?
1103 if (nOpt == m_nOptions)
1104 return m_nOptions;
1105
1106 // the 'update' option only affects our BrowserMode (with or w/o focus rect)
1107 BrowserMode nNewMode = m_nMode;
1108 if (!(m_nMode & BrowserMode::CURSOR_WO_FOCUS))
1109 {
1110 if (nOpt & DbGridControlOptions::Update)
1111 nNewMode |= BrowserMode::HIDECURSOR;
1112 else
1113 nNewMode &= ~BrowserMode::HIDECURSOR;
1114 }
1115 else
1116 nNewMode &= ~BrowserMode::HIDECURSOR;
1117 // should not be necessary if EnablePermanentCursor is used to change the cursor behaviour, but to be sure ...
1118
1119 if (nNewMode != m_nMode)
1120 {
1121 SetMode(nNewMode);
1122 m_nMode = nNewMode;
1123 }
1124
1125 // _after_ setting the mode because this results in an ActivateCell
1126 DeactivateCell();
1127
1128 bool bInsertChanged = (nOpt & DbGridControlOptions::Insert) != (m_nOptions & DbGridControlOptions::Insert);
1129 m_nOptions = nOpt;
1130 // we need to set this before the code below because it indirectly uses m_nOptions
1131
1132 // the 'insert' option affects our empty row
1133 if (bInsertChanged)
1134 {
1135 if (m_nOptions & DbGridControlOptions::Insert)
1136 { // the insert option is to be set
1137 m_xEmptyRow = new DbGridRow();
1138 RowInserted(GetRowCount());
1139 }
1140 else
1141 { // the insert option is to be reset
1142 m_xEmptyRow = nullptr;
1143 if ((GetCurRow() == GetRowCount() - 1) && (GetCurRow() > 0))
1144 GoToRowColumnId(GetCurRow() - 1, GetCurColumnId());
1145 RowRemoved(GetRowCount());
1146 }
1147 }
1148
1149 // the 'delete' options has no immediate consequences
1150
1151 ActivateCell();
1152 Invalidate();
1153 return m_nOptions;
1154}
1155
1156void DbGridControl::ForceHideScrollbars()
1157{
1158 if ( m_bHideScrollbars )
1159 return;
1160
1161 m_bHideScrollbars = true;
1162
1163 if ( adjustModeForScrollbars( m_nMode, m_bNavigationBar, m_bHideScrollbars ) )
1164 SetMode( m_nMode );
1165}
1166
1167void DbGridControl::EnablePermanentCursor(bool bEnable)
1168{
1169 if (IsPermanentCursorEnabled() == bEnable)
1170 return;
1171
1172 if (bEnable)
1173 {
1174 m_nMode &= ~BrowserMode::HIDECURSOR; // without this BrowserMode::CURSOR_WO_FOCUS won't have any affect
1175 m_nMode |= BrowserMode::CURSOR_WO_FOCUS;
1176 }
1177 else
1178 {
1179 if (m_nOptions & DbGridControlOptions::Update)
1180 m_nMode |= BrowserMode::HIDECURSOR; // no cursor at all
1181 else
1182 m_nMode &= ~BrowserMode::HIDECURSOR; // at least the "non-permanent" cursor
1183
1184 m_nMode &= ~BrowserMode::CURSOR_WO_FOCUS;
1185 }
1186 SetMode(m_nMode);
1187
1188 bool bWasEditing = IsEditing();
1189 DeactivateCell();
1190 if (bWasEditing)
1191 ActivateCell();
1192}
1193
1194bool DbGridControl::IsPermanentCursorEnabled() const
1195{
1196 return (m_nMode & BrowserMode::CURSOR_WO_FOCUS) && !(m_nMode & BrowserMode::HIDECURSOR);
1197}
1198
1199void DbGridControl::refreshController(sal_uInt16 _nColId, GrantControlAccess /*_aAccess*/)
1200{
1201 if ((GetCurColumnId() == _nColId) && IsEditing())
1202 { // the controller which is currently active needs to be refreshed
1203 DeactivateCell();
1204 ActivateCell();
1205 }
1206}
1207
1208void DbGridControl::setDataSource(const Reference< XRowSet >& _xCursor, DbGridControlOptions nOpts)
1209{
1210 if (!_xCursor.is() && !m_pDataCursor)
1211 return;
1212
1213 if (m_pDataSourcePropMultiplexer.is())
1214 {
1215 m_pDataSourcePropMultiplexer->dispose();
1216 m_pDataSourcePropMultiplexer.clear(); // this should delete the multiplexer
1217 delete m_pDataSourcePropListener;
1218 m_pDataSourcePropListener = nullptr;
1219 }
1220 m_xRowSetListener.clear();
1221
1222 // is the new cursor valid ?
1223 // the cursor is only valid if it contains some columns
1224 // if there is no cursor or the cursor is not valid we have to clean up and leave
1225 if (!_xCursor.is() || !Reference< XColumnsSupplier > (_xCursor, UNO_QUERY_THROW)->getColumns()->hasElements())
1226 {
1227 RemoveRows();
1228 return;
1229 }
1230
1231 // did the data cursor change?
1232 sal_uInt16 nCurPos = GetColumnPos(GetCurColumnId());
1233
1234 SetUpdateMode(false);
1235 RemoveRows();
1236 DisconnectFromFields();
1237
1238 m_pCursorDisposeListener.reset();
1239
1240 {
1241 ::osl::MutexGuard aGuard(m_aAdjustSafety);
1242 if (m_nAsynAdjustEvent)
1243 {
1244 // the adjust was thought to work with the old cursor which we don't have anymore
1245 RemoveUserEvent(m_nAsynAdjustEvent);
1246 m_nAsynAdjustEvent = nullptr;
1247 }
1248 }
1249
1250 // get a new formatter and data cursor
1251 m_xFormatter = nullptr;
1252 Reference< css::util::XNumberFormatsSupplier > xSupplier = getNumberFormats(getConnection(_xCursor), true);
1253 if (xSupplier.is())
1254 {
1255 m_xFormatter = css::util::NumberFormatter::create(m_xContext);
1256 m_xFormatter->attachNumberFormatsSupplier(xSupplier);
1257
1258 // retrieve the datebase of the Numberformatter
1259 try
1260 {
1261 xSupplier->getNumberFormatSettings()->getPropertyValue("NullDate") >>= m_aNullDate;
1262 }
1263 catch(Exception&)
1264 {
1265 }
1266 }
1267
1268 m_pDataCursor.reset(new CursorWrapper(_xCursor));
1269
1270 // now create a cursor for painting rows
1271 // we need that cursor only if we are not in insert only mode
1272 Reference< XResultSet > xClone;
1273 Reference< XResultSetAccess > xAccess( _xCursor, UNO_QUERY );
1274 try
1275 {
1276 xClone = xAccess.is() ? xAccess->createResultSet() : Reference< XResultSet > ();
1277 }
1278 catch(Exception&)
1279 {
1280 }
1281 if (xClone.is())
1282 m_pSeekCursor.reset(new CursorWrapper(xClone));
1283
1284 // property listening on the data source
1285 // (Normally one class would be sufficient : the multiplexer which could forward the property change to us.
1286 // But for that we would have been derived from ::comphelper::OPropertyChangeListener, which isn't exported.
1287 // So we introduce a second class, which is a ::comphelper::OPropertyChangeListener (in the implementation file we know this class)
1288 // and forwards the property changes to our special method "DataSourcePropertyChanged".)
1289 if (m_pDataCursor)
1290 {
1291 m_pDataSourcePropListener = new FmXGridSourcePropListener(this);
1292 m_pDataSourcePropMultiplexer = new ::comphelper::OPropertyChangeMultiplexer(m_pDataSourcePropListener, m_pDataCursor->getPropertySet() );
1293 m_pDataSourcePropMultiplexer->addProperty(FM_PROP_ISMODIFIED"IsModified");
1294 m_pDataSourcePropMultiplexer->addProperty(FM_PROP_ISNEW"IsNew");
1295 }
1296
1297 BrowserMode nOldMode = m_nMode;
1298 if (m_pSeekCursor)
1299 {
1300 try
1301 {
1302 Reference< XPropertySet > xSet(_xCursor, UNO_QUERY);
1303 if (xSet.is())
1304 {
1305 // check what kind of options are available
1306 sal_Int32 nConcurrency = ResultSetConcurrency::READ_ONLY;
1307 xSet->getPropertyValue(FM_PROP_RESULTSET_CONCURRENCY"ResultSetConcurrency") >>= nConcurrency;
1308
1309 if ( ResultSetConcurrency::UPDATABLE == nConcurrency )
1310 {
1311 sal_Int32 nPrivileges = 0;
1312 xSet->getPropertyValue(FM_PROP_PRIVILEGES"Privileges") >>= nPrivileges;
1313
1314 // Insert Option should be set if insert only otherwise you won't see any rows
1315 // and no insertion is possible
1316 if ((m_nOptionMask & DbGridControlOptions::Insert)
1317 && ((nPrivileges & Privilege::INSERT) == Privilege::INSERT) && (nOpts & DbGridControlOptions::Insert))
1318 m_nOptions |= DbGridControlOptions::Insert;
1319 if ((m_nOptionMask & DbGridControlOptions::Update)
1320 && ((nPrivileges & Privilege::UPDATE) == Privilege::UPDATE) && (nOpts & DbGridControlOptions::Update))
1321 m_nOptions |= DbGridControlOptions::Update;
1322 if ((m_nOptionMask & DbGridControlOptions::Delete)
1323 && ((nPrivileges & Privilege::DELETE) == Privilege::DELETE) && (nOpts & DbGridControlOptions::Delete))
1324 m_nOptions |= DbGridControlOptions::Delete;
1325 }
1326 }
1327 }
1328 catch( const Exception& )
1329 {
1330 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1330" ": ", "svx" );
;
1331 }
1332
1333 bool bPermanentCursor = IsPermanentCursorEnabled();
1334 m_nMode = DEFAULT_BROWSE_MODE;
1335
1336 if ( bPermanentCursor )
1337 {
1338 m_nMode |= BrowserMode::CURSOR_WO_FOCUS;
1339 m_nMode &= ~BrowserMode::HIDECURSOR;
1340 }
1341 else
1342 {
1343 // updates are allowed -> no focus rectangle
1344 if ( m_nOptions & DbGridControlOptions::Update )
1345 m_nMode |= BrowserMode::HIDECURSOR;
1346 }
1347
1348 m_nMode |= BrowserMode::MULTISELECTION;
1349
1350 adjustModeForScrollbars( m_nMode, m_bNavigationBar, m_bHideScrollbars );
1351
1352 Reference< XColumnsSupplier > xSupplyColumns(_xCursor, UNO_QUERY);
1353 if (xSupplyColumns.is())
1354 InitColumnsByFields(Reference< XIndexAccess > (xSupplyColumns->getColumns(), UNO_QUERY));
1355
1356 ConnectToFields();
1357 }
1358
1359 sal_uInt32 nRecordCount(0);
1360
1361 if (m_pSeekCursor)
1362 {
1363 Reference< XPropertySet > xSet = m_pDataCursor->getPropertySet();
1364 xSet->getPropertyValue(FM_PROP_ROWCOUNT"RowCount") >>= nRecordCount;
1365 m_bRecordCountFinal = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ROWCOUNTFINAL"IsRowCountFinal"));
1366
1367 m_xRowSetListener = new RowSetEventListener(this);
1368 Reference< XRowsChangeBroadcaster> xChangeBroad(xSet,UNO_QUERY);
1369 if ( xChangeBroad.is( ) )
1370 xChangeBroad->addRowsChangeListener(m_xRowSetListener);
1371
1372
1373 // insert the currently known rows
1374 // and one row if we are able to insert rows
1375 if (m_nOptions & DbGridControlOptions::Insert)
1376 {
1377 // insert the empty row for insertion
1378 m_xEmptyRow = new DbGridRow();
1379 ++nRecordCount;
1380 }
1381 if (nRecordCount)
1382 {
1383 m_xPaintRow = m_xSeekRow = new DbGridRow(m_pSeekCursor.get(), true);
1384 m_xDataRow = new DbGridRow(m_pDataCursor.get(), false);
1385 RowInserted(0, nRecordCount, false);
1386
1387 if (m_xSeekRow->IsValid())
1388 try
1389 {
1390 m_nSeekPos = m_pSeekCursor->getRow() - 1;
1391 }
1392 catch( const Exception& )
1393 {
1394 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1394" ": ", "svx" );
;
1395 m_nSeekPos = -1;
1396 }
1397 }
1398 else
1399 {
1400 // no rows so we don't need a seekcursor
1401 m_pSeekCursor.reset();
1402 }
1403 }
1404
1405 // go to the old column
1406 if (nCurPos == BROWSER_INVALIDID((sal_uInt16) 0xFFFF) || nCurPos >= ColCount())
1407 nCurPos = 0;
1408
1409 // Column zero is a valid choice and guaranteed to exist,
1410 // but invisible to the user; if we have at least one
1411 // user-visible column, go to that one.
1412 if (nCurPos == 0 && ColCount() > 1)
1413 nCurPos = 1;
1414
1415 // there are rows so go to the selected current column
1416 if (nRecordCount)
1417 GoToRowColumnId(0, GetColumnId(nCurPos));
1418 // else stop the editing if necessary
1419 else if (IsEditing())
1420 DeactivateCell();
1421
1422 // now reset the mode
1423 if (m_nMode != nOldMode)
1424 SetMode(m_nMode);
1425
1426 // RecalcRows was already called while resizing
1427 if (!IsResizing() && GetRowCount())
1428 RecalcRows(GetTopRow(), GetVisibleRows(), true);
1429
1430 m_aBar->InvalidateAll(m_nCurrentPos, true);
1431 SetUpdateMode(true);
1432
1433 // start listening on the seek cursor
1434 if (m_pSeekCursor)
1435 m_pCursorDisposeListener.reset(new DisposeListenerGridBridge(*this, Reference< XComponent > (Reference< XInterface >(*m_pSeekCursor), UNO_QUERY)));
1436}
1437
1438void DbGridControl::RemoveColumns()
1439{
1440 if ( IsEditing() )
1441 DeactivateCell();
1442
1443 m_aColumns.clear();
1444
1445 EditBrowseBox::RemoveColumns();
1446}
1447
1448std::unique_ptr<DbGridColumn> DbGridControl::CreateColumn(sal_uInt16 nId)
1449{
1450 return std::unique_ptr<DbGridColumn>(new DbGridColumn(nId, *this));
1451}
1452
1453sal_uInt16 DbGridControl::AppendColumn(const OUString& rName, sal_uInt16 nWidth, sal_uInt16 nModelPos, sal_uInt16 nId)
1454{
1455 DBG_ASSERT(nId == BROWSER_INVALIDID, "DbGridControl::AppendColumn : I want to set the ID myself ...")do { if (true && (!(nId == ((sal_uInt16) 0xFFFF)))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1455" ": "), "%s", "DbGridControl::AppendColumn : I want to set the ID myself ..."
); } } while (false)
;
1456 sal_uInt16 nRealPos = nModelPos;
1457 if (nModelPos != HEADERBAR_APPEND(sal_uInt16(0xFFFF)))
1458 {
1459 // calc the view pos. we can't use our converting functions because the new column
1460 // has no VCL-representation, yet.
1461 sal_Int16 nViewPos = nModelPos;
1462 while (nModelPos--)
1463 {
1464 if ( m_aColumns[ nModelPos ]->IsHidden() )
1465 --nViewPos;
1466 }
1467 // restore nModelPos, we need it later
1468 nModelPos = nRealPos;
1469 // the position the base class gets is the view pos + 1 (because of the handle column)
1470 nRealPos = nViewPos + 1;
1471 }
1472
1473 // calculate the new id
1474 for (nId=1; (GetModelColumnPos(nId) != GRID_COLUMN_NOT_FOUND((sal_uInt16) 0xFFFF)) && size_t(nId) <= m_aColumns.size(); ++nId)
1475 ;
1476 DBG_ASSERT(GetViewColumnPos(nId) == GRID_COLUMN_NOT_FOUND, "DbGridControl::AppendColumn : inconsistent internal state !")do { if (true && (!(GetViewColumnPos(nId) == ((sal_uInt16
) 0xFFFF)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1476" ": "), "%s", "DbGridControl::AppendColumn : inconsistent internal state !"
); } } while (false)
;
1477 // my column's models say "there is no column with id nId", but the view (the base class) says "there is a column ..."
1478
1479 EditBrowseBox::AppendColumn(rName, nWidth, nRealPos, nId);
1480 if (nModelPos == HEADERBAR_APPEND(sal_uInt16(0xFFFF)))
1481 m_aColumns.push_back( CreateColumn(nId) );
1482 else
1483 m_aColumns.insert( m_aColumns.begin() + nModelPos, CreateColumn(nId) );
1484
1485 return nId;
1486}
1487
1488void DbGridControl::RemoveColumn(sal_uInt16 nId)
1489{
1490 EditBrowseBox::RemoveColumn(nId);
1491
1492 const sal_uInt16 nIndex = GetModelColumnPos(nId);
1493 if(nIndex != GRID_COLUMN_NOT_FOUND((sal_uInt16) 0xFFFF))
1494 {
1495 m_aColumns.erase( m_aColumns.begin()+nIndex );
1496 }
1497}
1498
1499void DbGridControl::ColumnMoved(sal_uInt16 nId)
1500{
1501 EditBrowseBox::ColumnMoved(nId);
1502
1503 // remove the col from the model
1504 sal_uInt16 nOldModelPos = GetModelColumnPos(nId);
1505#ifdef DBG_UTIL
1506 DbGridColumn* pCol = m_aColumns[ nOldModelPos ].get();
1507 DBG_ASSERT(!pCol->IsHidden(), "DbGridControl::ColumnMoved : moved a hidden col ? how this ?")do { if (true && (!(!pCol->IsHidden()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1507" ": "), "%s", "DbGridControl::ColumnMoved : moved a hidden col ? how this ?"
); } } while (false)
;
1508#endif
1509
1510 // for the new model pos we can't use GetModelColumnPos because we are altering the model at the moment
1511 // so the method won't work (in fact it would return the old model pos)
1512
1513 // the new view pos is calculated easily
1514 sal_uInt16 nNewViewPos = GetViewColumnPos(nId);
1515
1516 // from that we can compute the new model pos
1517 size_t nNewModelPos;
1518 for (nNewModelPos = 0; nNewModelPos < m_aColumns.size(); ++nNewModelPos)
1519 {
1520 if (!m_aColumns[ nNewModelPos ]->IsHidden())
1521 {
1522 if (!nNewViewPos)
1523 break;
1524 else
1525 --nNewViewPos;
1526 }
1527 }
1528 DBG_ASSERT( nNewModelPos < m_aColumns.size(), "DbGridControl::ColumnMoved : could not find the new model position !")do { if (true && (!(nNewModelPos < m_aColumns.size
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1528" ": "), "%s", "DbGridControl::ColumnMoved : could not find the new model position !"
); } } while (false)
;
1529
1530 // this will work. of course the model isn't fully consistent with our view right now, but let's
1531 // look at the situation : a column has been moved with in the VIEW from pos m to n, say m<n (in the
1532 // other case we can use analogue arguments).
1533 // All cols k with m<k<=n have been shifted left on pos, the former col m now has pos n.
1534 // In the model this affects a range of cols x to y, where x<=m and y<=n. And the number of hidden cols
1535 // within this range is constant, so we may calculate the view pos from the model pos in the above way.
1536
1537 // for instance, let's look at a grid with six columns where the third one is hidden. this will
1538 // initially look like this :
1539
1540 // +---+---+---+---+---+---+
1541 // model pos | 0 | 1 |*2*| 3 | 4 | 5 |
1542 // +---+---+---+---+---+---+
1543 // ID | 1 | 2 | 3 | 4 | 5 | 6 |
1544 // +---+---+---+---+---+---+
1545 // view pos | 0 | 1 | - | 2 | 3 | 4 |
1546 // +---+---+---+---+---+---+
1547
1548 // if we move the column at (view) pos 1 to (view) pos 3 we have :
1549
1550 // +---+---+---+---+---+---+
1551 // model pos | 0 | 3 |*2*| 4 | 1 | 5 | // not reflecting the changes, yet
1552 // +---+---+---+---+---+---+
1553 // ID | 1 | 4 | 3 | 5 | 2 | 6 | // already reflecting the changes
1554 // +---+---+---+---+---+---+
1555 // view pos | 0 | 1 | - | 2 | 3 | 4 |
1556 // +---+---+---+---+---+---+
1557
1558 // or, sorted by the out-of-date model positions :
1559
1560 // +---+---+---+---+---+---+
1561 // model pos | 0 | 1 |*2*| 3 | 4 | 5 |
1562 // +---+---+---+---+---+---+
1563 // ID | 1 | 2 | 3 | 4 | 5 | 6 |
1564 // +---+---+---+---+---+---+
1565 // view pos | 0 | 3 | - | 1 | 2 | 4 |
1566 // +---+---+---+---+---+---+
1567
1568 // We know the new view pos (3) of the moved column because our base class tells us. So we look at our
1569 // model for the 4th (the pos is zero-based) visible column, it is at (model) position 4. And this is
1570 // exactly the pos where we have to re-insert our column's model, so it looks ike this :
1571
1572 // +---+---+---+---+---+---+
1573 // model pos | 0 |*1*| 2 | 3 | 4 | 5 |
1574 // +---+---+---+---+---+---+
1575 // ID | 1 | 3 | 4 | 5 | 2 | 6 |
1576 // +---+---+---+---+---+---+
1577 // view pos | 0 | - | 1 | 2 | 3 | 4 |
1578 // +---+---+---+---+---+---+
1579
1580 // Now, all is consistent again.
1581 // (except of the hidden column : The cycling of the cols occurred on the model, not on the view. maybe
1582 // the user expected the latter but there really is no good argument against our method ;) ...)
1583
1584 // And no, this large explanation isn't just because I wanted to play a board game or something like
1585 // that. It's because it took me a while to see it myself, and the whole theme (hidden cols, model col
1586 // positions, view col positions) is really painful (at least for me) so the above pictures helped me a lot ;)
1587
1588 auto temp = std::move(m_aColumns[ nOldModelPos ]);
1589 m_aColumns.erase( m_aColumns.begin() + nOldModelPos );
1590 m_aColumns.insert( m_aColumns.begin() + nNewModelPos, std::move(temp) );
1591}
1592
1593bool DbGridControl::SeekRow(long nRow)
1594{
1595 // in filter mode or in insert only mode we don't have any cursor!
1596 if ( !SeekCursor( nRow ) )
1597 return false;
1598
1599 if ( IsFilterMode() )
1600 {
1601 DBG_ASSERT( IsFilterRow( nRow ), "DbGridControl::SeekRow(): No filter row, wrong mode" )do { if (true && (!(IsFilterRow( nRow )))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1601" ": "), "%s", "DbGridControl::SeekRow(): No filter row, wrong mode"
); } } while (false)
;
1602 m_xPaintRow = m_xEmptyRow;
1603 }
1604 else
1605 {
1606 // on the current position we have to take the current row for display as we want
1607 // to have the most recent values for display
1608 if ( ( nRow == m_nCurrentPos ) && getDisplaySynchron() )
1609 m_xPaintRow = m_xCurrentRow;
1610 // seek to the empty insert row
1611 else if ( IsInsertionRow( nRow ) )
1612 m_xPaintRow = m_xEmptyRow;
1613 else
1614 {
1615 m_xSeekRow->SetState( m_pSeekCursor.get(), true );
1616 m_xPaintRow = m_xSeekRow;
1617 }
1618 }
1619
1620 EditBrowseBox::SeekRow(nRow);
1621
1622 return m_nSeekPos >= 0;
1623}
1624
1625// Is called whenever the visible amount of data changes
1626void DbGridControl::VisibleRowsChanged( long nNewTopRow, sal_uInt16 nLinesOnScreen )
1627{
1628 RecalcRows(nNewTopRow, nLinesOnScreen, false);
1629}
1630
1631void DbGridControl::RecalcRows(long nNewTopRow, sal_uInt16 nLinesOnScreen, bool bUpdateCursor)
1632{
1633 // If no cursor -> no rows in the browser.
1634 if (!m_pSeekCursor)
1635 {
1636 DBG_ASSERT(GetRowCount() == 0,"DbGridControl: without cursor no rows are allowed to be there")do { if (true && (!(GetRowCount() == 0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1636" ": "), "%s", "DbGridControl: without cursor no rows are allowed to be there"
); } } while (false)
;
1637 return;
1638 }
1639
1640 // ignore any implicitly made updates
1641 bool bDisablePaint = !bUpdateCursor && IsPaintEnabled();
1642 if (bDisablePaint)
1643 EnablePaint(false);
1644
1645 // adjust cache to the visible area
1646 Reference< XPropertySet > xSet = m_pSeekCursor->getPropertySet();
1647 sal_Int32 nCacheSize = 0;
1648 xSet->getPropertyValue(FM_PROP_FETCHSIZE"FetchSize") >>= nCacheSize;
1649 bool bCacheAligned = false;
1650 // no further cursor movements after initializing (m_nSeekPos < 0) because it is already
1651 // positioned on the first sentence
1652 long nDelta = nNewTopRow - GetTopRow();
1653 // limit for relative positioning
1654 long nLimit = nCacheSize ? nCacheSize / 2 : 0;
1655
1656 // more lines on screen than in cache
1657 if (nLimit < nLinesOnScreen)
1658 {
1659 Any aCacheSize;
1660 aCacheSize <<= sal_Int32(nLinesOnScreen*2);
1661 xSet->setPropertyValue(FM_PROP_FETCHSIZE"FetchSize", aCacheSize);
1662 // here we need to update the cursor for sure
1663 bUpdateCursor = true;
1664 bCacheAligned = true;
1665 nLimit = nLinesOnScreen;
1666 }
1667
1668 // In the following, all positionings are done as it is
1669 // ensured that there are enough lines in the data cache
1670
1671 // window goes downwards with less than two windows difference or
1672 // the cache was updated and no rowcount yet
1673 if (nDelta < nLimit && (nDelta > 0
1674 || (bCacheAligned && m_nTotalCount < 0)) )
1675 SeekCursor(nNewTopRow + nLinesOnScreen - 1);
1676 else if (nDelta < 0 && std::abs(nDelta) < nLimit)
1677 SeekCursor(nNewTopRow);
1678 else if (nDelta != 0 || bUpdateCursor)
1679 SeekCursor(nNewTopRow, true);
1680
1681 AdjustRows();
1682
1683 // ignore any updates implicit made
1684 EnablePaint(true);
1685}
1686
1687void DbGridControl::RowInserted(long nRow, long nNumRows, bool bDoPaint)
1688{
1689 if (!nNumRows)
1690 return;
1691
1692 if (m_bRecordCountFinal && m_nTotalCount < 0)
1693 {
1694 // if we have an insert row we have to reduce to count by 1
1695 // as the total count reflects only the existing rows in database
1696 m_nTotalCount = GetRowCount() + nNumRows;
1697 if (m_xEmptyRow.is())
1698 --m_nTotalCount;
1699 }
1700 else if (m_nTotalCount >= 0)
1701 m_nTotalCount += nNumRows;
1702
1703 EditBrowseBox::RowInserted(nRow, nNumRows, bDoPaint);
1704 m_aBar->InvalidateState(DbGridControlNavigationBarState::Count);
1705}
1706
1707void DbGridControl::RowRemoved(long nRow, long nNumRows, bool bDoPaint)
1708{
1709 if (!nNumRows)
1710 return;
1711
1712 if (m_bRecordCountFinal && m_nTotalCount < 0)
1713 {
1714 m_nTotalCount = GetRowCount() - nNumRows;
1715 // if we have an insert row reduce by 1
1716 if (m_xEmptyRow.is())
1717 --m_nTotalCount;
1718 }
1719 else if (m_nTotalCount >= 0)
1720 m_nTotalCount -= nNumRows;
1721
1722 EditBrowseBox::RowRemoved(nRow, nNumRows, bDoPaint);
1723 m_aBar->InvalidateState(DbGridControlNavigationBarState::Count);
1724}
1725
1726void DbGridControl::AdjustRows()
1727{
1728 if (!m_pSeekCursor)
1729 return;
1730
1731 Reference< XPropertySet > xSet = m_pDataCursor->getPropertySet();
1732
1733 // refresh RecordCount
1734 sal_Int32 nRecordCount = 0;
1735 xSet->getPropertyValue(FM_PROP_ROWCOUNT"RowCount") >>= nRecordCount;
1736 if (!m_bRecordCountFinal)
1737 m_bRecordCountFinal = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ROWCOUNTFINAL"IsRowCountFinal"));
1738
1739 // Did the number of rows change?
1740 // Here we need to consider that there might be an additional row for adding new data sets
1741
1742 // add additional AppendRow for insertion
1743 if (m_nOptions & DbGridControlOptions::Insert)
1744 ++nRecordCount;
1745
1746 // If there is currently an insertion, so do not consider this added row in RecordCount or Appendrow
1747 if (!IsUpdating() && m_bRecordCountFinal && IsModified() && m_xCurrentRow != m_xEmptyRow &&
1748 m_xCurrentRow->IsNew())
1749 ++nRecordCount;
1750 // ensured with !m_bUpdating: otherwise the edited data set (that SaveRow added and why this
1751 // method was called) would be called twice (if m_bUpdating == sal_True): once in RecordCount
1752 // and a second time here (60787 - FS)
1753
1754 if (nRecordCount != GetRowCount())
1755 {
1756 long nDelta = GetRowCount() - static_cast<long>(nRecordCount);
1757 if (nDelta > 0) // too many
1758 {
1759 RowRemoved(GetRowCount() - nDelta, nDelta, false);
1760 // some rows are gone, thus, repaint starting at the current position
1761 Invalidate();
1762
1763 sal_Int32 nNewPos = AlignSeekCursor();
1764 if (m_bSynchDisplay)
1765 EditBrowseBox::GoToRow(nNewPos);
1766
1767 SetCurrent(nNewPos);
1768 // there are rows so go to the selected current column
1769 if (nRecordCount)
1770 GoToRowColumnId(nNewPos, GetColumnId(GetCurColumnId()));
1771 if (!IsResizing() && GetRowCount())
1772 RecalcRows(GetTopRow(), GetVisibleRows(), true);
1773 m_aBar->InvalidateAll(m_nCurrentPos, true);
1774 }
1775 else // too few
1776 RowInserted(GetRowCount(), -nDelta);
1777 }
1778
1779 if (m_bRecordCountFinal && m_nTotalCount < 0)
1780 {
1781 if (m_nOptions & DbGridControlOptions::Insert)
1782 m_nTotalCount = GetRowCount() - 1;
1783 else
1784 m_nTotalCount = GetRowCount();
1785 }
1786 m_aBar->InvalidateState(DbGridControlNavigationBarState::Count);
1787}
1788
1789svt::EditBrowseBox::RowStatus DbGridControl::GetRowStatus(long nRow) const
1790{
1791 if (IsFilterRow(nRow))
1792 return EditBrowseBox::FILTER;
1793 else if (m_nCurrentPos >= 0 && nRow == m_nCurrentPos)
1794 {
1795 // new row
1796 if (!IsValid(m_xCurrentRow))
1797 return EditBrowseBox::DELETED;
1798 else if (IsModified())
1799 return EditBrowseBox::MODIFIED;
1800 else if (m_xCurrentRow->IsNew())
1801 return EditBrowseBox::CURRENTNEW;
1802 else
1803 return EditBrowseBox::CURRENT;
1804 }
1805 else if (IsInsertionRow(nRow))
1806 return EditBrowseBox::NEW;
1807 else if (!IsValid(m_xSeekRow))
1808 return EditBrowseBox::DELETED;
1809 else
1810 return EditBrowseBox::CLEAN;
1811}
1812
1813void DbGridControl::PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColumnId) const
1814{
1815 if (!IsValid(m_xPaintRow))
1816 return;
1817
1818 size_t Location = GetModelColumnPos(nColumnId);
1819 DbGridColumn* pColumn = (Location < m_aColumns.size() ) ? m_aColumns[ Location ].get() : nullptr;
1820 if (pColumn)
1821 {
1822 tools::Rectangle aArea(rRect);
1823 if ((GetMode() & BrowserMode::CURSOR_WO_FOCUS) == BrowserMode::CURSOR_WO_FOCUS)
1824 {
1825 aArea.AdjustTop(1 );
1826 aArea.AdjustBottom( -1 );
1827 }
1828 pColumn->Paint(rDev, aArea, m_xPaintRow.get(), getNumberFormatter());
1829 }
1830}
1831
1832bool DbGridControl::CursorMoving(long nNewRow, sal_uInt16 nNewCol)
1833{
1834
1835 DeactivateCell( false );
1836
1837 if ( m_pDataCursor
1838 && ( m_nCurrentPos != nNewRow )
1839 && !SetCurrent( nNewRow )
1840 )
1841 {
1842 ActivateCell();
1843 return false;
1844 }
1845
1846 return EditBrowseBox::CursorMoving( nNewRow, nNewCol );
1847}
1848
1849bool DbGridControl::SetCurrent(long nNewRow)
1850{
1851 // Each movement of the datacursor must start with BeginCursorAction and end with
1852 // EndCursorAction to block all notifications during the movement
1853 BeginCursorAction();
1854
1855 try
1856 {
1857 // compare positions
1858 if (SeekCursor(nNewRow))
1859 {
1860 if (IsFilterRow(nNewRow)) // special mode for filtering
1861 {
1862 m_xCurrentRow = m_xDataRow = m_xPaintRow = m_xEmptyRow;
1863 m_nCurrentPos = nNewRow;
1864 }
1865 else
1866 {
1867 bool bNewRowInserted = false;
1868 // Should we go to the insertrow ?
1869 if (IsInsertionRow(nNewRow))
1870 {
1871 // to we need to move the cursor to the insert row?
1872 // we need to insert the if the current row isn't the insert row or if the
1873 // cursor triggered the move by itself and we need a reinitialization of the row
1874 Reference< XPropertySet > xCursorProps = m_pDataCursor->getPropertySet();
1875 if ( !::comphelper::getBOOL(xCursorProps->getPropertyValue(FM_PROP_ISNEW"IsNew")) )
1876 {
1877 Reference< XResultSetUpdate > xUpdateCursor(Reference< XInterface >(*m_pDataCursor), UNO_QUERY);
1878 xUpdateCursor->moveToInsertRow();
1879 }
1880 bNewRowInserted = true;
1881 }
1882 else
1883 {
1884
1885 if ( !m_pSeekCursor->isBeforeFirst() && !m_pSeekCursor->isAfterLast() )
1886 {
1887 Any aBookmark = m_pSeekCursor->getBookmark();
1888 if (!m_xCurrentRow.is() || m_xCurrentRow->IsNew() || !CompareBookmark(aBookmark, m_pDataCursor->getBookmark()))
1889 {
1890 // adjust the cursor to the new desired row
1891 if (!m_pDataCursor->moveToBookmark(aBookmark))
1892 {
1893 EndCursorAction();
1894 return false;
1895 }
1896 }
1897 }
1898 }
1899 m_xDataRow->SetState(m_pDataCursor.get(), false);
1900 m_xCurrentRow = m_xDataRow;
1901
1902 long nPaintPos = -1;
1903 // do we have to repaint the last regular row in case of setting defaults or autovalues
1904 if (m_nCurrentPos >= 0 && m_nCurrentPos >= (GetRowCount() - 2))
1905 nPaintPos = m_nCurrentPos;
1906
1907 m_nCurrentPos = nNewRow;
1908
1909 // repaint the new row to display all defaults
1910 if (bNewRowInserted)
1911 RowModified(m_nCurrentPos);
1912 if (nPaintPos >= 0)
1913 RowModified(nPaintPos);
1914 }
1915 }
1916 else
1917 {
1918 OSL_FAIL("DbGridControl::SetCurrent : SeekRow failed !")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1918" ": "), "%s", "DbGridControl::SetCurrent : SeekRow failed !"
); } } while (false)
;
1919 EndCursorAction();
1920 return false;
1921 }
1922 }
1923 catch ( const Exception& )
1924 {
1925 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1925" ": ", "svx" );
;
1926 EndCursorAction();
1927 return false;
1928 }
1929
1930 EndCursorAction();
1931 return true;
1932}
1933
1934void DbGridControl::CursorMoved()
1935{
1936
1937 // cursor movement due to deletion or insertion of rows
1938 if (m_pDataCursor && m_nCurrentPos != GetCurRow())
1939 {
1940 DeactivateCell();
1941 SetCurrent(GetCurRow());
1942 }
1943
1944 EditBrowseBox::CursorMoved();
1945 m_aBar->InvalidateAll(m_nCurrentPos);
1946
1947 // select the new column when they moved
1948 if ( IsDesignMode() && GetSelectedColumnCount() > 0 && GetCurColumnId() )
1949 {
1950 SelectColumnId( GetCurColumnId() );
1951 }
1952
1953 if ( m_nLastColId != GetCurColumnId() )
1954 onColumnChange();
1955 m_nLastColId = GetCurColumnId();
1956
1957 if ( m_nLastRowId != GetCurRow() )
1958 onRowChange();
1959 m_nLastRowId = GetCurRow();
1960}
1961
1962void DbGridControl::onRowChange()
1963{
1964 // not interested in
1965}
1966
1967void DbGridControl::onColumnChange()
1968{
1969 if ( m_pGridListener )
1970 m_pGridListener->columnChanged();
1971}
1972
1973void DbGridControl::setDisplaySynchron(bool bSync)
1974{
1975 if (bSync != m_bSynchDisplay)
1976 {
1977 m_bSynchDisplay = bSync;
1978 if (m_bSynchDisplay)
1979 AdjustDataSource();
1980 }
1981}
1982
1983void DbGridControl::AdjustDataSource(bool bFull)
1984{
1985 SAL_INFO("svx.fmcomp", "DbGridControl::AdjustDataSource")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "DbGridControl::AdjustDataSource"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1985" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::AdjustDataSource"), 0
); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "DbGridControl::AdjustDataSource"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1985" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "DbGridControl::AdjustDataSource") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1985" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::AdjustDataSource"), 0
); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "DbGridControl::AdjustDataSource"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "1985" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1986 SolarMutexGuard aGuard;
1987 // If the current row is recalculated at the moment, do not adjust
1988
1989 if (bFull)
1990 m_xCurrentRow = nullptr;
1991 // if we are on the same row only repaint
1992 // but this is only possible for rows which are not inserted, in that case the comparison result
1993 // may not be correct
1994 else
1995 if ( m_xCurrentRow.is()
1996 && !m_xCurrentRow->IsNew()
1997 && !m_pDataCursor->isBeforeFirst()
1998 && !m_pDataCursor->isAfterLast()
1999 && !m_pDataCursor->rowDeleted()
2000 )
2001 {
2002 bool bEqualBookmarks = CompareBookmark( m_xCurrentRow->GetBookmark(), m_pDataCursor->getBookmark() );
2003
2004 bool bDataCursorIsOnNew = false;
2005 m_pDataCursor->getPropertySet()->getPropertyValue( FM_PROP_ISNEW"IsNew" ) >>= bDataCursorIsOnNew;
2006
2007 if ( bEqualBookmarks && !bDataCursorIsOnNew )
2008 {
2009 // position of my data cursor is the same as the position our current row points tpo
2010 // sync the status, repaint, done
2011 DBG_ASSERT(m_xDataRow == m_xCurrentRow, "Errors in the data row")do { if (true && (!(m_xDataRow == m_xCurrentRow))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2011" ": "), "%s", "Errors in the data row"); } } while
(false)
;
2012 SAL_INFO("svx.fmcomp", "same position, new state: " << ROWSTATUS(m_xCurrentRow))do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "same position, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), (
"svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2012" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "same position, new state: " <<
(!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus(
) == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "same position, new state: " << (!m_xCurrentRow
.is() ? "NULL" : m_xCurrentRow->GetStatus() == GridRowStatus
::Clean ? "CLEAN" : m_xCurrentRow->GetStatus() == GridRowStatus
::Modified ? "MODIFIED" : m_xCurrentRow->GetStatus() == GridRowStatus
::Deleted ? "DELETED" : "INVALID"); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2012" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "same position, new state: " << (!m_xCurrentRow
.is() ? "NULL" : m_xCurrentRow->GetStatus() == GridRowStatus
::Clean ? "CLEAN" : m_xCurrentRow->GetStatus() == GridRowStatus
::Modified ? "MODIFIED" : m_xCurrentRow->GetStatus() == GridRowStatus
::Deleted ? "DELETED" : "INVALID")) == 1) { ::sal_detail_log(
(::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2012" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "same position, new state: " <<
(!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus(
) == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "same position, new state: " << (!m_xCurrentRow
.is() ? "NULL" : m_xCurrentRow->GetStatus() == GridRowStatus
::Clean ? "CLEAN" : m_xCurrentRow->GetStatus() == GridRowStatus
::Modified ? "MODIFIED" : m_xCurrentRow->GetStatus() == GridRowStatus
::Deleted ? "DELETED" : "INVALID"); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2012" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2013 RowModified(m_nCurrentPos);
2014 return;
2015 }
2016 }
2017
2018 // away from the data cursor's row
2019 if (m_xPaintRow == m_xCurrentRow)
2020 m_xPaintRow = m_xSeekRow;
2021
2022 // not up-to-date row, thus, adjust completely
2023 if (!m_xCurrentRow.is())
2024 AdjustRows();
2025
2026 sal_Int32 nNewPos = AlignSeekCursor();
2027 if (nNewPos < 0)// could not find any position
2028 return;
2029
2030 if (nNewPos != m_nCurrentPos)
2031 {
2032 if (m_bSynchDisplay)
2033 EditBrowseBox::GoToRow(nNewPos);
2034
2035 if (!m_xCurrentRow.is())
2036 // Happens e.g. when deleting the n last datasets (n>1) while the cursor was positioned
2037 // on the last one. In this case, AdjustRows deletes two rows from BrowseBox, by what
2038 // CurrentRow is corrected to point two rows down, so that GoToRow will point into
2039 // emptiness (since we are - purportedly - at the correct position)
2040 SetCurrent(nNewPos);
2041 }
2042 else
2043 {
2044 SetCurrent(nNewPos);
2045 RowModified(nNewPos);
2046 }
2047
2048 // if the data cursor was moved from outside, this section is voided
2049 SetNoSelection();
2050 m_aBar->InvalidateAll(m_nCurrentPos, m_xCurrentRow.is());
2051}
2052
2053sal_Int32 DbGridControl::AlignSeekCursor()
2054{
2055 // position SeekCursor onto the data cursor, no data transmission
2056
2057 if (!m_pSeekCursor)
2058 return -1;
2059
2060 Reference< XPropertySet > xSet = m_pDataCursor->getPropertySet();
2061
2062 // now align the seek cursor and the data cursor
2063 if (::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISNEW"IsNew")))
2064 m_nSeekPos = GetRowCount() - 1;
2065 else
2066 {
2067 try
2068 {
2069 if ( m_pDataCursor->isBeforeFirst() )
2070 {
2071 // this is somewhat strange, but can nevertheless happen
2072 SAL_INFO( "svx.fmcomp", "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (before first)!" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (before first)!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2072" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (before first)!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (before first)!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2072" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (before first)!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2072" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (before first)!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (before first)!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2072" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2073 m_pSeekCursor->first();
2074 m_pSeekCursor->previous();
2075 m_nSeekPos = -1;
2076 }
2077 else if ( m_pDataCursor->isAfterLast() )
2078 {
2079 SAL_INFO( "svx.fmcomp", "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (after last)!" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (after last)!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2079" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (after last)!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (after last)!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2079" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (after last)!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2079" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (after last)!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (after last)!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2079" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2080 m_pSeekCursor->last();
2081 m_pSeekCursor->next();
2082 m_nSeekPos = -1;
2083 }
2084 else
2085 {
2086 m_pSeekCursor->moveToBookmark(m_pDataCursor->getBookmark());
2087 if (!CompareBookmark(m_pDataCursor->getBookmark(), m_pSeekCursor->getBookmark()))
2088 // unfortunately, moveToBookmark might lead to a re-positioning of the seek
2089 // cursor (if the complex moveToBookmark with all its events fires an update
2090 // somewhere) -> retry
2091 m_pSeekCursor->moveToBookmark(m_pDataCursor->getBookmark());
2092 // Now there is still the chance of a failure but it is less likely.
2093 // The alternative would be a loop until everything is fine - no good solution...
2094 m_nSeekPos = m_pSeekCursor->getRow() - 1;
2095 }
2096 }
2097 catch(Exception&)
2098 {
2099 }
2100 }
2101 return m_nSeekPos;
2102}
2103
2104bool DbGridControl::SeekCursor(long nRow, bool bAbsolute)
2105{
2106 // position SeekCursor onto the data cursor, no data transmission
2107
2108 // additions for the filtermode
2109 if (IsFilterRow(nRow))
2110 {
2111 m_nSeekPos = 0;
2112 return true;
2113 }
2114
2115 if (!m_pSeekCursor)
2116 return false;
2117
2118 // is this an insertion?
2119 if (IsValid(m_xCurrentRow) && m_xCurrentRow->IsNew() &&
2120 nRow >= m_nCurrentPos)
2121 {
2122 // if so, scrolling down must be prevented as this is already the last data set!
2123 if (nRow == m_nCurrentPos)
2124 {
2125 // no adjustment necessary
2126 m_nSeekPos = nRow;
2127 }
2128 else if (IsInsertionRow(nRow)) // blank row for data insertion
2129 m_nSeekPos = nRow;
2130 }
2131 else if (IsInsertionRow(nRow)) // blank row for data insertion
2132 m_nSeekPos = nRow;
2133 else if ((-1 == nRow) && (GetRowCount() == ((m_nOptions & DbGridControlOptions::Insert) ? 1 : 0)) && m_pSeekCursor->isAfterLast())
2134 m_nSeekPos = nRow;
2135 else
2136 {
2137 bool bSuccess = false;
2138 long nSteps = 0;
2139 try
2140 {
2141 if ( m_pSeekCursor->rowDeleted() )
2142 {
2143 // somebody deleted the current row of the seek cursor. Move it away from this row.
2144 m_pSeekCursor->next();
2145 if ( m_pSeekCursor->isAfterLast() || m_pSeekCursor->isBeforeFirst() )
2146 bAbsolute = true;
2147 }
2148
2149 if ( !bAbsolute )
2150 {
2151 DBG_ASSERT( !m_pSeekCursor->isAfterLast() && !m_pSeekCursor->isBeforeFirst(),do { if (true && (!(!m_pSeekCursor->isAfterLast() &&
!m_pSeekCursor->isBeforeFirst()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2152" ": "), "%s", "DbGridControl::SeekCursor: how did the seek cursor get to this position?!"
); } } while (false)
2152 "DbGridControl::SeekCursor: how did the seek cursor get to this position?!" )do { if (true && (!(!m_pSeekCursor->isAfterLast() &&
!m_pSeekCursor->isBeforeFirst()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2152" ": "), "%s", "DbGridControl::SeekCursor: how did the seek cursor get to this position?!"
); } } while (false)
;
2153 nSteps = nRow - (m_pSeekCursor->getRow() - 1);
2154 bAbsolute = std::abs(nSteps) > 100;
2155 }
2156
2157 if ( bAbsolute )
2158 {
2159 bSuccess = m_pSeekCursor->absolute(nRow + 1);
2160 if (bSuccess)
2161 m_nSeekPos = nRow;
2162 }
2163 else
2164 {
2165 if (nSteps > 0) // position onto the last needed data set
2166 {
2167 if (m_pSeekCursor->isAfterLast())
2168 bSuccess = false;
2169 else if (m_pSeekCursor->isBeforeFirst())
2170 bSuccess = m_pSeekCursor->absolute(nSteps);
2171 else
2172 bSuccess = m_pSeekCursor->relative(nSteps);
2173 }
2174 else if (nSteps < 0)
2175 {
2176 if (m_pSeekCursor->isBeforeFirst())
2177 bSuccess = false;
2178 else if (m_pSeekCursor->isAfterLast())
2179 bSuccess = m_pSeekCursor->absolute(nSteps);
2180 else
2181 bSuccess = m_pSeekCursor->relative(nSteps);
2182 }
2183 else
2184 {
2185 m_nSeekPos = nRow;
2186 return true;
2187 }
2188 }
2189 }
2190 catch(Exception&)
2191 {
2192 OSL_FAIL("DbGridControl::SeekCursor : failed ...")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2192" ": "), "%s", "DbGridControl::SeekCursor : failed ..."
); } } while (false)
;
2193 }
2194
2195 try
2196 {
2197 if (!bSuccess)
2198 {
2199 if (bAbsolute || nSteps > 0)
2200 {
2201 if (m_pSeekCursor->isLast())
2202 bSuccess = true;
2203 else
2204 bSuccess = m_pSeekCursor->last();
2205 }
2206 else
2207 {
2208 if (m_pSeekCursor->isFirst())
2209 bSuccess = true;
2210 else
2211 bSuccess = m_pSeekCursor->first();
2212 }
2213 }
2214
2215 if (bSuccess)
2216 m_nSeekPos = m_pSeekCursor->getRow() - 1;
2217 else
2218 m_nSeekPos = -1;
2219 }
2220 catch(Exception&)
2221 {
2222 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2222" ": ", "svx" );
;
2223 OSL_FAIL("DbGridControl::SeekCursor : failed ...")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2223" ": "), "%s", "DbGridControl::SeekCursor : failed ..."
); } } while (false)
;
2224 m_nSeekPos = -1; // no further data set available
2225 }
2226 }
2227 return m_nSeekPos == nRow;
2228}
2229
2230void DbGridControl::MoveToFirst()
2231{
2232 if (m_pSeekCursor && (GetCurRow() != 0))
2233 MoveToPosition(0);
2234}
2235
2236void DbGridControl::MoveToLast()
2237{
2238 if (!m_pSeekCursor)
2239 return;
2240
2241 if (m_nTotalCount < 0) // no RecordCount, yet
2242 {
2243 try
2244 {
2245 bool bRes = m_pSeekCursor->last();
2246
2247 if (bRes)
2248 {
2249 m_nSeekPos = m_pSeekCursor->getRow() - 1;
2250 AdjustRows();
2251 }
2252 }
2253 catch(Exception&)
2254 {
2255 }
2256 }
2257
2258 // position onto the last data set not on a blank row
2259 if (m_nOptions & DbGridControlOptions::Insert)
2260 {
2261 if ((GetRowCount() - 1) > 0)
2262 MoveToPosition(GetRowCount() - 2);
2263 }
2264 else if (GetRowCount())
2265 MoveToPosition(GetRowCount() - 1);
2266}
2267
2268void DbGridControl::MoveToPrev()
2269{
2270 long nNewRow = std::max(GetCurRow() - 1, 0L);
2271 if (GetCurRow() != nNewRow)
2272 MoveToPosition(nNewRow);
2273}
2274
2275void DbGridControl::MoveToNext()
2276{
2277 if (!m_pSeekCursor)
2278 return;
2279
2280 if (m_nTotalCount > 0)
2281 {
2282 // move the data cursor to the right position
2283 long nNewRow = std::min(GetRowCount() - 1, GetCurRow() + 1);
2284 if (GetCurRow() != nNewRow)
2285 MoveToPosition(nNewRow);
2286 }
2287 else
2288 {
2289 bool bOk = false;
2290 try
2291 {
2292 // try to move to next row
2293 // when not possible our paint cursor is already on the last row
2294 // then we must be sure that the data cursor is on the position
2295 // we call ourself again
2296 bOk = m_pSeekCursor->next();
2297 if (bOk)
2298 {
2299 m_nSeekPos = m_pSeekCursor->getRow() - 1;
2300 MoveToPosition(GetCurRow() + 1);
2301 }
2302 }
2303 catch(SQLException &)
2304 {
2305 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2305" ": ", "svx" );
;
2306 }
2307
2308 if(!bOk)
2309 {
2310 AdjustRows();
2311 if (m_nTotalCount > 0) // only to avoid infinite recursion
2312 MoveToNext();
2313 }
2314 }
2315}
2316
2317void DbGridControl::MoveToPosition(sal_uInt32 nPos)
2318{
2319 if (!m_pSeekCursor)
2320 return;
2321
2322 if (m_nTotalCount < 0 && static_cast<long>(nPos) >= GetRowCount())
2323 {
2324 try
2325 {
2326 if (!m_pSeekCursor->absolute(nPos + 1))
2327 {
2328 AdjustRows();
2329 return;
2330 }
2331 else
2332 {
2333 m_nSeekPos = m_pSeekCursor->getRow() - 1;
2334 AdjustRows();
2335 }
2336 }
2337 catch(Exception&)
2338 {
2339 return;
2340 }
2341 }
2342 EditBrowseBox::GoToRow(nPos);
2343 m_aBar->InvalidateAll(m_nCurrentPos);
2344}
2345
2346void DbGridControl::AppendNew()
2347{
2348 if (!m_pSeekCursor || !(m_nOptions & DbGridControlOptions::Insert))
2349 return;
2350
2351 if (m_nTotalCount < 0) // no RecordCount, yet
2352 {
2353 try
2354 {
2355 bool bRes = m_pSeekCursor->last();
2356
2357 if (bRes)
2358 {
2359 m_nSeekPos = m_pSeekCursor->getRow() - 1;
2360 AdjustRows();
2361 }
2362 }
2363 catch(Exception&)
2364 {
2365 return;
2366 }
2367 }
2368
2369 long nNewRow = m_nTotalCount + 1;
2370 if (nNewRow > 0 && GetCurRow() != nNewRow)
2371 MoveToPosition(nNewRow - 1);
2372}
2373
2374void DbGridControl::SetDesignMode(bool bMode)
2375{
2376 if (IsDesignMode() == bMode)
2377 return;
2378
2379 // adjust Enable/Disable for design mode so that the headerbar remains configurable
2380 if (bMode)
2381 {
2382 if (!IsEnabled())
2383 {
2384 Enable();
2385 GetDataWindow().Disable();
2386 }
2387 }
2388 else
2389 {
2390 // disable completely
2391 if (!GetDataWindow().IsEnabled())
2392 Disable();
2393 }
2394
2395 m_bDesignMode = bMode;
2396 GetDataWindow().SetMouseTransparent(bMode);
2397 SetMouseTransparent(bMode);
2398
2399 m_aBar->InvalidateAll(m_nCurrentPos, true);
2400}
2401
2402void DbGridControl::SetFilterMode(bool bMode)
2403{
2404 if (IsFilterMode() == bMode)
2405 return;
2406
2407 m_bFilterMode = bMode;
2408
2409 if (bMode)
2410 {
2411 SetUpdateMode(false);
2412
2413 // there is no cursor anymore
2414 if (IsEditing())
2415 DeactivateCell();
2416 RemoveRows(false);
2417
2418 m_xEmptyRow = new DbGridRow();
2419
2420 // setting the new filter controls
2421 for (auto const & pCurCol : m_aColumns)
2422 {
2423 if (!pCurCol->IsHidden())
2424 pCurCol->UpdateControl();
2425 }
2426
2427 // one row for filtering
2428 RowInserted(0);
2429 SetUpdateMode(true);
2430 }
2431 else
2432 setDataSource(Reference< XRowSet > ());
2433}
2434
2435OUString DbGridControl::GetCellText(long _nRow, sal_uInt16 _nColId) const
2436{
2437 size_t Location = GetModelColumnPos( _nColId );
2438 DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ].get() : nullptr;
2439 OUString sRet;
2440 if ( const_cast<DbGridControl*>(this)->SeekRow(_nRow) )
2441 sRet = GetCurrentRowCellText(pColumn, m_xPaintRow);
2442 return sRet;
2443}
2444
2445OUString DbGridControl::GetCurrentRowCellText(DbGridColumn const * pColumn,const DbGridRowRef& _rRow) const
2446{
2447 // text output for a single row
2448 OUString aText;
2449 if ( pColumn && IsValid(_rRow) )
2450 aText = pColumn->GetCellText(_rRow.get(), m_xFormatter);
2451 return aText;
2452}
2453
2454sal_uInt32 DbGridControl::GetTotalCellWidth(long nRow, sal_uInt16 nColId)
2455{
2456 if (SeekRow(nRow))
2457 {
2458 size_t Location = GetModelColumnPos( nColId );
2459 DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ].get() : nullptr;
2460 return GetDataWindow().GetTextWidth(GetCurrentRowCellText(pColumn,m_xPaintRow));
2461 }
2462 else
2463 return 30; // FIXME magic number for default cell width
2464}
2465
2466void DbGridControl::PreExecuteRowContextMenu(sal_uInt16 /*nRow*/, PopupMenu& rMenu)
2467{
2468 bool bDelete = (m_nOptions & DbGridControlOptions::Delete) && GetSelectRowCount() && !IsCurrentAppending();
2469 // if only a blank row is selected then do not delete
2470 bDelete = bDelete && !((m_nOptions & DbGridControlOptions::Insert) && GetSelectRowCount() == 1 && IsRowSelected(GetRowCount() - 1));
2471
2472 rMenu.EnableItem(rMenu.GetItemId("delete"), bDelete);
2473 rMenu.EnableItem(rMenu.GetItemId("save"), IsModified());
2474
2475 // the undo is more difficult
2476 bool bCanUndo = IsModified();
2477 int nState = -1;
2478 if (m_aMasterStateProvider.IsSet())
2479 nState = m_aMasterStateProvider.Call(DbGridControlNavigationBarState::Undo);
2480 bCanUndo &= ( 0 != nState );
2481
2482 rMenu.EnableItem(rMenu.GetItemId("undo"), bCanUndo);
2483}
2484
2485void DbGridControl::PostExecuteRowContextMenu(sal_uInt16 /*nRow*/, const PopupMenu& rMenu, sal_uInt16 nExecutionResult)
2486{
2487 if (nExecutionResult == rMenu.GetItemId("delete"))
2488 {
2489 // delete asynchronously
2490 if (m_nDeleteEvent)
2491 Application::RemoveUserEvent(m_nDeleteEvent);
2492 m_nDeleteEvent = Application::PostUserEvent(LINK(this,DbGridControl,OnDelete)::tools::detail::makeLink( ::tools::detail::castTo<DbGridControl
*>(this), &DbGridControl::LinkStubOnDelete)
, nullptr, true);
2493 }
2494 else if (nExecutionResult == rMenu.GetItemId("undo"))
2495 Undo();
2496 else if (nExecutionResult == rMenu.GetItemId("save"))
2497 SaveRow();
2498}
2499
2500void DbGridControl::DataSourcePropertyChanged(const PropertyChangeEvent& evt)
2501{
2502 SAL_INFO("svx.fmcomp", "DbGridControl::DataSourcePropertyChanged")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "DbGridControl::DataSourcePropertyChanged"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2502" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::DataSourcePropertyChanged"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "DbGridControl::DataSourcePropertyChanged"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), (
"/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2502" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "DbGridControl::DataSourcePropertyChanged") == 1)
{ ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2502" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::DataSourcePropertyChanged"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "DbGridControl::DataSourcePropertyChanged"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), (
"/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2502" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2503 SolarMutexGuard aGuard;
2504 // prop "IsModified" changed ?
2505 // during update don't care about the modified state
2506 if (IsUpdating() || evt.PropertyName != FM_PROP_ISMODIFIED"IsModified")
2507 return;
2508
2509 Reference< XPropertySet > xSource(evt.Source, UNO_QUERY);
2510 DBG_ASSERT( xSource.is(), "DbGridControl::DataSourcePropertyChanged: invalid event source!" )do { if (true && (!(xSource.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2510" ": "), "%s", "DbGridControl::DataSourcePropertyChanged: invalid event source!"
); } } while (false)
;
2511 bool bIsNew = false;
2512 if (xSource.is())
2513 bIsNew = ::comphelper::getBOOL(xSource->getPropertyValue(FM_PROP_ISNEW"IsNew"));
2514
2515 if (bIsNew && m_xCurrentRow.is())
2516 {
2517 DBG_ASSERT(::comphelper::getBOOL(xSource->getPropertyValue(FM_PROP_ROWCOUNTFINAL)), "DbGridControl::DataSourcePropertyChanged : somebody moved the form to a new record before the row count was final !")do { if (true && (!(::comphelper::getBOOL(xSource->
getPropertyValue("IsRowCountFinal"))))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2517" ": "), "%s", "DbGridControl::DataSourcePropertyChanged : somebody moved the form to a new record before the row count was final !"
); } } while (false)
;
2518 sal_Int32 nRecordCount = 0;
2519 xSource->getPropertyValue(FM_PROP_ROWCOUNT"RowCount") >>= nRecordCount;
2520 if (::comphelper::getBOOL(evt.NewValue))
2521 { // modified state changed from sal_False to sal_True and we're on an insert row
2522 // -> we've to add a new grid row
2523 if ((nRecordCount == GetRowCount() - 1) && m_xCurrentRow->IsNew())
2524 {
2525 RowInserted(GetRowCount());
2526 InvalidateStatusCell(m_nCurrentPos);
2527 m_aBar->InvalidateAll(m_nCurrentPos);
2528 }
2529 }
2530 else
2531 { // modified state changed from sal_True to sal_False and we're on an insert row
2532 // we have two "new row"s at the moment : the one we're editing currently (where the current
2533 // column is the only dirty element) and a "new new" row which is completely clean. As the first
2534 // one is about to be cleaned, too, the second one is obsolete now.
2535 if (m_xCurrentRow->IsNew() && nRecordCount == (GetRowCount() - 2))
2536 {
2537 RowRemoved(GetRowCount() - 1);
2538 InvalidateStatusCell(m_nCurrentPos);
2539 m_aBar->InvalidateAll(m_nCurrentPos);
2540 }
2541 }
2542 }
2543 if (m_xCurrentRow.is())
2544 {
2545 m_xCurrentRow->SetStatus(::comphelper::getBOOL(evt.NewValue) ? GridRowStatus::Modified : GridRowStatus::Clean);
2546 m_xCurrentRow->SetNew( bIsNew );
2547 InvalidateStatusCell(m_nCurrentPos);
2548 SAL_INFO("svx.fmcomp", "modified flag changed, new state: " << ROWSTATUS(m_xCurrentRow))do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "modified flag changed, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), (
"svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2548" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "modified flag changed, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "modified flag changed, new state: " << (!m_xCurrentRow
.is() ? "NULL" : m_xCurrentRow->GetStatus() == GridRowStatus
::Clean ? "CLEAN" : m_xCurrentRow->GetStatus() == GridRowStatus
::Modified ? "MODIFIED" : m_xCurrentRow->GetStatus() == GridRowStatus
::Deleted ? "DELETED" : "INVALID"); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2548" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "modified flag changed, new state: " << (!m_xCurrentRow
.is() ? "NULL" : m_xCurrentRow->GetStatus() == GridRowStatus
::Clean ? "CLEAN" : m_xCurrentRow->GetStatus() == GridRowStatus
::Modified ? "MODIFIED" : m_xCurrentRow->GetStatus() == GridRowStatus
::Deleted ? "DELETED" : "INVALID")) == 1) { ::sal_detail_log(
(::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2548" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "modified flag changed, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "modified flag changed, new state: " << (!m_xCurrentRow
.is() ? "NULL" : m_xCurrentRow->GetStatus() == GridRowStatus
::Clean ? "CLEAN" : m_xCurrentRow->GetStatus() == GridRowStatus
::Modified ? "MODIFIED" : m_xCurrentRow->GetStatus() == GridRowStatus
::Deleted ? "DELETED" : "INVALID"); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2548" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2549 }
2550}
2551
2552void DbGridControl::StartDrag( sal_Int8 /*nAction*/, const Point& rPosPixel )
2553{
2554 if (!m_pSeekCursor || IsResizing())
2555 return;
2556
2557 sal_uInt16 nColId = GetColumnId(GetColumnAtXPosPixel(rPosPixel.X()));
2558 long nRow = GetRowAtYPosPixel(rPosPixel.Y());
2559 if (nColId != HandleColumnId && nRow >= 0)
2560 {
2561 if (GetDataWindow().IsMouseCaptured())
2562 GetDataWindow().ReleaseMouse();
2563
2564 size_t Location = GetModelColumnPos( nColId );
2565 DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ].get() : nullptr;
2566 rtl::Reference<OStringTransferable> pTransferable = new OStringTransferable(GetCurrentRowCellText(pColumn,m_xPaintRow));
2567 pTransferable->StartDrag(this, DND_ACTION_COPYcss::datatransfer::dnd::DNDConstants::ACTION_COPY);
2568 }
2569}
2570
2571bool DbGridControl::canCopyCellText(sal_Int32 _nRow, sal_uInt16 _nColId)
2572{
2573 return (_nRow >= 0)
2574 && (_nRow < GetRowCount())
2575 && (_nColId != HandleColumnId)
2576 && (GetModelColumnPos(_nColId) != GRID_COLUMN_NOT_FOUND((sal_uInt16) 0xFFFF));
2577}
2578
2579void DbGridControl::copyCellText(sal_Int32 _nRow, sal_uInt16 _nColId)
2580{
2581 DBG_ASSERT(canCopyCellText(_nRow, _nColId), "DbGridControl::copyCellText: invalid call!")do { if (true && (!(canCopyCellText(_nRow, _nColId)))
) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2581" ": "), "%s", "DbGridControl::copyCellText: invalid call!"
); } } while (false)
;
2582 DbGridColumn* pColumn = m_aColumns[ GetModelColumnPos(_nColId) ].get();
2583 SeekRow(_nRow);
2584 OStringTransfer::CopyString( GetCurrentRowCellText( pColumn,m_xPaintRow ), this );
2585}
2586
2587void DbGridControl::executeRowContextMenu( long _nRow, const Point& _rPreferredPos )
2588{
2589 VclBuilder aBuilder(nullptr, AllSettings::GetUIRootDir(), "svx/ui/rowsmenu.ui", "");
2590 VclPtr<PopupMenu> aContextMenu(aBuilder.get_menu("menu"));
2591
2592 PreExecuteRowContextMenu( static_cast<sal_uInt16>(_nRow), *aContextMenu );
2593 aContextMenu->RemoveDisabledEntries( true, true );
2594 PostExecuteRowContextMenu( static_cast<sal_uInt16>(_nRow), *aContextMenu, aContextMenu->Execute( this, _rPreferredPos ) );
2595}
2596
2597void DbGridControl::Command(const CommandEvent& rEvt)
2598{
2599 switch (rEvt.GetCommand())
2600 {
2601 case CommandEventId::ContextMenu:
2602 {
2603 if ( !m_pSeekCursor )
2604 {
2605 EditBrowseBox::Command(rEvt);
2606 return;
2607 }
2608
2609 if ( !rEvt.IsMouseEvent() )
2610 { // context menu requested by keyboard
2611 if ( GetSelectRowCount() )
2612 {
2613 long nRow = FirstSelectedRow( );
2614
2615 ::tools::Rectangle aRowRect( GetRowRectPixel( nRow ) );
2616 executeRowContextMenu( nRow, aRowRect.LeftCenter() );
2617
2618 // handled
2619 return;
2620 }
2621 }
2622
2623 sal_uInt16 nColId = GetColumnId(GetColumnAtXPosPixel(rEvt.GetMousePosPixel().X()));
2624 long nRow = GetRowAtYPosPixel(rEvt.GetMousePosPixel().Y());
2625
2626 if (nColId == HandleColumnId)
2627 {
2628 executeRowContextMenu( nRow, rEvt.GetMousePosPixel() );
2629 }
2630 else if (canCopyCellText(nRow, nColId))
2631 {
2632 VclBuilder aBuilder(nullptr, AllSettings::GetUIRootDir(), "svx/ui/cellmenu.ui", "");
2633 VclPtr<PopupMenu> aContextMenu(aBuilder.get_menu("menu"));
2634 if (aContextMenu->Execute(this, rEvt.GetMousePosPixel()))
2635 copyCellText(nRow, nColId);
2636 }
2637 else
2638 {
2639 EditBrowseBox::Command(rEvt);
2640 return;
2641 }
2642
2643 [[fallthrough]];
2644 }
2645 default:
2646 EditBrowseBox::Command(rEvt);
2647 }
2648}
2649
2650IMPL_LINK_NOARG(DbGridControl, OnDelete, void*, void)void DbGridControl::LinkStubOnDelete(void * instance, void* data
) { return static_cast<DbGridControl *>(instance)->OnDelete
(data); } void DbGridControl::OnDelete(__attribute__ ((unused
)) void*)
2651{
2652 m_nDeleteEvent = nullptr;
2653 DeleteSelectedRows();
2654}
2655
2656void DbGridControl::DeleteSelectedRows()
2657{
2658 DBG_ASSERT(GetSelection(), "no selection!!!")do { if (true && (!(GetSelection()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2658" ": "), "%s", "no selection!!!"); } } while (false
)
;
2659
2660 if (!m_pSeekCursor)
2661 return;
2662}
2663
2664CellController* DbGridControl::GetController(long /*nRow*/, sal_uInt16 nColumnId)
2665{
2666 if (!IsValid(m_xCurrentRow) || !IsEnabled())
2667 return nullptr;
2668
2669 size_t Location = GetModelColumnPos(nColumnId);
2670 DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ].get() : nullptr;
2671 if (!pColumn)
2672 return nullptr;
2673
2674 CellController* pReturn = nullptr;
2675 if (IsFilterMode())
2676 pReturn = pColumn->GetController().get();
2677 else
2678 {
2679 if (::comphelper::hasProperty(FM_PROP_ENABLED"Enabled", pColumn->getModel()))
2680 {
2681 if (!::comphelper::getBOOL(pColumn->getModel()->getPropertyValue(FM_PROP_ENABLED"Enabled")))
2682 return nullptr;
2683 }
2684
2685 bool bInsert = (m_xCurrentRow->IsNew() && (m_nOptions & DbGridControlOptions::Insert));
2686 bool bUpdate = (!m_xCurrentRow->IsNew() && (m_nOptions & DbGridControlOptions::Update));
2687
2688 if ((bInsert && !pColumn->IsAutoValue()) || bUpdate)
2689 {
2690 pReturn = pColumn->GetController().get();
2691 }
2692 }
2693 return pReturn;
2694}
2695
2696void DbGridControl::CellModified()
2697{
2698 SAL_INFO("svx.fmcomp", "DbGridControl::CellModified")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "DbGridControl::CellModified"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2698" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::CellModified"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "DbGridControl::CellModified"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2698" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "DbGridControl::CellModified") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2698" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::CellModified"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "DbGridControl::CellModified"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2698" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2699
2700 {
2701 ::osl::MutexGuard aGuard(m_aAdjustSafety);
2702 if (m_nAsynAdjustEvent)
2703 {
2704 SAL_INFO("svx.fmcomp", "forcing a synchron call to " << (m_bPendingAdjustRows ? "AdjustRows" : "AdustDataSource"))do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "forcing a synchron call to "
<< (m_bPendingAdjustRows ? "AdjustRows" : "AdustDataSource"
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), (
"svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2704" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "forcing a synchron call to " <<
(m_bPendingAdjustRows ? "AdjustRows" : "AdustDataSource")), 0
); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "forcing a synchron call to " << (m_bPendingAdjustRows
? "AdjustRows" : "AdustDataSource"); ::sal::detail::log( (::
SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2704" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "forcing a synchron call to " << (m_bPendingAdjustRows
? "AdjustRows" : "AdustDataSource")) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2704" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "forcing a synchron call to " <<
(m_bPendingAdjustRows ? "AdjustRows" : "AdustDataSource")), 0
); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "forcing a synchron call to " << (m_bPendingAdjustRows
? "AdjustRows" : "AdustDataSource"); ::sal::detail::log( (::
SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2704" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2705 RemoveUserEvent(m_nAsynAdjustEvent);
2706 m_nAsynAdjustEvent = nullptr;
2707
2708 // force the call : this should be no problem as we're probably running in the solar thread here
2709 // (cell modified is triggered by user actions)
2710 if (m_bPendingAdjustRows)
2711 AdjustRows();
2712 else
2713 AdjustDataSource();
2714 }
2715 }
2716
2717 if (IsFilterMode() || !IsValid(m_xCurrentRow) || m_xCurrentRow->IsModified())
2718 return;
2719
2720 // enable edit mode
2721 // a data set should be inserted
2722 if (m_xCurrentRow->IsNew())
2723 {
2724 m_xCurrentRow->SetStatus(GridRowStatus::Modified);
2725 SAL_INFO("svx.fmcomp", "current row is new, new state: MODIFIED")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "current row is new, new state: MODIFIED"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2725" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "current row is new, new state: MODIFIED"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "current row is new, new state: MODIFIED"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2725" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "current row is new, new state: MODIFIED") == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2725" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "current row is new, new state: MODIFIED"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "current row is new, new state: MODIFIED"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2725" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2726 // if no row was added yet, do it now
2727 if (m_nCurrentPos == GetRowCount() - 1)
2728 {
2729 // increment RowCount
2730 RowInserted(GetRowCount());
2731 InvalidateStatusCell(m_nCurrentPos);
2732 m_aBar->InvalidateAll(m_nCurrentPos);
2733 }
2734 }
2735 else if (m_xCurrentRow->GetStatus() != GridRowStatus::Modified)
2736 {
2737 m_xCurrentRow->SetState(m_pDataCursor.get(), false);
2738 SAL_INFO("svx.fmcomp", "current row is not new, after SetState, new state: " << ROWSTATUS(m_xCurrentRow))do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "current row is not new, after SetState, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), (
"svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2738" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "current row is not new, after SetState, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "current row is not new, after SetState, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2738" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "current row is not new, after SetState, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), (
"svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2738" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "current row is not new, after SetState, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "current row is not new, after SetState, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2738" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2739 m_xCurrentRow->SetStatus(GridRowStatus::Modified);
2740 SAL_INFO("svx.fmcomp", "current row is not new, new state: MODIFIED")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "current row is not new, new state: MODIFIED"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2740" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "current row is not new, new state: MODIFIED"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "current row is not new, new state: MODIFIED"; ::sal
::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"),
("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2740" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "current row is not new, new state: MODIFIED") ==
1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2740" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "current row is not new, new state: MODIFIED"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "current row is not new, new state: MODIFIED"; ::sal
::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"),
("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2740" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2741 InvalidateStatusCell(m_nCurrentPos);
2742 }
2743}
2744
2745void DbGridControl::Dispatch(sal_uInt16 nId)
2746{
2747 if (nId == BROWSER_CURSORENDOFFILE741)
2748 {
2749 if (m_nOptions & DbGridControlOptions::Insert)
2750 AppendNew();
2751 else
2752 MoveToLast();
2753 }
2754 else
2755 EditBrowseBox::Dispatch(nId);
2756}
2757
2758void DbGridControl::Undo()
2759{
2760 if (IsFilterMode() || !IsValid(m_xCurrentRow) || !IsModified())
2761 return;
2762
2763 // check if we have somebody doin' the UNDO for us
2764 int nState = -1;
2765 if (m_aMasterStateProvider.IsSet())
2766 nState = m_aMasterStateProvider.Call(DbGridControlNavigationBarState::Undo);
2767 if (nState>0)
2768 { // yes, we have, and the slot is enabled
2769 DBG_ASSERT(m_aMasterSlotExecutor.IsSet(), "DbGridControl::Undo : a state, but no execute link ?")do { if (true && (!(m_aMasterSlotExecutor.IsSet()))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2769" ": "), "%s", "DbGridControl::Undo : a state, but no execute link ?"
); } } while (false)
;
2770 bool lResult = m_aMasterSlotExecutor.Call(DbGridControlNavigationBarState::Undo);
2771 if (lResult)
2772 // handled
2773 return;
2774 }
2775 else if (nState == 0)
2776 // yes, we have, and the slot is disabled
2777 return;
2778
2779 BeginCursorAction();
2780
2781 bool bAppending = m_xCurrentRow->IsNew();
2782 bool bDirty = m_xCurrentRow->IsModified();
2783
2784 try
2785 {
2786 // cancel editing
2787 Reference< XResultSetUpdate > xUpdateCursor(Reference< XInterface >(*m_pDataCursor), UNO_QUERY);
2788 // no effects if we're not updating currently
2789 if (bAppending)
2790 // just refresh the row
2791 xUpdateCursor->moveToInsertRow();
2792 else
2793 xUpdateCursor->cancelRowUpdates();
2794
2795 }
2796 catch(Exception&)
2797 {
2798 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2798" ": ", "svx" );
;
2799 }
2800
2801 EndCursorAction();
2802
2803 m_xDataRow->SetState(m_pDataCursor.get(), false);
2804 if (m_xPaintRow == m_xCurrentRow)
2805 m_xPaintRow = m_xCurrentRow = m_xDataRow;
2806 else
2807 m_xCurrentRow = m_xDataRow;
2808
2809 if (bAppending && (EditBrowseBox::IsModified() || bDirty))
2810 // remove the row
2811 if (m_nCurrentPos == GetRowCount() - 2)
2812 { // maybe we already removed it (in resetCurrentRow, called if the above moveToInsertRow
2813 // caused our data source form to be reset - which should be the usual case...)
2814 RowRemoved(GetRowCount() - 1);
2815 m_aBar->InvalidateAll(m_nCurrentPos);
2816 }
2817
2818 RowModified(m_nCurrentPos);
2819}
2820
2821void DbGridControl::resetCurrentRow()
2822{
2823 if (IsModified())
2824 {
2825 // scenario : we're on the insert row, the row is dirty, and thus there exists a "second" insert row (which
2826 // is clean). Normally in DataSourcePropertyChanged we would remove this second row if the modified state of
2827 // the insert row changes from sal_True to sal_False. But if our current cell is the only modified element (means the
2828 // data source isn't modified) and we're reset this DataSourcePropertyChanged would never be called, so we
2829 // would never delete the obsolete "second insert row". Thus in this special case this method here
2830 // is the only possibility to determine the redundance of the row (resetCurrentRow is called when the
2831 // "first insert row" is about to be cleaned, so of course the "second insert row" is redundant now)
2832 Reference< XPropertySet > xDataSource = getDataSource()->getPropertySet();
2833 if (xDataSource.is() && !::comphelper::getBOOL(xDataSource->getPropertyValue(FM_PROP_ISMODIFIED"IsModified")))
2834 {
2835 // are we on a new row currently ?
2836 if (m_xCurrentRow->IsNew())
2837 {
2838 if (m_nCurrentPos == GetRowCount() - 2)
2839 {
2840 RowRemoved(GetRowCount() - 1);
2841 m_aBar->InvalidateAll(m_nCurrentPos);
2842 }
2843 }
2844 }
2845
2846 // update the rows
2847 m_xDataRow->SetState(m_pDataCursor.get(), false);
2848 if (m_xPaintRow == m_xCurrentRow)
2849 m_xPaintRow = m_xCurrentRow = m_xDataRow;
2850 else
2851 m_xCurrentRow = m_xDataRow;
2852 }
2853
2854 RowModified(GetCurRow()); // will update the current controller if affected
2855}
2856
2857void DbGridControl::RowModified( long nRow )
2858{
2859 if (nRow == m_nCurrentPos && IsEditing())
2860 {
2861 CellControllerRef aTmpRef = Controller();
2862 aTmpRef->SaveValue();
2863 InitController(aTmpRef, m_nCurrentPos, GetCurColumnId());
2864 }
2865 EditBrowseBox::RowModified(nRow);
2866}
2867
2868bool DbGridControl::IsModified() const
2869{
2870 return !IsFilterMode() && IsValid(m_xCurrentRow) && (m_xCurrentRow->IsModified() || EditBrowseBox::IsModified());
2871}
2872
2873bool DbGridControl::IsCurrentAppending() const
2874{
2875 return m_xCurrentRow.is() && m_xCurrentRow->IsNew();
2876}
2877
2878bool DbGridControl::IsInsertionRow(long nRow) const
2879{
2880 return (m_nOptions & DbGridControlOptions::Insert) && m_nTotalCount >= 0 && (nRow == GetRowCount() - 1);
2881}
2882
2883bool DbGridControl::SaveModified()
2884{
2885 SAL_INFO("svx.fmcomp", "DbGridControl::SaveModified")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "DbGridControl::SaveModified"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2885" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::SaveModified"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "DbGridControl::SaveModified"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2885" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "DbGridControl::SaveModified") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2885" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::SaveModified"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "DbGridControl::SaveModified"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2885" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2886 DBG_ASSERT(IsValid(m_xCurrentRow), "GridControl:: Invalid row")do { if (true && (!(IsValid(m_xCurrentRow)))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2886" ": "), "%s", "GridControl:: Invalid row"); } } while
(false)
;
2887 if (!IsValid(m_xCurrentRow))
2888 return true;
2889
2890 // accept input for this field
2891 // Where there changes at the current input field?
2892 if (!EditBrowseBox::IsModified())
2893 return true;
2894
2895 size_t Location = GetModelColumnPos( GetCurColumnId() );
2896 DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ].get() : nullptr;
2897 bool bOK = pColumn && pColumn->Commit();
2898 DBG_ASSERT( Controller().is(), "DbGridControl::SaveModified: was modified, by have no controller?!" )do { if (true && (!(Controller().is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2898" ": "), "%s", "DbGridControl::SaveModified: was modified, by have no controller?!"
); } } while (false)
;
2899 if ( !Controller().is() )
2900 // this might happen if the callbacks implicitly triggered by Commit
2901 // fiddled with the form or the control ...
2902 // (Note that this here is a workaround, at most. We need a general concept how
2903 // to treat this, you can imagine an arbitrary number of scenarios where a callback
2904 // triggers something which leaves us in an expected state.)
2905 // #i67147# / 2006-07-17 / frank.schoenheit@sun.com
2906 return bOK;
2907
2908 if (bOK)
2909 {
2910 Controller()->SaveValue();
2911
2912 if ( IsValid(m_xCurrentRow) )
2913 {
2914 m_xCurrentRow->SetState(m_pDataCursor.get(), false);
2915 SAL_INFO("svx.fmcomp", "explicit SetState, new state: " << ROWSTATUS(m_xCurrentRow))do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "explicit SetState, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), (
"svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2915" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "explicit SetState, new state: " <<
(!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus(
) == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "explicit SetState, new state: " << (!m_xCurrentRow
.is() ? "NULL" : m_xCurrentRow->GetStatus() == GridRowStatus
::Clean ? "CLEAN" : m_xCurrentRow->GetStatus() == GridRowStatus
::Modified ? "MODIFIED" : m_xCurrentRow->GetStatus() == GridRowStatus
::Deleted ? "DELETED" : "INVALID"); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2915" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "explicit SetState, new state: " << (!m_xCurrentRow
.is() ? "NULL" : m_xCurrentRow->GetStatus() == GridRowStatus
::Clean ? "CLEAN" : m_xCurrentRow->GetStatus() == GridRowStatus
::Modified ? "MODIFIED" : m_xCurrentRow->GetStatus() == GridRowStatus
::Deleted ? "DELETED" : "INVALID")) == 1) { ::sal_detail_log(
(::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2915" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "explicit SetState, new state: " <<
(!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus(
) == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "explicit SetState, new state: " << (!m_xCurrentRow
.is() ? "NULL" : m_xCurrentRow->GetStatus() == GridRowStatus
::Clean ? "CLEAN" : m_xCurrentRow->GetStatus() == GridRowStatus
::Modified ? "MODIFIED" : m_xCurrentRow->GetStatus() == GridRowStatus
::Deleted ? "DELETED" : "INVALID"); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2915" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2916 InvalidateStatusCell( m_nCurrentPos );
2917 }
2918 else
2919 {
2920 SAL_INFO("svx.fmcomp", "no SetState, new state: " << ROWSTATUS(m_xCurrentRow))do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "no SetState, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), (
"svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2920" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "no SetState, new state: " << (
!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus() ==
GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "no SetState, new state: " << (!m_xCurrentRow
.is() ? "NULL" : m_xCurrentRow->GetStatus() == GridRowStatus
::Clean ? "CLEAN" : m_xCurrentRow->GetStatus() == GridRowStatus
::Modified ? "MODIFIED" : m_xCurrentRow->GetStatus() == GridRowStatus
::Deleted ? "DELETED" : "INVALID"); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2920" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "no SetState, new state: " << (!m_xCurrentRow
.is() ? "NULL" : m_xCurrentRow->GetStatus() == GridRowStatus
::Clean ? "CLEAN" : m_xCurrentRow->GetStatus() == GridRowStatus
::Modified ? "MODIFIED" : m_xCurrentRow->GetStatus() == GridRowStatus
::Deleted ? "DELETED" : "INVALID")) == 1) { ::sal_detail_log(
(::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2920" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "no SetState, new state: " << (
!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus() ==
GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "no SetState, new state: " << (!m_xCurrentRow
.is() ? "NULL" : m_xCurrentRow->GetStatus() == GridRowStatus
::Clean ? "CLEAN" : m_xCurrentRow->GetStatus() == GridRowStatus
::Modified ? "MODIFIED" : m_xCurrentRow->GetStatus() == GridRowStatus
::Deleted ? "DELETED" : "INVALID"); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2920" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2921 }
2922 }
2923
2924 return bOK;
2925}
2926
2927bool DbGridControl::SaveRow()
2928{
2929 SAL_INFO("svx.fmcomp", "DbGridControl::SaveRow")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "DbGridControl::SaveRow"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2929" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::SaveRow"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"DbGridControl::SaveRow"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2929" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "DbGridControl::SaveRow") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2929" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::SaveRow"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"DbGridControl::SaveRow"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2929" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2930 // valid row
2931 if (!IsValid(m_xCurrentRow) || !IsModified())
2932 return true;
2933 // value of the controller was not saved, yet
2934 else if (Controller().is() && Controller()->IsValueChangedFromSaved())
2935 {
2936 if (!SaveModified())
2937 return false;
2938 }
2939 m_bUpdating = true;
2940
2941 BeginCursorAction();
2942 bool bAppending = m_xCurrentRow->IsNew();
2943 bool bSuccess = false;
2944 try
2945 {
2946 Reference< XResultSetUpdate > xUpdateCursor(Reference< XInterface >(*m_pDataCursor), UNO_QUERY);
2947 if (bAppending)
2948 xUpdateCursor->insertRow();
2949 else
2950 xUpdateCursor->updateRow();
2951 bSuccess = true;
2952 }
2953 catch(SQLException&)
2954 {
2955 EndCursorAction();
2956 m_bUpdating = false;
2957 return false;
2958 }
2959
2960 try
2961 {
2962 if (bSuccess)
2963 {
2964 // if we are appending we still sit on the insert row
2965 // we don't move just clear the flags not to move on the current row
2966 m_xCurrentRow->SetState(m_pDataCursor.get(), false);
2967 SAL_INFO("svx.fmcomp", "explicit SetState after a successful update, new state: " << ROWSTATUS(m_xCurrentRow))do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "explicit SetState after a successful update, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), (
"svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2967" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "explicit SetState after a successful update, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "explicit SetState after a successful update, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2967" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "explicit SetState after a successful update, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), (
"svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2967" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "explicit SetState after a successful update, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "explicit SetState after a successful update, new state: "
<< (!m_xCurrentRow.is() ? "NULL" : m_xCurrentRow->GetStatus
() == GridRowStatus::Clean ? "CLEAN" : m_xCurrentRow->GetStatus
() == GridRowStatus::Modified ? "MODIFIED" : m_xCurrentRow->
GetStatus() == GridRowStatus::Deleted ? "DELETED" : "INVALID"
); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "2967" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2968 m_xCurrentRow->SetNew(false);
2969
2970 // adjust the seekcursor if it is on the same position as the datacursor
2971 if (m_nSeekPos == m_nCurrentPos || bAppending)
2972 {
2973 // get the bookmark to refetch the data
2974 // in insert mode we take the new bookmark of the data cursor
2975 Any aBookmark = bAppending ? m_pDataCursor->getBookmark() : m_pSeekCursor->getBookmark();
2976 m_pSeekCursor->moveToBookmark(aBookmark);
2977 // get the data
2978 m_xSeekRow->SetState(m_pSeekCursor.get(), true);
2979 m_nSeekPos = m_pSeekCursor->getRow() - 1;
2980 }
2981 }
2982 // and repaint the row
2983 RowModified(m_nCurrentPos);
2984 }
2985 catch(Exception&)
2986 {
2987 }
2988
2989 m_bUpdating = false;
2990 EndCursorAction();
2991
2992 // The old code returned (nRecords != 0) here.
2993 // Me thinks this is wrong : If something goes wrong while update the record, an exception will be thrown,
2994 // which results in a "return sal_False" (see above). If no exception is thrown, everything is fine. If nRecords
2995 // is zero, this simply means all fields had their original values.
2996 // FS - 06.12.99 - 70502
2997 return true;
2998}
2999
3000bool DbGridControl::PreNotify(NotifyEvent& rEvt)
3001{
3002 // do not handle events of the Navbar
3003 if (m_aBar->IsWindowOrChild(rEvt.GetWindow()))
3004 return BrowseBox::PreNotify(rEvt);
3005
3006 switch (rEvt.GetType())
3007 {
3008 case MouseNotifyEvent::KEYINPUT:
3009 {
3010 const KeyEvent* pKeyEvent = rEvt.GetKeyEvent();
3011
3012 sal_uInt16 nCode = pKeyEvent->GetKeyCode().GetCode();
3013 bool bShift = pKeyEvent->GetKeyCode().IsShift();
3014 bool bCtrl = pKeyEvent->GetKeyCode().IsMod1();
3015 bool bAlt = pKeyEvent->GetKeyCode().IsMod2();
3016 if ( ( KEY_TAB == nCode ) && bCtrl && !bAlt )
3017 {
3018 // Ctrl-Tab is used to step out of the control, without traveling to the
3019 // remaining cells first
3020 // -> build a new key event without the Ctrl-key, and let the very base class handle it
3021 vcl::KeyCode aNewCode( KEY_TAB, bShift, false, false, false );
3022 KeyEvent aNewEvent( pKeyEvent->GetCharCode(), aNewCode );
3023
3024 // call the Control - our direct base class will interpret this in a way we do not want (and do
3025 // a cell traveling)
3026 Control::KeyInput( aNewEvent );
3027 return true;
3028 }
3029
3030 if ( !bShift && !bCtrl && ( KEY_ESCAPE == nCode ) )
3031 {
3032 if (IsModified())
3033 {
3034 Undo();
3035 return true;
3036 }
3037 }
3038 else if ( ( KEY_DELETE == nCode ) && !bShift && !bCtrl ) // delete rows
3039 {
3040 if ((m_nOptions & DbGridControlOptions::Delete) && GetSelectRowCount())
3041 {
3042 // delete asynchronously
3043 if (m_nDeleteEvent)
3044 Application::RemoveUserEvent(m_nDeleteEvent);
3045 m_nDeleteEvent = Application::PostUserEvent(LINK(this,DbGridControl,OnDelete)::tools::detail::makeLink( ::tools::detail::castTo<DbGridControl
*>(this), &DbGridControl::LinkStubOnDelete)
, nullptr, true);
3046 return true;
3047 }
3048 }
3049
3050 [[fallthrough]];
3051 }
3052 default:
3053 return EditBrowseBox::PreNotify(rEvt);
3054 }
3055}
3056
3057bool DbGridControl::IsTabAllowed(bool bRight) const
3058{
3059 if (bRight)
3060 // Tab only if not on the _last_ row
3061 return GetCurRow() < (GetRowCount() - 1) || !m_bRecordCountFinal ||
3062 GetViewColumnPos(GetCurColumnId()) < (GetViewColCount() - 1);
3063 else
3064 {
3065 // Tab only if not on the _first_ row
3066 return GetCurRow() > 0 || (GetCurColumnId() && GetViewColumnPos(GetCurColumnId()) > 0);
3067 }
3068}
3069
3070void DbGridControl::KeyInput( const KeyEvent& rEvt )
3071{
3072 if (rEvt.GetKeyCode().GetFunction() == KeyFuncType::COPY)
3073 {
3074 long nRow = GetCurRow();
3075 sal_uInt16 nColId = GetCurColumnId();
3076 if (nRow >= 0 && nRow < GetRowCount() && nColId < ColCount())
3077 {
3078 size_t Location = GetModelColumnPos( nColId );
3079 DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ].get() : nullptr;
3080 OStringTransfer::CopyString( GetCurrentRowCellText( pColumn, m_xCurrentRow ), this );
3081 return;
3082 }
3083 }
3084 EditBrowseBox::KeyInput(rEvt);
3085}
3086
3087void DbGridControl::HideColumn(sal_uInt16 nId)
3088{
3089 DeactivateCell();
3090
3091 // determine the col for the focus to set to after removal
3092 sal_uInt16 nPos = GetViewColumnPos(nId);
3093 sal_uInt16 nNewColId = nPos == (ColCount()-1)
3094 ? GetColumnIdFromViewPos(nPos-1) // last col is to be removed -> take the previous
3095 : GetColumnIdFromViewPos(nPos+1); // take the next
3096
3097 long lCurrentWidth = GetColumnWidth(nId);
3098 EditBrowseBox::RemoveColumn(nId);
3099 // don't use my own RemoveColumn, this would remove it from m_aColumns, too
3100
3101 // update my model
3102 size_t Location = GetModelColumnPos( nId );
3103 DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ].get() : nullptr;
3104 DBG_ASSERT(pColumn, "DbGridControl::HideColumn : somebody did hide a nonexistent column !")do { if (true && (!(pColumn))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3104" ": "), "%s", "DbGridControl::HideColumn : somebody did hide a nonexistent column !"
); } } while (false)
;
3105 if (pColumn)
3106 {
3107 pColumn->m_bHidden = true;
3108 pColumn->m_nLastVisibleWidth = CalcReverseZoom(lCurrentWidth);
3109 }
3110
3111 // and reset the focus
3112 if ( nId == GetCurColumnId() )
3113 GoToColumnId( nNewColId );
3114}
3115
3116void DbGridControl::ShowColumn(sal_uInt16 nId)
3117{
3118 sal_uInt16 nPos = GetModelColumnPos(nId);
3119 DBG_ASSERT(nPos != GRID_COLUMN_NOT_FOUND, "DbGridControl::ShowColumn : invalid argument !")do { if (true && (!(nPos != ((sal_uInt16) 0xFFFF)))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3119" ": "), "%s", "DbGridControl::ShowColumn : invalid argument !"
); } } while (false)
;
3120 if (nPos == GRID_COLUMN_NOT_FOUND((sal_uInt16) 0xFFFF))
3121 return;
3122
3123 DbGridColumn* pColumn = m_aColumns[ nPos ].get();
3124 if (!pColumn->IsHidden())
3125 {
3126 DBG_ASSERT(GetViewColumnPos(nId) != GRID_COLUMN_NOT_FOUND, "DbGridControl::ShowColumn : inconsistent internal state !")do { if (true && (!(GetViewColumnPos(nId) != ((sal_uInt16
) 0xFFFF)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3126" ": "), "%s", "DbGridControl::ShowColumn : inconsistent internal state !"
); } } while (false)
;
3127 // if the column isn't marked as hidden, it should be visible, shouldn't it ?
3128 return;
3129 }
3130 DBG_ASSERT(GetViewColumnPos(nId) == GRID_COLUMN_NOT_FOUND, "DbGridControl::ShowColumn : inconsistent internal state !")do { if (true && (!(GetViewColumnPos(nId) == ((sal_uInt16
) 0xFFFF)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3130" ": "), "%s", "DbGridControl::ShowColumn : inconsistent internal state !"
); } } while (false)
;
3131 // the opposite situation ...
3132
3133 // to determine the new view position we need an adjacent non-hidden column
3134 sal_uInt16 nNextNonHidden = BROWSER_INVALIDID((sal_uInt16) 0xFFFF);
3135 // first search the cols to the right
3136 for ( size_t i = nPos + 1; i < m_aColumns.size(); ++i )
3137 {
3138 DbGridColumn* pCurCol = m_aColumns[ i ].get();
3139 if (!pCurCol->IsHidden())
3140 {
3141 nNextNonHidden = i;
3142 break;
3143 }
3144 }
3145 if ((nNextNonHidden == BROWSER_INVALIDID((sal_uInt16) 0xFFFF)) && (nPos > 0))
3146 {
3147 // then to the left
3148 for ( size_t i = nPos; i > 0; --i )
3149 {
3150 DbGridColumn* pCurCol = m_aColumns[ i-1 ].get();
3151 if (!pCurCol->IsHidden())
3152 {
3153 nNextNonHidden = i-1;
3154 break;
3155 }
3156 }
3157 }
3158 sal_uInt16 nNewViewPos = (nNextNonHidden == BROWSER_INVALIDID((sal_uInt16) 0xFFFF))
3159 ? 1 // there is no visible column -> insert behind the handle col
3160 : GetViewColumnPos( m_aColumns[ nNextNonHidden ]->GetId() ) + 1;
3161 // the first non-handle col has "view pos" 0, but the pos arg for InsertDataColumn expects
3162 // a position 1 for the first non-handle col -> +1
3163 DBG_ASSERT(nNewViewPos != GRID_COLUMN_NOT_FOUND, "DbGridControl::ShowColumn : inconsistent internal state !")do { if (true && (!(nNewViewPos != ((sal_uInt16) 0xFFFF
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3163" ": "), "%s", "DbGridControl::ShowColumn : inconsistent internal state !"
); } } while (false)
;
3164 // we found a col marked as visible but got no view pos for it ...
3165
3166 if ((nNextNonHidden<nPos) && (nNextNonHidden != BROWSER_INVALIDID((sal_uInt16) 0xFFFF)))
3167 // nNextNonHidden is a column to the left, so we want to insert the new col _right_ beside it's pos
3168 ++nNewViewPos;
3169
3170 DeactivateCell();
3171
3172 OUString aName;
3173 pColumn->getModel()->getPropertyValue(FM_PROP_LABEL"Label") >>= aName;
3174 InsertDataColumn(nId, aName, CalcZoom(pColumn->m_nLastVisibleWidth), HeaderBarItemBits::CENTER | HeaderBarItemBits::CLICKABLE, nNewViewPos);
3175 pColumn->m_bHidden = false;
3176
3177 ActivateCell();
3178 Invalidate();
3179}
3180
3181sal_uInt16 DbGridControl::GetColumnIdFromModelPos( sal_uInt16 nPos ) const
3182{
3183 if (nPos >= m_aColumns.size())
3184 {
3185 OSL_FAIL("DbGridControl::GetColumnIdFromModelPos : invalid argument !")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3185" ": "), "%s", "DbGridControl::GetColumnIdFromModelPos : invalid argument !"
); } } while (false)
;
3186 return GRID_COLUMN_NOT_FOUND((sal_uInt16) 0xFFFF);
3187 }
3188
3189 DbGridColumn* pCol = m_aColumns[ nPos ].get();
3190#if (OSL_DEBUG_LEVEL1 > 0) || defined DBG_UTIL
3191 // in the debug version, we convert the ModelPos into a ViewPos and compare this with the
3192 // value we will return (nId at the corresponding Col in m_aColumns)
3193
3194 if (!pCol->IsHidden())
3195 { // makes sense only if the column is visible
3196 sal_uInt16 nViewPos = nPos;
3197 for ( size_t i = 0; i < m_aColumns.size() && i < nPos; ++i)
3198 if ( m_aColumns[ i ]->IsHidden())
3199 --nViewPos;
3200
3201 DBG_ASSERT(pCol && GetColumnIdFromViewPos(nViewPos) == pCol->GetId(),do { if (true && (!(pCol && GetColumnIdFromViewPos
(nViewPos) == pCol->GetId()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3202" ": "), "%s", "DbGridControl::GetColumnIdFromModelPos : this isn't consistent... did I misunderstand something ?"
); } } while (false)
3202 "DbGridControl::GetColumnIdFromModelPos : this isn't consistent... did I misunderstand something ?")do { if (true && (!(pCol && GetColumnIdFromViewPos
(nViewPos) == pCol->GetId()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3202" ": "), "%s", "DbGridControl::GetColumnIdFromModelPos : this isn't consistent... did I misunderstand something ?"
); } } while (false)
;
3203 }
3204#endif
3205 return pCol->GetId();
3206}
3207
3208sal_uInt16 DbGridControl::GetModelColumnPos( sal_uInt16 nId ) const
3209{
3210 for ( size_t i = 0; i < m_aColumns.size(); ++i )
3211 if ( m_aColumns[ i ]->GetId() == nId )
3212 return i;
3213
3214 return GRID_COLUMN_NOT_FOUND((sal_uInt16) 0xFFFF);
3215}
3216
3217void DbGridControl::implAdjustInSolarThread(bool _bRows)
3218{
3219 SAL_INFO("svx.fmcomp", "DbGridControl::implAdjustInSolarThread")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "DbGridControl::implAdjustInSolarThread"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3219" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::implAdjustInSolarThread"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "DbGridControl::implAdjustInSolarThread"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3219" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "DbGridControl::implAdjustInSolarThread") == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3219" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "DbGridControl::implAdjustInSolarThread"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "DbGridControl::implAdjustInSolarThread"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3219" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3220 ::osl::MutexGuard aGuard(m_aAdjustSafety);
3221 if (!Application::IsMainThread())
3222 {
3223 m_nAsynAdjustEvent = PostUserEvent(LINK(this, DbGridControl, OnAsyncAdjust)::tools::detail::makeLink( ::tools::detail::castTo<DbGridControl
*>(this), &DbGridControl::LinkStubOnAsyncAdjust)
, reinterpret_cast< void* >( _bRows ), true);
3224 m_bPendingAdjustRows = _bRows;
3225 if (_bRows)
3226 SAL_INFO("svx.fmcomp", "posting an AdjustRows")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "posting an AdjustRows"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3226" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "posting an AdjustRows"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"posting an AdjustRows"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3226" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "posting an AdjustRows") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3226" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "posting an AdjustRows"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"posting an AdjustRows"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3226" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3227 else
3228 SAL_INFO("svx.fmcomp", "posting an AdjustDataSource")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "posting an AdjustDataSource"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3228" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "posting an AdjustDataSource"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "posting an AdjustDataSource"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3228" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "posting an AdjustDataSource") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3228" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "posting an AdjustDataSource"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "posting an AdjustDataSource"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3228" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3229 }
3230 else
3231 {
3232 if (_bRows)
3233 SAL_INFO("svx.fmcomp", "doing an AdjustRows")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "doing an AdjustRows"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3233" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "doing an AdjustRows"), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"doing an AdjustRows"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3233" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "doing an AdjustRows") == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3233" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "doing an AdjustRows"), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"doing an AdjustRows"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3233" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3234 else
3235 SAL_INFO("svx.fmcomp", "doing an AdjustDataSource")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "doing an AdjustDataSource"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3235" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "doing an AdjustDataSource"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"doing an AdjustDataSource"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3235" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "doing an AdjustDataSource") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3235" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "doing an AdjustDataSource"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"doing an AdjustDataSource"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3235" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3236 // always adjust the rows before adjusting the data source
3237 // If this is not necessary (because the row count did not change), nothing is done
3238 // The problem is that we can't rely on the order of which the calls come in: If the cursor was moved
3239 // to a position behind row count know 'til now, the cursorMoved notification may come before the
3240 // RowCountChanged notification
3241 // 94093 - 02.11.2001 - frank.schoenheit@sun.com
3242 AdjustRows();
3243
3244 if ( !_bRows )
3245 AdjustDataSource();
3246 }
3247}
3248
3249IMPL_LINK(DbGridControl, OnAsyncAdjust, void*, pAdjustWhat, void)void DbGridControl::LinkStubOnAsyncAdjust(void * instance, void
* data) { return static_cast<DbGridControl *>(instance)
->OnAsyncAdjust(data); } void DbGridControl::OnAsyncAdjust
(void* pAdjustWhat)
3250{
3251 m_nAsynAdjustEvent = nullptr;
3252
3253 AdjustRows();
3254 // see implAdjustInSolarThread for a comment why we do this every time
3255
3256 if ( !pAdjustWhat )
3257 AdjustDataSource();
3258}
3259
3260void DbGridControl::BeginCursorAction()
3261{
3262 if (m_pFieldListeners)
3263 {
3264 ColumnFieldValueListeners* pListeners = static_cast<ColumnFieldValueListeners*>(m_pFieldListeners);
3265 for (const auto& rListener : *pListeners)
3266 {
3267 GridFieldValueListener* pCurrent = rListener.second;
3268 if (pCurrent)
3269 pCurrent->suspend();
3270 }
3271 }
3272
3273 if (m_pDataSourcePropListener)
3274 m_pDataSourcePropListener->suspend();
3275}
3276
3277void DbGridControl::EndCursorAction()
3278{
3279 if (m_pFieldListeners)
3280 {
3281 ColumnFieldValueListeners* pListeners = static_cast<ColumnFieldValueListeners*>(m_pFieldListeners);
3282 for (const auto& rListener : *pListeners)
3283 {
3284 GridFieldValueListener* pCurrent = rListener.second;
3285 if (pCurrent)
3286 pCurrent->resume();
3287 }
3288 }
3289
3290 if (m_pDataSourcePropListener)
3291 m_pDataSourcePropListener->resume();
3292}
3293
3294void DbGridControl::ConnectToFields()
3295{
3296 ColumnFieldValueListeners* pListeners = static_cast<ColumnFieldValueListeners*>(m_pFieldListeners);
3297 DBG_ASSERT(!pListeners || pListeners->empty(), "DbGridControl::ConnectToFields : please call DisconnectFromFields first !")do { if (true && (!(!pListeners || pListeners->empty
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3297" ": "), "%s", "DbGridControl::ConnectToFields : please call DisconnectFromFields first !"
); } } while (false)
;
3298
3299 if (!pListeners)
3300 {
3301 pListeners = new ColumnFieldValueListeners;
3302 m_pFieldListeners = pListeners;
3303 }
3304
3305 for (auto const & pCurrent : m_aColumns)
3306 {
3307 sal_uInt16 nViewPos = pCurrent ? GetViewColumnPos(pCurrent->GetId()) : GRID_COLUMN_NOT_FOUND((sal_uInt16) 0xFFFF);
3308 if (GRID_COLUMN_NOT_FOUND((sal_uInt16) 0xFFFF) == nViewPos)
3309 continue;
3310
3311 Reference< XPropertySet > xField = pCurrent->GetField();
3312 if (!xField.is())
3313 continue;
3314
3315 // column is visible and bound here
3316 GridFieldValueListener*& rpListener = (*pListeners)[pCurrent->GetId()];
3317 DBG_ASSERT(!rpListener, "DbGridControl::ConnectToFields : already a listener for this column ?!")do { if (true && (!(!rpListener))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3317" ": "), "%s", "DbGridControl::ConnectToFields : already a listener for this column ?!"
); } } while (false)
;
3318 rpListener = new GridFieldValueListener(*this, xField, pCurrent->GetId());
3319 }
3320}
3321
3322void DbGridControl::DisconnectFromFields()
3323{
3324 if (!m_pFieldListeners)
3325 return;
3326
3327 ColumnFieldValueListeners* pListeners = static_cast<ColumnFieldValueListeners*>(m_pFieldListeners);
3328 while (!pListeners->empty())
3329 {
3330 sal_Int32 nOldSize = pListeners->size();
3331 pListeners->begin()->second->dispose();
3332 DBG_ASSERT(nOldSize > static_cast<sal_Int32>(pListeners->size()), "DbGridControl::DisconnectFromFields : dispose on a listener should result in a removal from my list !")do { if (true && (!(nOldSize > static_cast<sal_Int32
>(pListeners->size())))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3332" ": "), "%s", "DbGridControl::DisconnectFromFields : dispose on a listener should result in a removal from my list !"
); } } while (false)
;
3333 }
3334
3335 delete pListeners;
3336 m_pFieldListeners = nullptr;
3337}
3338
3339void DbGridControl::FieldValueChanged(sal_uInt16 _nId)
3340{
3341 osl::MutexGuard aPreventDestruction(m_aDestructionSafety);
3342 // needed as this may run in a thread other than the main one
3343 if (GetRowStatus(GetCurRow()) != EditBrowseBox::MODIFIED)
3344 // all other cases are handled elsewhere
3345 return;
3346
3347 size_t Location = GetModelColumnPos( _nId );
3348 DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ].get() : nullptr;
3349 if (!pColumn)
3350 return;
3351
3352 std::unique_ptr<vcl::SolarMutexTryAndBuyGuard> pGuard;
3353 while (!m_bWantDestruction && (!pGuard || !pGuard->isAcquired()))
3354 pGuard.reset(new vcl::SolarMutexTryAndBuyGuard);
3355
3356 if (m_bWantDestruction)
3357 { // at this moment, within another thread, our destructor tries to destroy the listener which called this method
3358 // => don't do anything
3359 // 73365 - 23.02.00 - FS
3360 return;
3361 }
3362
3363 // and finally do the update ...
3364 pColumn->UpdateFromField(m_xCurrentRow.get(), m_xFormatter);
3365 RowModified(GetCurRow());
3366}
3367
3368void DbGridControl::FieldListenerDisposing(sal_uInt16 _nId)
3369{
3370 ColumnFieldValueListeners* pListeners = static_cast<ColumnFieldValueListeners*>(m_pFieldListeners);
3371 if (!pListeners)
3372 {
3373 OSL_FAIL("DbGridControl::FieldListenerDisposing : invalid call (have no listener array) !")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3373" ": "), "%s", "DbGridControl::FieldListenerDisposing : invalid call (have no listener array) !"
); } } while (false)
;
3374 return;
3375 }
3376
3377 ColumnFieldValueListeners::const_iterator aPos = pListeners->find(_nId);
3378 if (aPos == pListeners->end())
3379 {
3380 OSL_FAIL("DbGridControl::FieldListenerDisposing : invalid call (did not find the listener) !")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/gridctrl.cxx"
":" "3380" ": "), "%s", "DbGridControl::FieldListenerDisposing : invalid call (did not find the listener) !"
); } } while (false)
;
3381 return;
3382 }
3383
3384 delete aPos->second;
3385
3386 pListeners->erase(aPos);
3387}
3388
3389void DbGridControl::disposing(sal_uInt16 _nId)
3390{
3391 if (_nId == 0)
3392 { // the seek cursor is being disposed
3393 ::osl::MutexGuard aGuard(m_aAdjustSafety);
3394 setDataSource(nullptr, DbGridControlOptions::Readonly); // our clone was disposed so we set our datasource to null to avoid later access to it
3395 if (m_nAsynAdjustEvent)
3396 {
3397 RemoveUserEvent(m_nAsynAdjustEvent);
3398 m_nAsynAdjustEvent = nullptr;
3399 }
3400 }
3401}
3402
3403sal_Int32 DbGridControl::GetAccessibleControlCount() const
3404{
3405 return EditBrowseBox::GetAccessibleControlCount() + 1; // the navigation control
3406}
3407
3408Reference<XAccessible > DbGridControl::CreateAccessibleControl( sal_Int32 _nIndex )
3409{
3410 Reference<XAccessible > xRet;
3411 if ( _nIndex == EditBrowseBox::GetAccessibleControlCount() )
3412 {
3413 xRet = m_aBar->GetAccessible();
3414 }
3415 else
3416 xRet = EditBrowseBox::CreateAccessibleControl( _nIndex );
3417 return xRet;
3418}
3419
3420Reference< XAccessible > DbGridControl::CreateAccessibleCell( sal_Int32 _nRow, sal_uInt16 _nColumnPos )
3421{
3422 sal_uInt16 nColumnId = GetColumnId( _nColumnPos );
3423 size_t Location = GetModelColumnPos(nColumnId);
3424 DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ].get() : nullptr;
3425 if ( pColumn )
3426 {
3427 Reference< css::awt::XControl> xInt(pColumn->GetCell());
3428 Reference< css::awt::XCheckBox> xBox(xInt,UNO_QUERY);
3429 if ( xBox.is() )
3430 {
3431 TriState eValue = TRISTATE_FALSE;
3432 switch( xBox->getState() )
3433 {
3434 case 0:
3435 eValue = TRISTATE_FALSE;
3436 break;
3437 case 1:
3438 eValue = TRISTATE_TRUE;
3439 break;
3440 case 2:
3441 eValue = TRISTATE_INDET;
3442 break;
3443 }
3444 return EditBrowseBox::CreateAccessibleCheckBoxCell( _nRow, _nColumnPos,eValue );
3445 }
3446 }
3447 return EditBrowseBox::CreateAccessibleCell( _nRow, _nColumnPos );
3448}
3449
3450/* 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);
7
Calling copy constructor for 'Reference<NavigationBar>'
10
Returning from copy constructor for 'Reference<NavigationBar>'
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
11
Calling 'Reference::clear'
18
Returning; memory was released
205 if (aTmp.get()) {
19
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)
8
Assuming field 'm_pBody' is non-null
9
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
11.1
Field 'm_pBody' is non-null
11.1
Field 'm_pBody' is non-null
11.1
Field 'm_pBody' is non-null
11.1
Field 'm_pBody' is non-null
)
12
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
13
Calling 'VclReferenceBase::release'
17
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;
20
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)
14
Assuming the condition is true
15
Taking true branch
40 delete this;
16
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