File: | home/maarten/src/libreoffice/core/include/rtl/ref.hxx |
Warning: | line 192, column 9 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
67 | using namespace ::dbtools; | |||
68 | using namespace ::dbtools::DBTypeConversion; | |||
69 | using namespace ::svxform; | |||
70 | using namespace ::svt; | |||
71 | using namespace ::com::sun::star::beans; | |||
72 | using namespace ::com::sun::star::lang; | |||
73 | using namespace ::com::sun::star::uno; | |||
74 | using namespace ::com::sun::star::sdbc; | |||
75 | using namespace ::com::sun::star::sdbcx; | |||
76 | using namespace ::com::sun::star::sdb; | |||
77 | using namespace ::com::sun::star::datatransfer; | |||
78 | using namespace ::com::sun::star::container; | |||
79 | using 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 | ||||
83 | constexpr 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 | ||||
92 | class RowSetEventListener : public ::cppu::WeakImplHelper<XRowsChangeListener> | |||
93 | { | |||
94 | VclPtr<DbGridControl> m_pControl; | |||
95 | public: | |||
96 | explicit RowSetEventListener(DbGridControl* i_pControl) : m_pControl(i_pControl) | |||
97 | { | |||
98 | } | |||
99 | ||||
100 | private: | |||
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 | ||||
125 | class GridFieldValueListener; | |||
126 | typedef std::map<sal_uInt16, GridFieldValueListener*> ColumnFieldValueListeners; | |||
127 | ||||
128 | class 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 | ||||
137 | public: | |||
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 | ||||
149 | GridFieldValueListener::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 | ||||
163 | GridFieldValueListener::~GridFieldValueListener() | |||
164 | { | |||
165 | dispose(); | |||
166 | } | |||
167 | ||||
168 | void 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 | ||||
175 | void 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 | ||||
193 | class DisposeListenerGridBridge : public FmXDisposeListener | |||
194 | { | |||
195 | DbGridControl& m_rParent; | |||
196 | rtl::Reference<FmXDisposeMultiplexer> m_xRealListener; | |||
197 | ||||
198 | public: | |||
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 | ||||
205 | DisposeListenerGridBridge::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 | ||||
216 | DisposeListenerGridBridge::~DisposeListenerGridBridge() | |||
217 | { | |||
218 | if (m_xRealListener.is()) | |||
219 | { | |||
220 | m_xRealListener->dispose(); | |||
221 | } | |||
222 | } | |||
223 | ||||
224 | const 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 | ||||
238 | bool CompareBookmark(const Any& aLeft, const Any& aRight) | |||
239 | { | |||
240 | return aLeft == aRight; | |||
241 | } | |||
242 | ||||
243 | class 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 | ||||
251 | public: | |||
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 | ||||
260 | FmXGridSourcePropListener::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 | ||||
268 | void 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 | ||||
275 | const int nReserveNumDigits = 7; | |||
276 | ||||
277 | NavigationBar::AbsolutePos::AbsolutePos(std::unique_ptr<weld::Entry> xEntry, NavigationBar* pBar) | |||
278 | : RecordItemWindowBase(std::move(xEntry)) | |||
279 | , m_xParent(pBar) | |||
280 | { | |||
281 | } | |||
282 | ||||
283 | bool 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 | ||||
293 | void NavigationBar::AbsolutePos::PositionFired(sal_Int64 nRecord) | |||
294 | { | |||
295 | m_xParent->PositionDataSource(nRecord); | |||
296 | m_xParent->InvalidateState(DbGridControlNavigationBarState::Absolute); | |||
297 | } | |||
298 | ||||
299 | void 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 | ||||
310 | NavigationBar::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 | ||||
366 | NavigationBar::~NavigationBar() | |||
367 | { | |||
368 | disposeOnce(); | |||
369 | } | |||
370 | ||||
371 | void 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 | ||||
385 | sal_uInt16 NavigationBar::ArrangeControls() | |||
386 | { | |||
387 | return m_xContainer->get_preferred_size().Width(); | |||
388 | } | |||
389 | ||||
390 | IMPL_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 | ||||
395 | IMPL_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 | ||||
400 | IMPL_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 | ||||
411 | IMPL_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 | ||||
417 | IMPL_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 | ||||
427 | IMPL_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 | ||||
433 | IMPL_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 | ||||
468 | void 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 | ||||
498 | bool 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 | ||||
553 | void 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 | ||||
641 | DbGridRow::DbGridRow():m_eStatus(GridRowStatus::Clean), m_bIsNew(true) | |||
642 | {} | |||
643 | ||||
644 | DbGridRow::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 | ||||
690 | DbGridRow::~DbGridRow() | |||
691 | { | |||
692 | } | |||
693 | ||||
694 | void 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 | ||||
742 | DbGridControl::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 | ||||
781 | void 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 | ||||
790 | void 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 | ||||
802 | DbGridControl::~DbGridControl() | |||
803 | { | |||
804 | disposeOnce(); | |||
805 | } | |||
806 | ||||
807 | void DbGridControl::dispose() | |||
808 | { | |||
809 | if (!IsDisposed()) | |||
| ||||
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) | |||
821 | Application::RemoveUserEvent(m_nDeleteEvent); | |||
822 | ||||
823 | if (m_pDataSourcePropMultiplexer.is()) | |||
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(); | |||
836 | ||||
837 | EditBrowseBox::dispose(); | |||
838 | } | |||
839 | ||||
840 | void 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 | ||||
878 | void 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 | ||||
889 | void 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 | ||||
900 | void 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 | ||||
944 | void 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 | ||||
963 | void 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 | ||||
986 | void 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 | ||||
997 | void 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 | ||||
1008 | namespace | |||
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 | ||||
1042 | void 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 | ||||
1077 | DbGridControlOptions 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 | ||||
1156 | void 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 | ||||
1167 | void 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 | ||||
1194 | bool DbGridControl::IsPermanentCursorEnabled() const | |||
1195 | { | |||
1196 | return (m_nMode & BrowserMode::CURSOR_WO_FOCUS) && !(m_nMode & BrowserMode::HIDECURSOR); | |||
1197 | } | |||
1198 | ||||
1199 | void 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 | ||||
1208 | void 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 | ||||
1438 | void DbGridControl::RemoveColumns() | |||
1439 | { | |||
1440 | if ( IsEditing() ) | |||
1441 | DeactivateCell(); | |||
1442 | ||||
1443 | m_aColumns.clear(); | |||
1444 | ||||
1445 | EditBrowseBox::RemoveColumns(); | |||
1446 | } | |||
1447 | ||||
1448 | std::unique_ptr<DbGridColumn> DbGridControl::CreateColumn(sal_uInt16 nId) | |||
1449 | { | |||
1450 | return std::unique_ptr<DbGridColumn>(new DbGridColumn(nId, *this)); | |||
1451 | } | |||
1452 | ||||
1453 | sal_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 | ||||
1488 | void 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 | ||||
1499 | void 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 | ||||
1593 | bool 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 | |||
1626 | void DbGridControl::VisibleRowsChanged( long nNewTopRow, sal_uInt16 nLinesOnScreen ) | |||
1627 | { | |||
1628 | RecalcRows(nNewTopRow, nLinesOnScreen, false); | |||
1629 | } | |||
1630 | ||||
1631 | void 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 | ||||
1687 | void 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 | ||||
1707 | void 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 | ||||
1726 | void 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 | ||||
1789 | svt::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 | ||||
1813 | void 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 | ||||
1832 | bool 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 | ||||
1849 | bool 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 | ||||
1934 | void 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 | ||||
1962 | void DbGridControl::onRowChange() | |||
1963 | { | |||
1964 | // not interested in | |||
1965 | } | |||
1966 | ||||
1967 | void DbGridControl::onColumnChange() | |||
1968 | { | |||
1969 | if ( m_pGridListener ) | |||
1970 | m_pGridListener->columnChanged(); | |||
1971 | } | |||
1972 | ||||
1973 | void DbGridControl::setDisplaySynchron(bool bSync) | |||
1974 | { | |||
1975 | if (bSync != m_bSynchDisplay) | |||
1976 | { | |||
1977 | m_bSynchDisplay = bSync; | |||
1978 | if (m_bSynchDisplay) | |||
1979 | AdjustDataSource(); | |||
1980 | } | |||
1981 | } | |||
1982 | ||||
1983 | void 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 | ||||
2053 | sal_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 | ||||
2104 | bool 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 | ||||
2230 | void DbGridControl::MoveToFirst() | |||
2231 | { | |||
2232 | if (m_pSeekCursor && (GetCurRow() != 0)) | |||
2233 | MoveToPosition(0); | |||
2234 | } | |||
2235 | ||||
2236 | void 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 | ||||
2268 | void DbGridControl::MoveToPrev() | |||
2269 | { | |||
2270 | long nNewRow = std::max(GetCurRow() - 1, 0L); | |||
2271 | if (GetCurRow() != nNewRow) | |||
2272 | MoveToPosition(nNewRow); | |||
2273 | } | |||
2274 | ||||
2275 | void 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 | ||||
2317 | void 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 | ||||
2346 | void 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 | ||||
2374 | void 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 | ||||
2402 | void 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 | ||||
2435 | OUString 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 | ||||
2445 | OUString 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 | ||||
2454 | sal_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 | ||||
2466 | void 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 | ||||
2485 | void 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 | ||||
2500 | void 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 | ||||
2552 | void 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 | ||||
2571 | bool 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 | ||||
2579 | void 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 | ||||
2587 | void 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 | ||||
2597 | void 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 | ||||
2650 | IMPL_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 | ||||
2656 | void 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 | ||||
2664 | CellController* 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 | ||||
2696 | void 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 | ||||
2745 | void 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 | ||||
2758 | void 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 | ||||
2821 | void 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 | ||||
2857 | void 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 | ||||
2868 | bool DbGridControl::IsModified() const | |||
2869 | { | |||
2870 | return !IsFilterMode() && IsValid(m_xCurrentRow) && (m_xCurrentRow->IsModified() || EditBrowseBox::IsModified()); | |||
2871 | } | |||
2872 | ||||
2873 | bool DbGridControl::IsCurrentAppending() const | |||
2874 | { | |||
2875 | return m_xCurrentRow.is() && m_xCurrentRow->IsNew(); | |||
2876 | } | |||
2877 | ||||
2878 | bool DbGridControl::IsInsertionRow(long nRow) const | |||
2879 | { | |||
2880 | return (m_nOptions & DbGridControlOptions::Insert) && m_nTotalCount >= 0 && (nRow == GetRowCount() - 1); | |||
2881 | } | |||
2882 | ||||
2883 | bool 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 | ||||
2927 | bool 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 | ||||
3000 | bool 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 | ||||
3057 | bool 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 | ||||
3070 | void 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 | ||||
3087 | void 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 | ||||
3116 | void 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 | ||||
3181 | sal_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 | ||||
3208 | sal_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 | ||||
3217 | void 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 | ||||
3249 | IMPL_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 | ||||
3260 | void 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 | ||||
3277 | void 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 | ||||
3294 | void 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 | ||||
3322 | void 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 | ||||
3339 | void 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 | ||||
3368 | void 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 | ||||
3389 | void 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 | ||||
3403 | sal_Int32 DbGridControl::GetAccessibleControlCount() const | |||
3404 | { | |||
3405 | return EditBrowseBox::GetAccessibleControlCount() + 1; // the navigation control | |||
3406 | } | |||
3407 | ||||
3408 | Reference<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 | ||||
3420 | Reference< 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: */ |
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 | |
36 | class VclReferenceBase; |
37 | |
38 | namespace vcl::detail { |
39 | |
40 | template<typename> |
41 | constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; } |
42 | |
43 | template<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 | */ |
56 | template <class reference_type> |
57 | class 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 | |
66 | public: |
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); |
204 | m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-) |
205 | if (aTmp.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 | |
218 | template<typename T1, typename T2> |
219 | inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) { |
220 | return p1.get() == p2.get(); |
221 | } |
222 | |
223 | template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2) |
224 | { |
225 | return p1.get() == p2; |
226 | } |
227 | |
228 | template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) { |
229 | return p1.get() == p2; |
230 | } |
231 | |
232 | template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2) |
233 | { |
234 | return p1 == p2.get(); |
235 | } |
236 | |
237 | template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) { |
238 | return p1 == p2.get(); |
239 | } |
240 | |
241 | template<typename T1, typename T2> |
242 | inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) { |
243 | return !(p1 == p2); |
244 | } |
245 | |
246 | template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2) |
247 | { |
248 | return !(p1 == p2); |
249 | } |
250 | |
251 | template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) { |
252 | return !(p1 == p2); |
253 | } |
254 | |
255 | template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2) |
256 | { |
257 | return !(p1 == p2); |
258 | } |
259 | |
260 | template<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 | */ |
274 | template <class reference_type> |
275 | class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type> |
276 | { |
277 | public: |
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 | |
290 | template <class reference_type> |
291 | class ScopedVclPtr : public VclPtr<reference_type> |
292 | { |
293 | public: |
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 | |
378 | private: |
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 | |
387 | protected: |
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 |
406 | template <class reference_type> |
407 | class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type> |
408 | { |
409 | public: |
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 | |
421 | private: |
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: */ |
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 | |||||||||
34 | namespace rtl | ||||||||
35 | { | ||||||||
36 | |||||||||
37 | /** Template reference class for reference type. | ||||||||
38 | */ | ||||||||
39 | template <class reference_type> | ||||||||
40 | class Reference | ||||||||
41 | { | ||||||||
42 | /** The <b>reference_type</b> body pointer. | ||||||||
43 | */ | ||||||||
44 | reference_type * m_pBody; | ||||||||
45 | |||||||||
46 | |||||||||
47 | public: | ||||||||
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) | ||||||||
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
| ||||||||
177 | { | ||||||||
178 | reference_type * const pOld = m_pBody; | ||||||||
179 | m_pBody = NULL__null; | ||||||||
180 | pOld->release(); | ||||||||
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; | ||||||||
| |||||||||
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 | ||||||||
277 | namespace 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 | */ | ||||||||
286 | template<typename T> | ||||||||
287 | struct 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: */ |
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 | |
25 | class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase |
26 | { |
27 | mutable oslInterlockedCount mnRefCnt; |
28 | |
29 | template<typename T> friend class VclPtr; |
30 | |
31 | public: |
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) |
40 | delete this; |
41 | } |
42 | #ifdef DBG_UTIL |
43 | #ifndef _WIN32 |
44 | sal_Int32 getRefCount() const { return mnRefCnt; } |
45 | #endif |
46 | #endif |
47 | |
48 | |
49 | private: |
50 | VclReferenceBase(const VclReferenceBase&) = delete; |
51 | VclReferenceBase& operator=(const VclReferenceBase&) = delete; |
52 | |
53 | bool mbDisposed : 1; |
54 | |
55 | protected: |
56 | VclReferenceBase(); |
57 | protected: |
58 | virtual ~VclReferenceBase(); |
59 | |
60 | protected: |
61 | virtual void dispose(); |
62 | |
63 | public: |
64 | void disposeOnce(); |
65 | bool isDisposed() const { return mbDisposed; } |
66 | |
67 | }; |
68 | #endif |