Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <sal/macros.h>
31 : : #include "fmhelp.hrc"
32 : : #include <svx/gridctrl.hxx>
33 : : #include "gridcell.hxx"
34 : : #include "svx/dbtoolsclient.hxx"
35 : : #include "svx/fmtools.hxx"
36 : : #include <svtools/stringtransfer.hxx>
37 : :
38 : : #include "fmprop.hrc"
39 : : #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
40 : : #include <com/sun/star/accessibility/XAccessible.hpp>
41 : : #include <com/sun/star/sdb/XResultSetAccess.hpp>
42 : : #include <com/sun/star/sdb/RowChangeAction.hpp>
43 : : #include <com/sun/star/sdb/XRowsChangeBroadcaster.hpp>
44 : : #include <com/sun/star/sdbc/XResultSetUpdate.hpp>
45 : : #include <com/sun/star/sdbcx/Privilege.hpp>
46 : : #include <com/sun/star/container/XChild.hpp>
47 : : #include <com/sun/star/util/XNumberFormatter.hpp>
48 : : #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
49 : : #include <com/sun/star/util/XCloneable.hpp>
50 : : #include <com/sun/star/beans/XPropertySet.hpp>
51 : : #include <com/sun/star/beans/PropertyChangeEvent.hpp>
52 : : #include <comphelper/extract.hxx>
53 : : #include <tools/resid.hxx>
54 : : #include <tools/diagnose_ex.h>
55 : : #include <vcl/menu.hxx>
56 : :
57 : : #include "svx/fmresids.hrc"
58 : :
59 : : #include <svx/svxids.hrc>
60 : : #include <tools/shl.hxx>
61 : : #include <svx/dialmgr.hxx>
62 : : #include "fmservs.hxx"
63 : : #include "sdbdatacolumn.hxx"
64 : :
65 : : #include <comphelper/stl_types.hxx>
66 : : #include <comphelper/property.hxx>
67 : : #include "trace.hxx"
68 : :
69 : : #include <algorithm>
70 : :
71 : : using namespace ::svxform;
72 : : using namespace ::svt;
73 : : using namespace ::com::sun::star::beans;
74 : : using namespace ::com::sun::star::lang;
75 : : using namespace ::com::sun::star::uno;
76 : : using namespace ::com::sun::star::sdbc;
77 : : using namespace ::com::sun::star::sdbcx;
78 : : using namespace ::com::sun::star::sdb;
79 : : using namespace ::com::sun::star::datatransfer;
80 : : using namespace ::com::sun::star::container;
81 : : using namespace com::sun::star::accessibility;
82 : :
83 : : #define ROWSTATUS(row) !row.Is() ? "NULL" : row->GetStatus() == GRS_CLEAN ? "CLEAN" : row->GetStatus() == GRS_MODIFIED ? "MODIFIED" : row->GetStatus() == GRS_DELETED ? "DELETED" : "INVALID"
84 : :
85 : :
86 : : #define DEFAULT_BROWSE_MODE \
87 : : BROWSER_COLUMNSELECTION \
88 : : | BROWSER_MULTISELECTION \
89 : : | BROWSER_KEEPSELECTION \
90 : : | BROWSER_TRACKING_TIPS \
91 : : | BROWSER_HLINESFULL \
92 : : | BROWSER_VLINESFULL \
93 : : | BROWSER_HEADERBAR_NEW \
94 : :
95 [ - + ]: 4 : class RowSetEventListener : public ::cppu::WeakImplHelper1<XRowsChangeListener>
96 : : {
97 : : DbGridControl* m_pControl;
98 : : public:
99 : 2 : RowSetEventListener(DbGridControl* i_pControl) : m_pControl(i_pControl)
100 : : {
101 : 2 : }
102 : : private:
103 : : // XEventListener
104 : 2 : virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& /*i_aEvt*/) throw ( RuntimeException )
105 : : {
106 : 2 : }
107 : 0 : virtual void SAL_CALL rowsChanged(const ::com::sun::star::sdb::RowsChangeEvent& i_aEvt) throw ( RuntimeException )
108 : : {
109 [ # # ]: 0 : if ( i_aEvt.Action == RowChangeAction::UPDATE )
110 : : {
111 : 0 : ::DbGridControl::GrantControlAccess aAccess;
112 : 0 : CursorWrapper* pSeek = m_pControl->GetSeekCursor(aAccess);
113 : 0 : const DbGridRowRef& rSeekRow = m_pControl->GetSeekRow(aAccess);
114 : 0 : const Any* pIter = i_aEvt.Bookmarks.getConstArray();
115 : 0 : const Any* pEnd = pIter + i_aEvt.Bookmarks.getLength();
116 [ # # ]: 0 : for(;pIter != pEnd;++pIter)
117 : : {
118 [ # # ]: 0 : pSeek->moveToBookmark(*pIter);
119 : : // get the data
120 [ # # ]: 0 : rSeekRow->SetState(pSeek, sal_True);
121 [ # # ]: 0 : sal_Int32 nSeekPos = pSeek->getRow() - 1;
122 : 0 : m_pControl->SetSeekPos(nSeekPos,aAccess);
123 [ # # ]: 0 : m_pControl->RowModified(nSeekPos);
124 : : }
125 : : }
126 : 0 : }
127 : : };
128 : : //==============================================================================
129 : :
130 : : class GridFieldValueListener;
131 : : DECLARE_STL_MAP(sal_uInt16, GridFieldValueListener*, ::std::less<sal_uInt16>, ColumnFieldValueListeners);
132 : :
133 : : //==============================================================================
134 : :
135 : : DBG_NAME(GridFieldValueListener)
136 : : class GridFieldValueListener : protected ::comphelper::OPropertyChangeListener
137 : : {
138 : : osl::Mutex m_aMutex;
139 : : DbGridControl& m_rParent;
140 : : ::comphelper::OPropertyChangeMultiplexer* m_pRealListener;
141 : : sal_uInt16 m_nId;
142 : : sal_Int16 m_nSuspended;
143 : : sal_Bool m_bDisposed : 1;
144 : :
145 : : public:
146 : : GridFieldValueListener(DbGridControl& _rParent, const Reference< XPropertySet >& xField, sal_uInt16 _nId);
147 : : virtual ~GridFieldValueListener();
148 : :
149 : : virtual void _propertyChanged(const PropertyChangeEvent& evt) throw( RuntimeException );
150 : :
151 : 62 : void suspend() { ++m_nSuspended; }
152 : 62 : void resume() { --m_nSuspended; }
153 : :
154 : : void dispose();
155 : : };
156 : : //------------------------------------------------------------------------------
157 : 62 : GridFieldValueListener::GridFieldValueListener(DbGridControl& _rParent, const Reference< XPropertySet >& _rField, sal_uInt16 _nId)
158 : : :OPropertyChangeListener(m_aMutex)
159 : : ,m_rParent(_rParent)
160 : : ,m_pRealListener(NULL)
161 : : ,m_nId(_nId)
162 : : ,m_nSuspended(0)
163 [ + - ]: 62 : ,m_bDisposed(sal_False)
164 : : {
165 : : DBG_CTOR(GridFieldValueListener, NULL);
166 [ + - ]: 62 : if (_rField.is())
167 : : {
168 [ + - ]: 62 : m_pRealListener = new ::comphelper::OPropertyChangeMultiplexer(this, _rField);
169 [ + - ][ + - ]: 62 : m_pRealListener->addProperty(FM_PROP_VALUE);
170 : 62 : m_pRealListener->acquire();
171 : : }
172 : 62 : }
173 : :
174 : : //------------------------------------------------------------------------------
175 [ + - ]: 62 : GridFieldValueListener::~GridFieldValueListener()
176 : : {
177 : : DBG_DTOR(GridFieldValueListener, NULL);
178 [ + - ]: 62 : dispose();
179 [ - + ]: 124 : }
180 : :
181 : : //------------------------------------------------------------------------------
182 : 44 : void GridFieldValueListener::_propertyChanged(const PropertyChangeEvent& _evt) throw( RuntimeException )
183 : : {
184 : : DBG_ASSERT(m_nSuspended>=0, "GridFieldValueListener::_propertyChanged : resume > suspend !");
185 [ - + ]: 44 : if (m_nSuspended <= 0)
186 : 0 : m_rParent.FieldValueChanged(m_nId, _evt);
187 : 44 : }
188 : :
189 : : //------------------------------------------------------------------------------
190 : 124 : void GridFieldValueListener::dispose()
191 : : {
192 [ + + ]: 124 : if (m_bDisposed)
193 : : {
194 : : DBG_ASSERT(m_pRealListener == NULL, "GridFieldValueListener::dispose : inconsistent !");
195 : 124 : return;
196 : : }
197 : :
198 [ + - ]: 62 : if (m_pRealListener)
199 : : {
200 : 62 : m_pRealListener->dispose();
201 : 62 : m_pRealListener->release();
202 : 62 : m_pRealListener = NULL;
203 : : }
204 : :
205 : 62 : m_bDisposed = sal_True;
206 : 62 : m_rParent.FieldListenerDisposing(m_nId);
207 : : }
208 : :
209 : : //==============================================================================
210 : :
211 : : class DisposeListenerGridBridge : public FmXDisposeListener
212 : : {
213 : : osl::Mutex m_aMutex;
214 : : DbGridControl& m_rParent;
215 : : FmXDisposeMultiplexer* m_pRealListener;
216 : :
217 : : public:
218 : : DisposeListenerGridBridge( DbGridControl& _rParent, const Reference< XComponent >& _rxObject, sal_Int16 _rId = -1);
219 : : virtual ~DisposeListenerGridBridge();
220 : :
221 : 2 : virtual void disposing(const EventObject& _rEvent, sal_Int16 _nId) throw( RuntimeException ) { m_rParent.disposing(_nId, _rEvent); }
222 : : };
223 : :
224 : : //==============================================================================
225 : :
226 : :
227 : : DBG_NAME(DisposeListenerGridBridge)
228 : : //------------------------------------------------------------------------------
229 : 2 : DisposeListenerGridBridge::DisposeListenerGridBridge(DbGridControl& _rParent, const Reference< XComponent >& _rxObject, sal_Int16 _rId)
230 : : :FmXDisposeListener(m_aMutex)
231 : : ,m_rParent(_rParent)
232 [ + - ]: 2 : ,m_pRealListener(NULL)
233 : : {
234 : : DBG_CTOR(DisposeListenerGridBridge,NULL);
235 : :
236 [ + - ]: 2 : if (_rxObject.is())
237 : : {
238 [ + - ]: 2 : m_pRealListener = new FmXDisposeMultiplexer(this, _rxObject, _rId);
239 : 2 : m_pRealListener->acquire();
240 : : }
241 : 2 : }
242 : :
243 : : //------------------------------------------------------------------------------
244 [ + - ]: 2 : DisposeListenerGridBridge::~DisposeListenerGridBridge()
245 : : {
246 [ + - ]: 2 : if (m_pRealListener)
247 : : {
248 [ + - ]: 2 : m_pRealListener->dispose();
249 : 2 : m_pRealListener->release();
250 : 2 : m_pRealListener = NULL;
251 : : }
252 : :
253 : : DBG_DTOR(DisposeListenerGridBridge,NULL);
254 [ - + ]: 4 : }
255 : :
256 : : //==============================================================================
257 : :
258 : : static sal_uInt16 ControlMap[] =
259 : : {
260 : : DbGridControl::NavigationBar::RECORD_TEXT,
261 : : DbGridControl::NavigationBar::RECORD_ABSOLUTE,
262 : : DbGridControl::NavigationBar::RECORD_OF,
263 : : DbGridControl::NavigationBar::RECORD_COUNT,
264 : : DbGridControl::NavigationBar::RECORD_FIRST,
265 : : DbGridControl::NavigationBar::RECORD_NEXT,
266 : : DbGridControl::NavigationBar::RECORD_PREV,
267 : : DbGridControl::NavigationBar::RECORD_LAST,
268 : : DbGridControl::NavigationBar::RECORD_NEW,
269 : : 0
270 : : };
271 : :
272 : : //------------------------------------------------------------------------------
273 : 0 : sal_Bool CompareBookmark(const Any& aLeft, const Any& aRight)
274 : : {
275 : 0 : return ::comphelper::compare(aLeft, aRight);
276 : : }
277 : :
278 : : //==============================================================================
279 [ + - ][ - + ]: 4 : class FmXGridSourcePropListener : public ::comphelper::OPropertyChangeListener
280 : : {
281 : : DbGridControl* m_pParent;
282 : :
283 : : // a DbGridControl has no mutex, so we use our own as the base class expects one
284 : : osl::Mutex m_aMutex;
285 : : sal_Int16 m_nSuspended;
286 : :
287 : : public:
288 : : FmXGridSourcePropListener(DbGridControl* _pParent);
289 : :
290 : 2 : void suspend() { ++m_nSuspended; }
291 : 2 : void resume() { --m_nSuspended; }
292 : :
293 : : virtual void _propertyChanged(const PropertyChangeEvent& evt) throw( RuntimeException );
294 : : };
295 : :
296 : : //------------------------------------------------------------------------------
297 : 2 : FmXGridSourcePropListener::FmXGridSourcePropListener(DbGridControl* _pParent)
298 : : :OPropertyChangeListener(m_aMutex)
299 : : ,m_pParent(_pParent)
300 [ + - ]: 2 : ,m_nSuspended(0)
301 : : {
302 : : DBG_ASSERT(m_pParent, "FmXGridSourcePropListener::FmXGridSourcePropListener : invalid parent !");
303 : 2 : }
304 : :
305 : : //------------------------------------------------------------------------------
306 : 0 : void FmXGridSourcePropListener::_propertyChanged(const PropertyChangeEvent& evt) throw( RuntimeException )
307 : : {
308 : : DBG_ASSERT(m_nSuspended>=0, "FmXGridSourcePropListener::_propertyChanged : resume > suspend !");
309 [ # # ]: 0 : if (m_nSuspended <= 0)
310 : 0 : m_pParent->DataSourcePropertyChanged(evt);
311 : 0 : }
312 : :
313 : : //==============================================================================
314 : : //------------------------------------------------------------------------------
315 : 40 : DbGridControl::NavigationBar::AbsolutePos::AbsolutePos(Window* pParent, WinBits nStyle)
316 : 40 : :NumericField(pParent, nStyle)
317 : : {
318 [ + - ]: 40 : SetMin(1);
319 : 40 : SetFirst(1);
320 : 40 : SetSpinSize(1);
321 : :
322 [ + - ]: 40 : SetDecimalDigits(0);
323 [ + - ]: 40 : SetStrictFormat(sal_True);
324 : 40 : }
325 : :
326 : : //------------------------------------------------------------------------------
327 : 0 : void DbGridControl::NavigationBar::AbsolutePos::KeyInput(const KeyEvent& rEvt)
328 : : {
329 [ # # ][ # # ]: 0 : if (rEvt.GetKeyCode() == KEY_RETURN && GetText().Len())
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # ]
330 : : {
331 : 0 : sal_Int64 nRecord = GetValue();
332 [ # # ][ # # ]: 0 : if (nRecord < GetMin() || nRecord > GetMax())
[ # # ]
333 : 0 : return;
334 : : else
335 : 0 : ((NavigationBar*)GetParent())->PositionDataSource(static_cast<sal_Int32>(nRecord));
336 : : }
337 [ # # ][ # # ]: 0 : else if (rEvt.GetKeyCode() == KEY_TAB)
338 : 0 : GetParent()->GetParent()->GrabFocus();
339 : : else
340 : 0 : NumericField::KeyInput(rEvt);
341 : : }
342 : :
343 : : //------------------------------------------------------------------------------
344 : 0 : void DbGridControl::NavigationBar::AbsolutePos::LoseFocus()
345 : : {
346 : 0 : NumericField::LoseFocus();
347 : 0 : sal_Int64 nRecord = GetValue();
348 [ # # ][ # # ]: 0 : if (nRecord < GetMin() || nRecord > GetMax())
[ # # ]
349 : 0 : return;
350 : : else
351 : : {
352 : 0 : ((NavigationBar*)GetParent())->PositionDataSource(static_cast<sal_Int32>(nRecord));
353 : 0 : ((NavigationBar*)GetParent())->InvalidateState(NavigationBar::RECORD_ABSOLUTE);
354 : : }
355 : : }
356 : :
357 : : //------------------------------------------------------------------------------
358 : 0 : void DbGridControl::NavigationBar::PositionDataSource(sal_Int32 nRecord)
359 : : {
360 [ # # ]: 0 : if (m_bPositioning)
361 : 0 : return;
362 : : // the MoveToPosition may cause a LoseFocus which would lead to a second MoveToPosition, so protect agains this
363 : : // recursion
364 : : // 68167 - 13.08.99 - FS
365 : 0 : m_bPositioning = sal_True;
366 : 0 : ((DbGridControl*)GetParent())->MoveToPosition(nRecord - 1);
367 : 0 : m_bPositioning = sal_False;
368 : : }
369 : :
370 : : //------------------------------------------------------------------------------
371 : 40 : DbGridControl::NavigationBar::NavigationBar(Window* pParent, WinBits nStyle)
372 : : :Control(pParent, nStyle)
373 : : ,m_aRecordText(this, WB_VCENTER)
374 : : ,m_aAbsolute(this, WB_VCENTER)
375 : : ,m_aRecordOf(this, WB_VCENTER)
376 : : ,m_aRecordCount(this, WB_CENTER | WB_VCENTER)
377 : : ,m_aFirstBtn(this, WB_RECTSTYLE|WB_NOPOINTERFOCUS)
378 : : ,m_aPrevBtn(this, WB_REPEAT|WB_RECTSTYLE|WB_NOPOINTERFOCUS)
379 : : ,m_aNextBtn(this, WB_REPEAT|WB_RECTSTYLE|WB_NOPOINTERFOCUS)
380 : : ,m_aLastBtn(this, WB_RECTSTYLE|WB_NOPOINTERFOCUS)
381 : : ,m_aNewBtn(this, WB_RECTSTYLE|WB_NOPOINTERFOCUS)
382 : : ,m_nDefaultWidth(0)
383 : : ,m_nCurrentPos(-1)
384 [ + - ][ + - ]: 40 : ,m_bPositioning(sal_False)
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
385 : : {
386 [ + - ]: 40 : m_aFirstBtn.SetSymbol(SYMBOL_FIRST);
387 [ + - ]: 40 : m_aPrevBtn.SetSymbol(SYMBOL_PREV);
388 [ + - ]: 40 : m_aNextBtn.SetSymbol(SYMBOL_NEXT);
389 [ + - ]: 40 : m_aLastBtn.SetSymbol(SYMBOL_LAST);
390 [ + - ][ + - ]: 40 : m_aNewBtn.SetModeImage(((DbGridControl*)pParent)->GetImage(DbGridControl_Base::NEW));
[ + - ]
391 : :
392 [ + - ]: 40 : m_aFirstBtn.SetHelpId(HID_GRID_TRAVEL_FIRST);
393 [ + - ]: 40 : m_aPrevBtn.SetHelpId(HID_GRID_TRAVEL_PREV);
394 [ + - ]: 40 : m_aNextBtn.SetHelpId(HID_GRID_TRAVEL_NEXT);
395 [ + - ]: 40 : m_aLastBtn.SetHelpId(HID_GRID_TRAVEL_LAST);
396 [ + - ]: 40 : m_aNewBtn.SetHelpId(HID_GRID_TRAVEL_NEW);
397 [ + - ]: 40 : m_aAbsolute.SetHelpId(HID_GRID_TRAVEL_ABSOLUTE);
398 [ + - ]: 40 : m_aRecordCount.SetHelpId(HID_GRID_NUMBEROFRECORDS);
399 : :
400 : : // Handler fuer Buttons einrichten
401 [ + - ]: 40 : m_aFirstBtn.SetClickHdl(LINK(this,NavigationBar,OnClick));
402 [ + - ]: 40 : m_aPrevBtn.SetClickHdl(LINK(this,NavigationBar,OnClick));
403 [ + - ]: 40 : m_aNextBtn.SetClickHdl(LINK(this,NavigationBar,OnClick));
404 [ + - ]: 40 : m_aLastBtn.SetClickHdl(LINK(this,NavigationBar,OnClick));
405 [ + - ]: 40 : m_aNewBtn.SetClickHdl(LINK(this,NavigationBar,OnClick));
406 : :
407 [ + - ][ + - ]: 40 : m_aRecordText.SetText(XubString(SVX_RES(RID_STR_REC_TEXT)));
[ + - ][ + - ]
408 [ + - ][ + - ]: 40 : m_aRecordOf.SetText(XubString(SVX_RES(RID_STR_REC_FROM_TEXT)));
[ + - ][ + - ]
409 [ + - ][ + - ]: 40 : m_aRecordCount.SetText(rtl::OUString('?'));
[ + - ]
410 : :
411 [ + - ]: 40 : m_nDefaultWidth = ArrangeControls();
412 : :
413 [ + - ]: 40 : m_aFirstBtn.Disable();
414 [ + - ]: 40 : m_aPrevBtn.Disable();
415 [ + - ]: 40 : m_aNextBtn.Disable();
416 [ + - ]: 40 : m_aLastBtn.Disable();
417 [ + - ]: 40 : m_aNewBtn.Disable();
418 [ + - ]: 40 : m_aRecordText.Disable();
419 [ + - ]: 40 : m_aRecordOf.Disable();
420 [ + - ]: 40 : m_aRecordCount.Disable();
421 [ + - ]: 40 : m_aAbsolute.Disable();
422 : :
423 [ + - ]: 40 : AllSettings aSettings = m_aNextBtn.GetSettings();
424 [ + - ]: 40 : MouseSettings aMouseSettings = aSettings.GetMouseSettings();
425 [ + - ]: 40 : aMouseSettings.SetButtonRepeat(aMouseSettings.GetButtonRepeat() / 4);
426 [ + - ]: 40 : aSettings.SetMouseSettings(aMouseSettings);
427 [ + - ]: 40 : m_aNextBtn.SetSettings(aSettings, sal_True);
428 [ + - ]: 40 : m_aPrevBtn.SetSettings(aSettings, sal_True);
429 : :
430 [ + - ]: 40 : m_aFirstBtn.Show();
431 [ + - ]: 40 : m_aPrevBtn.Show();
432 [ + - ]: 40 : m_aNextBtn.Show();
433 [ + - ]: 40 : m_aLastBtn.Show();
434 [ + - ]: 40 : m_aNewBtn.Show();
435 [ + - ]: 40 : m_aRecordText.Show();
436 [ + - ]: 40 : m_aRecordOf.Show();
437 [ + - ]: 40 : m_aRecordCount.Show();
438 [ + - ][ + - ]: 40 : m_aAbsolute.Show();
[ + - ]
439 : 40 : }
440 : :
441 : : namespace
442 : : {
443 : 590 : void SetPosAndSize(Button& _rButton,Point& _rPos,const Size& _rSize)
444 : : {
445 : 590 : _rButton.SetPosPixel( _rPos );
446 : 590 : _rButton.SetSizePixel( _rSize );
447 : 590 : _rPos.X() += (sal_uInt16)_rSize.Width();
448 : 590 : }
449 : : }
450 : : //------------------------------------------------------------------------------
451 : 118 : sal_uInt16 DbGridControl::NavigationBar::ArrangeControls()
452 : : {
453 : : // Positionierung der Controls
454 : : // Basisgroessen ermitteln
455 : 118 : sal_uInt16 nX = 0;
456 : 118 : sal_uInt16 nY = 0;
457 [ + - ][ + - ]: 118 : Rectangle aRect(((DbGridControl*)GetParent())->GetControlArea());
458 [ + - ]: 118 : const long nH = aRect.GetSize().Height();
459 [ + - ][ + - ]: 118 : Size aBorder = LogicToPixel(Size(3, 3),MAP_APPFONT);
[ + - ]
460 [ + - ][ + - ]: 118 : aBorder = Size(CalcZoom(aBorder.Width()), CalcZoom(aBorder.Height()));
461 : :
462 : : // Controls Groessen und Positionen setzen
463 : : //
464 [ + - ]: 118 : XubString aText = m_aRecordText.GetText();
465 [ + - ]: 118 : long nTextWidth = m_aRecordText.GetTextWidth(aText);
466 [ + - ]: 118 : m_aRecordText.SetPosPixel(Point(nX,nY) );
467 [ + - ]: 118 : m_aRecordText.SetSizePixel(Size(nTextWidth,nH));
468 : 118 : nX = sal::static_int_cast< sal_uInt16 >(nX + nTextWidth + aBorder.Width());
469 : :
470 [ + - ]: 118 : m_aAbsolute.SetPosPixel( Point(nX,nY));
471 [ + - ][ + - ]: 118 : m_aAbsolute.SetSizePixel( Size(3*nH,aRect.GetSize().Height()) ); // Heuristik XXXXXXX
472 : 118 : nX = sal::static_int_cast< sal_uInt16 >(nX + (3*nH) + aBorder.Width());
473 : :
474 [ + - ][ + - ]: 118 : aText = m_aRecordOf.GetText();
[ + - ]
475 [ + - ]: 118 : nTextWidth = m_aRecordOf.GetTextWidth(aText);
476 [ + - ]: 118 : m_aRecordOf.SetPosPixel(Point(nX,nY) );
477 [ + - ]: 118 : m_aRecordOf.SetSizePixel(Size(nTextWidth,nH));
478 : 118 : nX = sal::static_int_cast< sal_uInt16 >(nX + nTextWidth + aBorder.Width());
479 : :
480 [ + - ][ + - ]: 118 : nTextWidth = m_aRecordCount.GetTextWidth( rtl::OUString("0000000 (00000) *") );
[ + - ]
481 [ + - ]: 118 : m_aRecordCount.SetPosPixel(Point(nX,nY) );
482 [ + - ]: 118 : m_aRecordCount.SetSizePixel(Size(nTextWidth,nH));
483 : 118 : nX = sal::static_int_cast< sal_uInt16 >(nX + nTextWidth + aBorder.Width());
484 : :
485 : 118 : Point aButtonPos(nX,nY);
486 : 118 : Size aButtonSize(nH,nH);
487 [ + - ]: 118 : SetPosAndSize(m_aFirstBtn, aButtonPos, aButtonSize);
488 [ + - ]: 118 : SetPosAndSize(m_aPrevBtn, aButtonPos, aButtonSize);
489 [ + - ]: 118 : SetPosAndSize(m_aNextBtn, aButtonPos, aButtonSize);
490 [ + - ]: 118 : SetPosAndSize(m_aLastBtn, aButtonPos, aButtonSize);
491 [ + - ]: 118 : SetPosAndSize(m_aNewBtn, aButtonPos, aButtonSize);
492 : :
493 : : nX = sal::static_int_cast< sal_uInt16 >(
494 : 118 : aButtonPos.X() + (sal_uInt16)(nH + aBorder.Width()));
495 : :
496 : : // Ist der Font des Edits groesser als das Feld?
497 [ + - ]: 118 : Font aOutputFont = m_aAbsolute.GetFont();
498 [ + - ][ - + ]: 118 : if (aOutputFont.GetSize().Height() > nH)
499 : : {
500 : : Font aApplFont = OutputDevice::GetDefaultFont(
501 : : DEFAULTFONT_SANS_UNICODE,
502 [ # # ][ # # ]: 0 : Application::GetSettings().GetUILanguage(),
503 : : DEFAULTFONT_FLAGS_ONLYONE,
504 : : this
505 [ # # ]: 0 : );
506 [ # # ]: 0 : aApplFont.SetSize( Size( 0, nH - 2 ) );
507 [ # # ]: 0 : m_aAbsolute.SetControlFont( aApplFont );
508 : :
509 [ # # ]: 0 : aApplFont.SetTransparent( sal_True );
510 [ # # ]: 0 : m_aRecordText.SetControlFont( aApplFont );
511 [ # # ]: 0 : m_aRecordOf.SetControlFont( aApplFont );
512 [ # # ][ # # ]: 0 : m_aRecordCount.SetControlFont( aApplFont );
513 : : }
514 [ + - ][ + - ]: 118 : return nX;
515 : : }
516 : :
517 : : //------------------------------------------------------------------------------
518 : 0 : IMPL_LINK(DbGridControl::NavigationBar, OnClick, Button *, pButton )
519 : : {
520 : 0 : DbGridControl* pParent = (DbGridControl*)GetParent();
521 : :
522 [ # # ]: 0 : if (pParent->m_aMasterSlotExecutor.IsSet())
523 : : {
524 : 0 : long lResult = 0;
525 [ # # ]: 0 : if (pButton == &m_aFirstBtn)
526 : 0 : lResult = pParent->m_aMasterSlotExecutor.Call((void*)RECORD_FIRST);
527 [ # # ]: 0 : else if( pButton == &m_aPrevBtn )
528 : 0 : lResult = pParent->m_aMasterSlotExecutor.Call((void*)RECORD_PREV);
529 [ # # ]: 0 : else if( pButton == &m_aNextBtn )
530 : 0 : lResult = pParent->m_aMasterSlotExecutor.Call((void*)RECORD_NEXT);
531 [ # # ]: 0 : else if( pButton == &m_aLastBtn )
532 : 0 : lResult = pParent->m_aMasterSlotExecutor.Call((void*)RECORD_LAST);
533 [ # # ]: 0 : else if( pButton == &m_aNewBtn )
534 : 0 : lResult = pParent->m_aMasterSlotExecutor.Call((void*)RECORD_NEW);
535 : :
536 [ # # ]: 0 : if (lResult)
537 : : // the link already handled it
538 : 0 : return 0;
539 : : }
540 : :
541 [ # # ]: 0 : if (pButton == &m_aFirstBtn)
542 : 0 : pParent->MoveToFirst();
543 [ # # ]: 0 : else if( pButton == &m_aPrevBtn )
544 : 0 : pParent->MoveToPrev();
545 [ # # ]: 0 : else if( pButton == &m_aNextBtn )
546 : 0 : pParent->MoveToNext();
547 [ # # ]: 0 : else if( pButton == &m_aLastBtn )
548 : 0 : pParent->MoveToLast();
549 [ # # ]: 0 : else if( pButton == &m_aNewBtn )
550 : 0 : pParent->AppendNew();
551 : 0 : return 0;
552 : : }
553 : :
554 : : //------------------------------------------------------------------------------
555 : 131 : void DbGridControl::NavigationBar::InvalidateAll(sal_Int32 nCurrentPos, sal_Bool bAll)
556 : : {
557 [ + + ][ + + ]: 131 : if (m_nCurrentPos != nCurrentPos || nCurrentPos < 0 || bAll)
[ + + ]
558 : : {
559 : 127 : DbGridControl* pParent = (DbGridControl*)GetParent();
560 : :
561 [ + + ]: 127 : sal_Int32 nAdjustedRowCount = pParent->GetRowCount() - ((pParent->GetOptions() & DbGridControl::OPT_INSERT) ? 2 : 1);
562 : :
563 : : // Wann mu� alles invalidiert werden
564 [ + + ][ + - ]: 127 : bAll = bAll || m_nCurrentPos <= 0;
565 [ - + ][ # # ]: 127 : bAll = bAll || nCurrentPos <= 0;
566 [ - + ][ # # ]: 127 : bAll = bAll || m_nCurrentPos >= nAdjustedRowCount;
567 [ - + ][ # # ]: 127 : bAll = bAll || nCurrentPos >= nAdjustedRowCount;
568 : :
569 [ + - ]: 127 : if ( bAll )
570 : : {
571 : 127 : m_nCurrentPos = nCurrentPos;
572 : 127 : int i = 0;
573 [ + + ]: 1270 : while (ControlMap[i])
574 : 1143 : SetState(ControlMap[i++]);
575 : : }
576 : : else // befindet sich in der Mitte
577 : : {
578 : 0 : m_nCurrentPos = nCurrentPos;
579 : 0 : SetState(NavigationBar::RECORD_COUNT);
580 : 0 : SetState(NavigationBar::RECORD_ABSOLUTE);
581 : : }
582 : : }
583 : 131 : }
584 : :
585 : : //------------------------------------------------------------------------------
586 : 1147 : sal_Bool DbGridControl::NavigationBar::GetState(sal_uInt16 nWhich) const
587 : : {
588 : 1147 : DbGridControl* pParent = (DbGridControl*)GetParent();
589 : :
590 [ + + ]: 1165 : if (!pParent->IsOpen() || pParent->IsDesignMode() || !pParent->IsEnabled()
[ + - - + ]
[ + + ][ + + ]
591 : 18 : || pParent->IsFilterMode() )
592 : 1129 : return sal_False;
593 : : else
594 : : {
595 : : // check if we have a master state provider
596 [ + - ]: 18 : if (pParent->m_aMasterStateProvider.IsSet())
597 : : {
598 : 18 : long nState = pParent->m_aMasterStateProvider.Call(reinterpret_cast< void* >( nWhich ) );
599 [ - + ]: 18 : if (nState>=0)
600 : 0 : return (nState>0);
601 : : }
602 : :
603 : 18 : sal_Bool bAvailable = sal_True;
604 : :
605 [ + + + + : 18 : switch (nWhich)
+ + ]
606 : : {
607 : : case NavigationBar::RECORD_FIRST:
608 : : case NavigationBar::RECORD_PREV:
609 : 4 : bAvailable = m_nCurrentPos > 0;
610 : 4 : break;
611 : : case NavigationBar::RECORD_NEXT:
612 [ + - ]: 2 : if(pParent->m_bRecordCountFinal)
613 : : {
614 : 2 : bAvailable = m_nCurrentPos < pParent->GetRowCount() - 1;
615 [ # # ][ - + ]: 2 : if (!bAvailable && pParent->GetOptions() & DbGridControl::OPT_INSERT)
[ - + ]
616 [ # # ][ # # ]: 0 : bAvailable = (m_nCurrentPos == pParent->GetRowCount() - 2) && pParent->IsModified();
617 : : }
618 : 2 : break;
619 : : case NavigationBar::RECORD_LAST:
620 [ + - ]: 2 : if(pParent->m_bRecordCountFinal)
621 : : {
622 [ + - ]: 2 : if (pParent->GetOptions() & DbGridControl::OPT_INSERT)
623 : 2 : bAvailable = pParent->IsCurrentAppending() ? pParent->GetRowCount() > 1 :
624 [ - + ]: 2 : m_nCurrentPos != pParent->GetRowCount() - 2;
625 : : else
626 : 0 : bAvailable = m_nCurrentPos != pParent->GetRowCount() - 1;
627 : : }
628 : 2 : break;
629 : : case NavigationBar::RECORD_NEW:
630 [ + - ][ + - ]: 2 : bAvailable = (pParent->GetOptions() & DbGridControl::OPT_INSERT) && pParent->GetRowCount() && m_nCurrentPos < pParent->GetRowCount() - 1;
[ + - ]
631 : 2 : break;
632 : : case NavigationBar::RECORD_ABSOLUTE:
633 : 2 : bAvailable = pParent->GetRowCount() > 0;
634 : 2 : break;
635 : : }
636 : 1147 : return bAvailable;
637 : : }
638 : : }
639 : :
640 : : //------------------------------------------------------------------------------
641 : 1147 : void DbGridControl::NavigationBar::SetState(sal_uInt16 nWhich)
642 : : {
643 : 1147 : sal_Bool bAvailable = GetState(nWhich);
644 : 1147 : DbGridControl* pParent = (DbGridControl*)GetParent();
645 : 1147 : Window* pWnd = NULL;
646 [ + + + + : 1147 : switch (nWhich)
+ + + + +
- ]
647 : : {
648 : : case NavigationBar::RECORD_FIRST:
649 : 127 : pWnd = &m_aFirstBtn;
650 : 127 : break;
651 : : case NavigationBar::RECORD_PREV:
652 : 127 : pWnd = &m_aPrevBtn;
653 : 127 : break;
654 : : case NavigationBar::RECORD_NEXT:
655 : 127 : pWnd = &m_aNextBtn;
656 : 127 : break;
657 : : case NavigationBar::RECORD_LAST:
658 : 127 : pWnd = &m_aLastBtn;
659 : 127 : break;
660 : : case NavigationBar::RECORD_NEW:
661 : 127 : pWnd = &m_aNewBtn;
662 : 127 : break;
663 : : case NavigationBar::RECORD_ABSOLUTE:
664 : 127 : pWnd = &m_aAbsolute;
665 [ + + ]: 127 : if (bAvailable)
666 : : {
667 [ + - ]: 2 : if (pParent->m_nTotalCount >= 0)
668 : : {
669 [ - + ]: 2 : if (pParent->IsCurrentAppending())
670 : 0 : m_aAbsolute.SetMax(pParent->m_nTotalCount + 1);
671 : : else
672 : 2 : m_aAbsolute.SetMax(pParent->m_nTotalCount);
673 : : }
674 : : else
675 : 0 : m_aAbsolute.SetMax(LONG_MAX);
676 : :
677 : 2 : m_aAbsolute.SetValue(m_nCurrentPos + 1);
678 : : }
679 : : else
680 [ + - ]: 125 : m_aAbsolute.SetText(String());
681 : 127 : break;
682 : : case NavigationBar::RECORD_TEXT:
683 : 127 : pWnd = &m_aRecordText;
684 : 127 : break;
685 : : case NavigationBar::RECORD_OF:
686 : 127 : pWnd = &m_aRecordOf;
687 : 127 : break;
688 : : case NavigationBar::RECORD_COUNT:
689 : : {
690 : 131 : pWnd = &m_aRecordCount;
691 [ + - ]: 131 : String aText;
692 [ + + ]: 131 : if (bAvailable)
693 : : {
694 [ + - ]: 2 : if (pParent->GetOptions() & DbGridControl::OPT_INSERT)
695 : : {
696 [ + - ][ - + ]: 2 : if (pParent->IsCurrentAppending() && !pParent->IsModified())
[ # # ][ # # ]
[ - + ]
697 [ # # ][ # # ]: 0 : aText = String::CreateFromInt32(pParent->GetRowCount());
[ # # ][ # # ]
698 : : else
699 [ + - ][ + - ]: 2 : aText = String::CreateFromInt32(pParent->GetRowCount() - 1);
[ + - ][ + - ]
700 : : }
701 : : else
702 [ # # ][ # # ]: 0 : aText = String::CreateFromInt32(pParent->GetRowCount());
[ # # ][ # # ]
703 [ - + ]: 2 : if(!pParent->m_bRecordCountFinal)
704 [ # # ]: 0 : aText += rtl::OUString(" *");
705 : : }
706 : : else
707 [ + - ][ + - ]: 129 : aText = String();
[ + - ]
708 : :
709 : : // add the number of selected rows, if applicable
710 [ + - ][ - + ]: 131 : if (pParent->GetSelectRowCount())
711 : : {
712 [ # # ]: 0 : String aExtendedInfo(aText);
713 [ # # ]: 0 : aExtendedInfo.AppendAscii(" (");
714 [ # # ][ # # ]: 0 : aExtendedInfo += String::CreateFromInt32(pParent->GetSelectRowCount());
[ # # ][ # # ]
715 [ # # ]: 0 : aExtendedInfo += ')';
716 [ # # ][ # # ]: 0 : pWnd->SetText(aExtendedInfo);
717 : : }
718 : : else
719 [ + - ]: 131 : pWnd->SetText(aText);
720 : :
721 [ + - ][ + - ]: 131 : pParent->SetRealRowCount(aText);
722 : 131 : } break;
723 : : }
724 : : DBG_ASSERT(pWnd, "kein Fenster");
725 [ + - ][ + + ]: 1147 : if (pWnd && (pWnd->IsEnabled() != bAvailable))
[ + + ]
726 : : // this "pWnd->IsEnabled() != bAvailable" is a little hack : Window::Enable always generates a user
727 : : // event (ImplGenerateMouseMove) even if nothing happened. This may lead to some unwanted effects, so we
728 : : // do this check.
729 : : // For further explanation see Bug 69900.
730 : 424 : pWnd->Enable(bAvailable);
731 : 1147 : }
732 : :
733 : : //------------------------------------------------------------------------------
734 : 78 : void DbGridControl::NavigationBar::Resize()
735 : : {
736 : 78 : Control::Resize();
737 : 78 : ArrangeControls();
738 : 78 : }
739 : :
740 : : //------------------------------------------------------------------------------
741 : 11 : void DbGridControl::NavigationBar::Paint(const Rectangle& rRect)
742 : : {
743 [ + - ]: 11 : Control::Paint(rRect);
744 [ + - ]: 11 : Point aAbsolutePos = m_aAbsolute.GetPosPixel();
745 [ + - ]: 11 : Size aAbsoluteSize = m_aAbsolute.GetSizePixel();
746 : :
747 : 11 : DrawLine(Point(aAbsolutePos.X() - 1, 0 ),
748 [ + - ]: 22 : Point(aAbsolutePos.X() - 1, aAbsolutePos.Y() + aAbsoluteSize.Height()));
749 : :
750 : 11 : DrawLine(Point(aAbsolutePos.X() + aAbsoluteSize.Width() + 1, 0 ),
751 [ + - ]: 22 : Point(aAbsolutePos.X() + aAbsoluteSize.Width() + 1, aAbsolutePos.Y() + aAbsoluteSize.Height()));
752 : 11 : }
753 : :
754 : : //------------------------------------------------------------------------------
755 : 306 : void DbGridControl::NavigationBar::StateChanged( StateChangedType nType )
756 : : {
757 [ + - ]: 306 : Control::StateChanged( nType );
758 : :
759 : : Window* pWindows[] = { &m_aRecordText,
760 : : &m_aAbsolute,
761 : : &m_aRecordOf,
762 : : &m_aRecordCount,
763 : : &m_aFirstBtn,
764 : : &m_aPrevBtn,
765 : : &m_aNextBtn,
766 : : &m_aLastBtn,
767 : : &m_aNewBtn
768 : 306 : };
769 : :
770 [ + - + ]: 306 : switch ( nType )
771 : : {
772 : : case STATE_CHANGE_MIRRORING:
773 : : {
774 : 136 : sal_Bool bIsRTLEnabled = IsRTLEnabled();
775 [ + + ]: 1360 : for ( size_t i=0; i < (sizeof (pWindows) / sizeof(pWindows[0])); ++i )
776 [ + - ]: 1224 : pWindows[i]->EnableRTL( bIsRTLEnabled );
777 : : }
778 : 136 : break;
779 : :
780 : : case STATE_CHANGE_ZOOM:
781 : : {
782 [ # # ][ # # ]: 0 : Fraction aZoom = GetZoom();
783 : :
784 : : // not all of these controls need to know the new zoom, but to be sure ...
785 [ # # ]: 0 : Font aFont( GetSettings().GetStyleSettings().GetFieldFont() );
786 [ # # ][ # # ]: 0 : if ( IsControlFont() )
787 [ # # ][ # # ]: 0 : aFont.Merge( GetControlFont() );
[ # # ]
788 : :
789 [ # # ]: 0 : for (size_t i=0; i < sizeof(pWindows)/sizeof(pWindows[0]); ++i)
790 : : {
791 [ # # ]: 0 : pWindows[i]->SetZoom(aZoom);
792 [ # # ]: 0 : pWindows[i]->SetZoomedPointFont(aFont);
793 : : }
794 : :
795 [ # # ]: 0 : SetZoomedPointFont( aFont );
796 : :
797 : : // rearrange the controls
798 [ # # ][ # # ]: 0 : m_nDefaultWidth = ArrangeControls();
799 : : }
800 : 0 : break;
801 : : }
802 : 306 : }
803 : :
804 : : //------------------------------------------------------------------------------
805 : 4 : DbGridRow::DbGridRow(CursorWrapper* pCur, sal_Bool bPaintCursor)
806 [ + - ]: 4 : :m_bIsNew(sal_False)
807 : : {
808 : :
809 [ + - ][ + - ]: 4 : if (pCur && pCur->Is())
[ + - ]
810 : : {
811 [ + - ][ + - ]: 4 : Reference< XIndexAccess > xColumns(pCur->getColumns(), UNO_QUERY);
812 : : DataColumn* pColumn;
813 [ + - ][ + - ]: 128 : for (sal_Int32 i = 0; i < xColumns->getCount(); ++i)
[ + + ]
814 : : {
815 : 124 : Reference< XPropertySet > xColSet;
816 [ + - ][ + - ]: 124 : ::cppu::extractInterface(xColSet, xColumns->getByIndex(i));
[ + - ]
817 [ + - ][ + - ]: 124 : pColumn = new DataColumn(xColSet);
818 [ + - ]: 124 : m_aVariants.push_back( pColumn );
819 : 124 : }
820 : :
821 [ + - ][ - + ]: 4 : if (pCur->rowDeleted())
822 : 0 : m_eStatus = GRS_DELETED;
823 : : else
824 : : {
825 [ + + ]: 4 : if (bPaintCursor)
826 [ + - ][ + - ]: 2 : m_eStatus = (pCur->isAfterLast() || pCur->isBeforeFirst()) ? GRS_INVALID : GRS_CLEAN;
[ + - ][ - + ]
827 : : else
828 : : {
829 : 2 : Reference< XPropertySet > xSet = pCur->getPropertySet();
830 [ + - ]: 2 : if (xSet.is())
831 : : {
832 [ + - ][ + - ]: 2 : m_bIsNew = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISNEW));
[ + - ][ + - ]
833 [ + - ][ + - ]: 2 : if (!m_bIsNew && (pCur->isAfterLast() || pCur->isBeforeFirst()))
[ + - ][ - + ]
[ - + ][ + - ]
834 : 0 : m_eStatus = GRS_INVALID;
835 [ + - ][ + - ]: 2 : else if (::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISMODIFIED)))
[ + - ][ + - ]
[ - + ]
836 : 0 : m_eStatus = GRS_MODIFIED;
837 : : else
838 : 2 : m_eStatus = GRS_CLEAN;
839 : : }
840 : : else
841 : 2 : m_eStatus = GRS_INVALID;
842 : : }
843 : : }
844 [ + - ][ + - ]: 4 : if (!m_bIsNew && IsValid())
[ + - ]
845 [ + - ]: 4 : m_aBookmark = pCur->getBookmark();
846 : : else
847 : 4 : m_aBookmark = Any();
848 : : }
849 : : else
850 : 0 : m_eStatus = GRS_INVALID;
851 : 4 : }
852 : :
853 : : //------------------------------------------------------------------------------
854 : 6 : DbGridRow::~DbGridRow()
855 : : {
856 [ + + ]: 130 : for ( size_t i = 0, n = m_aVariants.size(); i < n; ++i )
857 [ + - ][ + - ]: 124 : delete m_aVariants[ i ];
858 : 6 : m_aVariants.clear();
859 [ - + ]: 12 : }
860 : :
861 : : //------------------------------------------------------------------------------
862 : 16 : void DbGridRow::SetState(CursorWrapper* pCur, sal_Bool bPaintCursor)
863 : : {
864 [ + - ][ + - ]: 16 : if (pCur && pCur->Is())
[ + - ]
865 : : {
866 [ - + ]: 16 : if (pCur->rowDeleted())
867 : : {
868 : 0 : m_eStatus = GRS_DELETED;
869 : 0 : m_bIsNew = sal_False;
870 : : }
871 : : else
872 : : {
873 : 16 : m_eStatus = GRS_CLEAN;
874 [ + + ]: 16 : if (!bPaintCursor)
875 : : {
876 : 2 : Reference< XPropertySet > xSet = pCur->getPropertySet();
877 : : DBG_ASSERT(xSet.is(), "DbGridRow::SetState : invalid cursor !");
878 : :
879 [ + - ][ + - ]: 2 : if (::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISMODIFIED)))
[ + - ][ - + ]
[ + - ]
880 : 0 : m_eStatus = GRS_MODIFIED;
881 [ + - ][ + - ]: 2 : m_bIsNew = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISNEW));
[ + - ][ + - ]
[ # # ]
882 : : }
883 : : else
884 : 14 : m_bIsNew = sal_False;
885 : : }
886 : :
887 : : try
888 : : {
889 [ + - ][ + - ]: 16 : if (!m_bIsNew && IsValid())
[ + - ]
890 [ + - ]: 16 : m_aBookmark = pCur->getBookmark();
891 : : else
892 : 0 : m_aBookmark = Any();
893 : : }
894 : 0 : catch(SQLException&)
895 : : {
896 : : DBG_UNHANDLED_EXCEPTION();
897 : 0 : m_aBookmark = Any();
898 : 0 : m_eStatus = GRS_INVALID;
899 : 0 : m_bIsNew = sal_False;
900 : : }
901 : : }
902 : : else
903 : : {
904 : 0 : m_aBookmark = Any();
905 : 0 : m_eStatus = GRS_INVALID;
906 : 0 : m_bIsNew = sal_False;
907 : : }
908 : 16 : }
909 : :
910 : : DBG_NAME(DbGridControl);
911 : : //------------------------------------------------------------------------------
912 : 40 : DbGridControl::DbGridControl(
913 : : Reference< XMultiServiceFactory > _rxFactory,
914 : : Window* pParent,
915 : : WinBits nBits)
916 : : :DbGridControl_Base(pParent, EBBF_NONE, nBits, DEFAULT_BROWSE_MODE )
917 : : ,m_xServiceFactory(_rxFactory)
918 : : ,m_aBar(this)
919 : : ,m_nAsynAdjustEvent(0)
920 : : ,m_pDataSourcePropMultiplexer(NULL)
921 : : ,m_pDataSourcePropListener(NULL)
922 : : ,m_pFieldListeners(NULL)
923 : : ,m_pCursorDisposeListener(NULL)
924 : : ,m_pGridListener(NULL)
925 : : ,m_pDataCursor(NULL)
926 : : ,m_pSeekCursor(NULL)
927 : : ,m_nSeekPos(-1)
928 : : ,m_nTotalCount(-1)
929 [ + - ][ + - ]: 80 : ,m_aNullDate(OTypeConversionClient().getStandardDate())
930 : : ,m_nMode(DEFAULT_BROWSE_MODE)
931 : : ,m_nCurrentPos(-1)
932 : : ,m_nDeleteEvent(0)
933 : : ,m_nOptions(OPT_READONLY)
934 : : ,m_nOptionMask(OPT_INSERT | OPT_UPDATE | OPT_DELETE)
935 : : ,m_nLastColId((sal_uInt16)-1)
936 : : ,m_nLastRowId(-1)
937 : : ,m_bDesignMode(sal_False)
938 : : ,m_bRecordCountFinal(sal_False)
939 : : ,m_bMultiSelection(sal_True)
940 : : ,m_bNavigationBar(sal_True)
941 : : ,m_bSynchDisplay(sal_True)
942 : : ,m_bForceROController(sal_False)
943 : : ,m_bHandle(sal_True)
944 : : ,m_bFilterMode(sal_False)
945 : : ,m_bWantDestruction(sal_False)
946 : : ,m_bInAdjustDataSource(sal_False)
947 : : ,m_bPendingAdjustRows(sal_False)
948 : : ,m_bHideScrollbars( sal_False )
949 [ + - ][ + - ]: 80 : ,m_bUpdating(sal_False)
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
950 : : {
951 : : DBG_CTOR(DbGridControl,NULL);
952 : :
953 [ + - ][ + - ]: 40 : String sName(SVX_RES(RID_STR_NAVIGATIONBAR));
954 [ + - ]: 40 : m_aBar.SetAccessibleName(sName);
955 [ + - ]: 40 : m_aBar.Show();
956 [ + - ][ + - ]: 40 : ImplInitWindow( InitAll );
957 : 40 : }
958 : :
959 : : //------------------------------------------------------------------------------
960 : 66 : void DbGridControl::InsertHandleColumn()
961 : : {
962 : : // Handle Column einfuegen
963 : : // Da die BrowseBox ohne handleColums Paintprobleme hat
964 : : // wird diese versteckt
965 [ + + ]: 66 : if (HasHandle())
966 [ + - ][ + - ]: 50 : BrowseBox::InsertHandleColumn(GetDefaultColumnWidth(String()));
967 : : else
968 : 16 : BrowseBox::InsertHandleColumn(0);
969 : 66 : }
970 : :
971 : : //------------------------------------------------------------------------------
972 : 40 : void DbGridControl::Init()
973 : : {
974 : 40 : BrowserHeader* pNewHeader = CreateHeaderBar(this);
975 : 40 : pHeader->SetMouseTransparent(sal_False);
976 : :
977 : 40 : SetHeaderBar(pNewHeader);
978 : 40 : SetMode(m_nMode);
979 [ + - ]: 40 : SetCursorColor(Color(0xFF, 0, 0));
980 : :
981 : 40 : InsertHandleColumn();
982 : 40 : }
983 : :
984 : : //------------------------------------------------------------------------------
985 [ + - ][ + - ]: 40 : DbGridControl::~DbGridControl()
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
986 : : {
987 [ + - ]: 40 : RemoveColumns();
988 : :
989 : : {
990 : 40 : m_bWantDestruction = sal_True;
991 [ + - ]: 40 : osl::MutexGuard aGuard(m_aDestructionSafety);
992 [ + + ]: 40 : if (m_pFieldListeners)
993 [ + - ]: 2 : DisconnectFromFields();
994 [ + + ]: 40 : if (m_pCursorDisposeListener)
995 : : {
996 [ + - ][ + - ]: 2 : delete m_pCursorDisposeListener;
997 : 2 : m_pCursorDisposeListener = NULL;
998 [ + - ]: 40 : }
999 : : }
1000 : :
1001 [ - + ]: 40 : if (m_nDeleteEvent)
1002 [ # # ]: 0 : Application::RemoveUserEvent(m_nDeleteEvent);
1003 : :
1004 [ - + ]: 40 : if (m_pDataSourcePropMultiplexer)
1005 : : {
1006 [ # # ]: 0 : m_pDataSourcePropMultiplexer->dispose();
1007 : 0 : m_pDataSourcePropMultiplexer->release(); // this should delete the multiplexer
1008 [ # # ][ # # ]: 0 : delete m_pDataSourcePropListener;
1009 : 0 : m_pDataSourcePropMultiplexer = NULL;
1010 : 0 : m_pDataSourcePropListener = NULL;
1011 : : }
1012 : 40 : m_xRowSetListener.clear();
1013 : :
1014 [ # # ][ - + ]: 40 : delete m_pDataCursor;
1015 [ - + ][ # # ]: 40 : delete m_pSeekCursor;
1016 : :
1017 : : DBG_DTOR(DbGridControl,NULL);
1018 [ - + ]: 40 : }
1019 : :
1020 : : //------------------------------------------------------------------------------
1021 : 517 : void DbGridControl::StateChanged( StateChangedType nType )
1022 : : {
1023 : 517 : DbGridControl_Base::StateChanged( nType );
1024 : :
1025 [ + - + - : 517 : switch (nType)
- + ]
1026 : : {
1027 : : case STATE_CHANGE_MIRRORING:
1028 : 98 : ImplInitWindow( InitWritingMode );
1029 : 98 : Invalidate();
1030 : 98 : break;
1031 : :
1032 : : case STATE_CHANGE_ZOOM:
1033 : : {
1034 [ # # ]: 0 : ImplInitWindow( InitFont );
1035 : :
1036 : : // and give it a chance to rearrange
1037 [ # # ]: 0 : Point aPoint = GetControlArea().TopLeft();
1038 : 0 : sal_uInt16 nX = (sal_uInt16)aPoint.X();
1039 [ # # ]: 0 : ArrangeControls(nX, (sal_uInt16)aPoint.Y());
1040 [ # # ]: 0 : ReserveControlArea((sal_uInt16)nX);
1041 : : }
1042 : 0 : break;
1043 : : case STATE_CHANGE_CONTROLFONT:
1044 : 76 : ImplInitWindow( InitFont );
1045 : 76 : Invalidate();
1046 : 76 : break;
1047 : : case STATE_CHANGE_CONTROLFOREGROUND:
1048 : 0 : ImplInitWindow( InitForeground );
1049 : 0 : Invalidate();
1050 : 0 : break;
1051 : : case STATE_CHANGE_CONTROLBACKGROUND:
1052 : 0 : ImplInitWindow( InitBackground );
1053 : 0 : Invalidate();
1054 : 0 : break;
1055 : : }
1056 : 517 : }
1057 : :
1058 : : //------------------------------------------------------------------------------
1059 : 64 : void DbGridControl::DataChanged( const DataChangedEvent& rDCEvt )
1060 : : {
1061 : 64 : DbGridControl_Base::DataChanged( rDCEvt );
1062 [ + - ]: 128 : if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS ) &&
[ + - + - ]
1063 : 64 : (rDCEvt.GetFlags() & SETTINGS_STYLE) )
1064 : : {
1065 : 64 : ImplInitWindow( InitAll );
1066 : 64 : Invalidate();
1067 : : }
1068 : 64 : }
1069 : :
1070 : : //------------------------------------------------------------------------------
1071 : 0 : void DbGridControl::Select()
1072 : : {
1073 : 0 : DbGridControl_Base::Select();
1074 : :
1075 : : // as the selected rows may have changed, udate the according display in our navigation bar
1076 : 0 : m_aBar.InvalidateState(NavigationBar::RECORD_COUNT);
1077 : :
1078 [ # # ]: 0 : if (m_pGridListener)
1079 : 0 : m_pGridListener->selectionChanged();
1080 : 0 : }
1081 : :
1082 : : //------------------------------------------------------------------------------
1083 : 278 : void DbGridControl::ImplInitWindow( const InitWindowFacet _eInitWhat )
1084 : : {
1085 [ + + ]: 558 : for ( size_t i = 0; i < m_aColumns.size(); ++i )
1086 : : {
1087 : 280 : DbGridColumn* pCol = m_aColumns[ i ];
1088 [ + - ]: 280 : if (pCol)
1089 : 280 : pCol->ImplInitWindow( GetDataWindow(), _eInitWhat );
1090 : : }
1091 : :
1092 [ + + ]: 278 : if ( ( _eInitWhat & InitWritingMode ) != 0 )
1093 : : {
1094 [ + + ]: 202 : if ( m_bNavigationBar )
1095 : : {
1096 : 136 : m_aBar.EnableRTL( IsRTLEnabled() );
1097 : : }
1098 : : }
1099 : :
1100 [ + + ]: 278 : if ( ( _eInitWhat & InitFont ) != 0 )
1101 : : {
1102 [ + + ]: 180 : if ( m_bNavigationBar )
1103 : : {
1104 [ + - ]: 98 : Font aFont = m_aBar.GetSettings().GetStyleSettings().GetFieldFont();
1105 [ + - ][ + + ]: 98 : if ( IsControlFont() )
1106 [ + - ][ + - ]: 52 : m_aBar.SetControlFont( GetControlFont() );
[ + - ]
1107 : : else
1108 [ + - ]: 46 : m_aBar.SetControlFont();
1109 : :
1110 [ + - ][ + - ]: 98 : m_aBar.SetZoom( GetZoom() );
[ + - ]
1111 : : }
1112 : : }
1113 : :
1114 [ + + ]: 278 : if ( ( _eInitWhat & InitBackground ) != 0 )
1115 : : {
1116 [ - + ]: 104 : if (IsControlBackground())
1117 : : {
1118 [ # # ][ # # ]: 0 : GetDataWindow().SetBackground(GetControlBackground());
[ # # ]
1119 [ # # ]: 0 : GetDataWindow().SetControlBackground(GetControlBackground());
1120 [ # # ]: 0 : GetDataWindow().SetFillColor(GetControlBackground());
1121 : : }
1122 : : else
1123 : : {
1124 : 104 : GetDataWindow().SetControlBackground();
1125 : 104 : GetDataWindow().SetFillColor(GetFillColor());
1126 : : }
1127 : : }
1128 : 278 : }
1129 : :
1130 : : //------------------------------------------------------------------------------
1131 : 0 : void DbGridControl::RemoveRows(sal_Bool bNewCursor)
1132 : : {
1133 : : // Hat sich der DatenCursor verandert ?
1134 [ # # ]: 0 : if (!bNewCursor)
1135 : : {
1136 [ # # ]: 0 : DELETEZ(m_pSeekCursor);
1137 : 0 : m_xPaintRow = m_xDataRow = m_xEmptyRow = m_xCurrentRow = m_xSeekRow = NULL;
1138 : 0 : m_nCurrentPos = m_nSeekPos = -1;
1139 : 0 : m_nOptions = OPT_READONLY;
1140 : :
1141 : 0 : RowRemoved(0, GetRowCount(), sal_False);
1142 : 0 : m_nTotalCount = -1;
1143 : : }
1144 : : else
1145 : : {
1146 : 0 : RemoveRows();
1147 : : }
1148 : 0 : }
1149 : :
1150 : : //------------------------------------------------------------------------------
1151 : 4 : void DbGridControl::RemoveRows()
1152 : : {
1153 : : // we're going to remove all columns and all row, so deactivate the current cell
1154 [ - + ]: 4 : if (IsEditing())
1155 : 0 : DeactivateCell();
1156 : :
1157 : : // alle Columns deinitialisieren
1158 : : // existieren Spalten, dann alle Controller freigeben
1159 [ + + ]: 128 : for (size_t i = 0; i < m_aColumns.size(); i++)
1160 : 124 : m_aColumns[ i ]->Clear();
1161 : :
1162 [ + + ]: 4 : DELETEZ(m_pSeekCursor);
1163 [ + + ]: 4 : DELETEZ(m_pDataCursor);
1164 : :
1165 : 4 : m_xPaintRow = m_xDataRow = m_xEmptyRow = m_xCurrentRow = m_xSeekRow = NULL;
1166 : 4 : m_nCurrentPos = m_nSeekPos = m_nTotalCount = -1;
1167 : 4 : m_nOptions = OPT_READONLY;
1168 : :
1169 : : // Anzahl Saetze im Browser auf 0 zuruecksetzen
1170 : 4 : DbGridControl_Base::RemoveRows();
1171 : 4 : m_aBar.InvalidateAll(m_nCurrentPos, sal_True);
1172 : 4 : }
1173 : :
1174 : : //------------------------------------------------------------------------------
1175 : 301 : void DbGridControl::ArrangeControls(sal_uInt16& nX, sal_uInt16 nY)
1176 : : {
1177 : : // Positionierung der Controls
1178 [ + + ]: 301 : if (m_bNavigationBar)
1179 : : {
1180 : 154 : nX = m_aBar.GetDefaultWidth();
1181 [ + - ]: 154 : Rectangle aRect(GetControlArea());
1182 [ + - ][ + - ]: 154 : m_aBar.SetPosSizePixel(Point(0,nY + 1), Size(nX, aRect.GetSize().Height() - 1));
1183 : : }
1184 : 301 : }
1185 : :
1186 : : //------------------------------------------------------------------------------
1187 : 54 : void DbGridControl::EnableHandle(sal_Bool bEnable)
1188 : : {
1189 [ + + ]: 54 : if (m_bHandle == bEnable)
1190 : 54 : return;
1191 : :
1192 : : // HandleColumn wird nur ausgeblendet,
1193 : : // da es sonst etliche Probleme mit dem Zeichnen gibt
1194 : 24 : RemoveColumn( HandleColumnId );
1195 : 24 : m_bHandle = bEnable;
1196 : 24 : InsertHandleColumn();
1197 : : }
1198 : :
1199 : : //------------------------------------------------------------------------------
1200 : : namespace
1201 : : {
1202 : 26 : bool adjustModeForScrollbars( BrowserMode& _rMode, sal_Bool _bNavigationBar, sal_Bool _bHideScrollbars )
1203 : : {
1204 : 26 : BrowserMode nOldMode = _rMode;
1205 : :
1206 [ + + ]: 26 : if ( !_bNavigationBar )
1207 : : {
1208 : 16 : _rMode &= ~BROWSER_AUTO_HSCROLL;
1209 : : }
1210 : :
1211 [ - + ]: 26 : if ( _bHideScrollbars )
1212 : : {
1213 : 0 : _rMode |= ( BROWSER_NO_HSCROLL | BROWSER_NO_VSCROLL );
1214 : 0 : _rMode &= ~( BROWSER_AUTO_HSCROLL | BROWSER_AUTO_VSCROLL );
1215 : : }
1216 : : else
1217 : : {
1218 : 26 : _rMode |= ( BROWSER_AUTO_HSCROLL | BROWSER_AUTO_VSCROLL );
1219 : 26 : _rMode &= ~( BROWSER_NO_HSCROLL | BROWSER_NO_VSCROLL );
1220 : : }
1221 : :
1222 : : // note: if we have a navigation bar, we always have a AUTO_HSCROLL. In particular,
1223 : : // _bHideScrollbars is ignored then
1224 [ + + ]: 26 : if ( _bNavigationBar )
1225 : : {
1226 : 10 : _rMode |= BROWSER_AUTO_HSCROLL;
1227 : 10 : _rMode &= ~BROWSER_NO_HSCROLL;
1228 : : }
1229 : :
1230 : 26 : return nOldMode != _rMode;
1231 : : }
1232 : : }
1233 : :
1234 : : //------------------------------------------------------------------------------
1235 : 54 : void DbGridControl::EnableNavigationBar(sal_Bool bEnable)
1236 : : {
1237 [ + + ]: 54 : if (m_bNavigationBar == bEnable)
1238 : 54 : return;
1239 : :
1240 : 24 : m_bNavigationBar = bEnable;
1241 : :
1242 [ + + ]: 24 : if (bEnable)
1243 : : {
1244 [ + - ]: 8 : m_aBar.Show();
1245 [ + - ]: 8 : m_aBar.Enable();
1246 [ + - ]: 8 : m_aBar.InvalidateAll(m_nCurrentPos, sal_True);
1247 : :
1248 [ - + ]: 8 : if ( adjustModeForScrollbars( m_nMode, m_bNavigationBar, m_bHideScrollbars ) )
1249 [ # # ]: 0 : SetMode( m_nMode );
1250 : :
1251 : : // liefert die Groe�e der Reserved ControlArea
1252 [ + - ]: 8 : Point aPoint = GetControlArea().TopLeft();
1253 : 8 : sal_uInt16 nX = (sal_uInt16)aPoint.X();
1254 : :
1255 [ + - ]: 8 : ArrangeControls(nX, (sal_uInt16)aPoint.Y());
1256 [ + - ]: 8 : ReserveControlArea((sal_uInt16)nX);
1257 : : }
1258 : : else
1259 : : {
1260 : 16 : m_aBar.Hide();
1261 : 16 : m_aBar.Disable();
1262 : :
1263 [ + - ]: 16 : if ( adjustModeForScrollbars( m_nMode, m_bNavigationBar, m_bHideScrollbars ) )
1264 : 16 : SetMode( m_nMode );
1265 : :
1266 : 16 : ReserveControlArea();
1267 : : }
1268 : : }
1269 : :
1270 : : //------------------------------------------------------------------------------
1271 : 0 : sal_uInt16 DbGridControl::SetOptions(sal_uInt16 nOpt)
1272 : : {
1273 : : DBG_ASSERT(!m_xCurrentRow || !m_xCurrentRow->IsModified(),
1274 : : "DbGridControl::SetOptions : please do not call when editing a record (things are much easier this way ;) !");
1275 : :
1276 : : // for the next setDataSource (which is triggered by a refresh, for instance)
1277 : 0 : m_nOptionMask = nOpt;
1278 : :
1279 : : // normalize the new options
1280 : 0 : Reference< XPropertySet > xDataSourceSet = m_pDataCursor->getPropertySet();
1281 [ # # ]: 0 : if (xDataSourceSet.is())
1282 : : {
1283 : : // feststellen welche Updatem�glichkeiten bestehen
1284 : 0 : sal_Int32 nPrivileges = 0;
1285 [ # # ][ # # ]: 0 : xDataSourceSet->getPropertyValue(FM_PROP_PRIVILEGES) >>= nPrivileges;
[ # # ]
1286 [ # # ]: 0 : if ((nPrivileges & Privilege::INSERT) == 0)
1287 : 0 : nOpt &= ~OPT_INSERT;
1288 [ # # ]: 0 : if ((nPrivileges & Privilege::UPDATE) == 0)
1289 : 0 : nOpt &= ~OPT_UPDATE;
1290 [ # # ]: 0 : if ((nPrivileges & Privilege::DELETE) == 0)
1291 : 0 : nOpt &= ~OPT_DELETE;
1292 : : }
1293 : : else
1294 : 0 : nOpt = OPT_READONLY;
1295 : :
1296 : : // need to do something after that ?
1297 [ # # ]: 0 : if (nOpt == m_nOptions)
1298 : 0 : return m_nOptions;
1299 : :
1300 : : // the 'update' option only affects our BrowserMode (with or w/o focus rect)
1301 : 0 : BrowserMode nNewMode = m_nMode;
1302 [ # # ]: 0 : if ((m_nMode & BROWSER_CURSOR_WO_FOCUS) == 0)
1303 : : {
1304 [ # # ]: 0 : if (nOpt & OPT_UPDATE)
1305 : 0 : nNewMode |= BROWSER_HIDECURSOR;
1306 : : else
1307 : 0 : nNewMode &= ~BROWSER_HIDECURSOR;
1308 : : }
1309 : : else
1310 : 0 : nNewMode &= ~BROWSER_HIDECURSOR;
1311 : : // should not be neccessary if EnablePermanentCursor is used to change the cursor behaviour, but to be sure ...
1312 : :
1313 [ # # ]: 0 : if (nNewMode != m_nMode)
1314 : : {
1315 [ # # ]: 0 : SetMode(nNewMode);
1316 : 0 : m_nMode = nNewMode;
1317 : : }
1318 : :
1319 : : // _after_ setting the mode because this results in an ActivateCell
1320 [ # # ]: 0 : DeactivateCell();
1321 : :
1322 : 0 : sal_Bool bInsertChanged = (nOpt & OPT_INSERT) != (m_nOptions & OPT_INSERT);
1323 : 0 : m_nOptions = nOpt;
1324 : : // we need to set this before the code below because it indirectly uses m_nOptions
1325 : :
1326 : : // the 'insert' option affects our empty row
1327 [ # # ]: 0 : if (bInsertChanged)
1328 : : {
1329 [ # # ]: 0 : if (m_nOptions & OPT_INSERT)
1330 : : { // the insert option is to be set
1331 [ # # ][ # # ]: 0 : m_xEmptyRow = new DbGridRow();
[ # # ]
1332 [ # # ][ # # ]: 0 : RowInserted(GetRowCount(), 1, sal_True);
1333 : : }
1334 : : else
1335 : : { // the insert option is to be reset
1336 [ # # ]: 0 : m_xEmptyRow = NULL;
1337 [ # # ][ # # ]: 0 : if ((GetCurRow() == GetRowCount() - 1) && (GetCurRow() > 0))
[ # # ][ # # ]
1338 [ # # ]: 0 : GoToRowColumnId(GetCurRow() - 1, GetCurColumnId());
1339 [ # # ][ # # ]: 0 : RowRemoved(GetRowCount(), 1, sal_True);
1340 : : }
1341 : : }
1342 : :
1343 : : // the 'delete' options has no immediate consequences
1344 : :
1345 [ # # ]: 0 : ActivateCell();
1346 [ # # ]: 0 : Invalidate();
1347 : 0 : return m_nOptions;
1348 : : }
1349 : :
1350 : : //------------------------------------------------------------------------------
1351 : 0 : void DbGridControl::ForceHideScrollbars( sal_Bool _bForce )
1352 : : {
1353 [ # # ]: 0 : if ( m_bHideScrollbars == _bForce )
1354 : 0 : return;
1355 : :
1356 : 0 : m_bHideScrollbars = _bForce;
1357 : :
1358 [ # # ]: 0 : if ( adjustModeForScrollbars( m_nMode, m_bNavigationBar, m_bHideScrollbars ) )
1359 : 0 : SetMode( m_nMode );
1360 : : }
1361 : :
1362 : : //------------------------------------------------------------------------------
1363 : 54 : void DbGridControl::EnablePermanentCursor(sal_Bool bEnable)
1364 : : {
1365 [ + + ]: 54 : if (IsPermanentCursorEnabled() == bEnable)
1366 : 54 : return;
1367 : :
1368 [ + + ]: 22 : if (bEnable)
1369 : : {
1370 : 14 : m_nMode &= ~BROWSER_HIDECURSOR; // without this BROWSER_CURSOR_WO_FOCUS won't have any affect
1371 : 14 : m_nMode |= BROWSER_CURSOR_WO_FOCUS;
1372 : : }
1373 : : else
1374 : : {
1375 [ - + ]: 8 : if (m_nOptions & OPT_UPDATE)
1376 : 0 : m_nMode |= BROWSER_HIDECURSOR; // no cursor at all
1377 : : else
1378 : 8 : m_nMode &= ~BROWSER_HIDECURSOR; // at least the "non-permanent" cursor
1379 : :
1380 : 8 : m_nMode &= ~BROWSER_CURSOR_WO_FOCUS;
1381 : : }
1382 : 22 : SetMode(m_nMode);
1383 : :
1384 : 22 : sal_Bool bWasEditing = IsEditing();
1385 : 22 : DeactivateCell();
1386 [ - + ]: 22 : if (bWasEditing)
1387 : 0 : ActivateCell();
1388 : : }
1389 : :
1390 : : //------------------------------------------------------------------------------
1391 : 56 : sal_Bool DbGridControl::IsPermanentCursorEnabled() const
1392 : : {
1393 [ + + ][ + - ]: 56 : return ((m_nMode & BROWSER_CURSOR_WO_FOCUS) != 0) && ((m_nMode & BROWSER_HIDECURSOR) == 0);
1394 : : }
1395 : :
1396 : : //------------------------------------------------------------------------------
1397 : 0 : void DbGridControl::refreshController(sal_uInt16 _nColId, GrantControlAccess /*_aAccess*/)
1398 : : {
1399 [ # # ][ # # ]: 0 : if ((GetCurColumnId() == _nColId) && IsEditing())
[ # # ]
1400 : : { // the controller which is currently active needs to be refreshed
1401 : 0 : DeactivateCell();
1402 : 0 : ActivateCell();
1403 : : }
1404 : 0 : }
1405 : :
1406 : : //------------------------------------------------------------------------------
1407 : 8 : void DbGridControl::setDataSource(const Reference< XRowSet >& _xCursor, sal_uInt16 nOpts)
1408 : : {
1409 [ + + ][ + + ]: 8 : if (!_xCursor.is() && !m_pDataCursor)
[ + + ]
1410 : : return;
1411 : :
1412 [ + + ]: 4 : if (m_pDataSourcePropMultiplexer)
1413 : : {
1414 [ + - ]: 2 : m_pDataSourcePropMultiplexer->dispose();
1415 : 2 : m_pDataSourcePropMultiplexer->release(); // this should delete the multiplexer
1416 [ + - ][ + - ]: 2 : delete m_pDataSourcePropListener;
1417 : 2 : m_pDataSourcePropMultiplexer = NULL;
1418 : 2 : m_pDataSourcePropListener = NULL;
1419 : : }
1420 : 4 : m_xRowSetListener.clear();
1421 : :
1422 : : // is the new cursor valid ?
1423 : : // the cursor is only valid if it contains some columns
1424 : : // if there is no cursor or the cursor is not valid we have to clean up an leave
1425 [ + - ][ + - ]: 4 : if (!_xCursor.is() || !Reference< XColumnsSupplier > (_xCursor, UNO_QUERY)->getColumns()->hasElements())
[ + - ][ + - ]
[ + - ][ - + ]
[ + + ][ + + ]
[ + + # #
# # ][ + + ]
1426 : : {
1427 [ + - ]: 2 : RemoveRows();
1428 : : return;
1429 : : }
1430 : :
1431 : : // Hat sich der DatenCursor verandert ?
1432 [ + - ]: 2 : sal_uInt16 nCurPos = GetColumnPos(GetCurColumnId());
1433 : :
1434 [ + - ]: 2 : SetUpdateMode(sal_False);
1435 [ + - ]: 2 : RemoveRows();
1436 [ + - ]: 2 : DisconnectFromFields();
1437 : :
1438 [ - + ][ # # ]: 2 : DELETEZ(m_pCursorDisposeListener);
1439 : :
1440 : : {
1441 [ + - ]: 2 : ::osl::MutexGuard aGuard(m_aAdjustSafety);
1442 [ - + ]: 2 : if (m_nAsynAdjustEvent)
1443 : : {
1444 : : // the adjust was thought to work with the old cursor which we don't have anymore
1445 [ # # ]: 0 : RemoveUserEvent(m_nAsynAdjustEvent);
1446 : 0 : m_nAsynAdjustEvent = 0;
1447 [ + - ]: 2 : }
1448 : : }
1449 : :
1450 : : // get a new formatter and data cursor
1451 [ + - ]: 2 : m_xFormatter = NULL;
1452 [ + - ]: 2 : OStaticDataAccessTools aStaticTools;
1453 [ + - ][ + - ]: 2 : Reference< ::com::sun::star::util::XNumberFormatsSupplier > xSupplier = aStaticTools.getNumberFormats(aStaticTools.getRowSetConnection(_xCursor), sal_True);
1454 [ + - ][ + - ]: 2 : if (xSupplier.is() && m_xServiceFactory.is())
[ + - ]
1455 : : {
1456 : : m_xFormatter = Reference< ::com::sun::star::util::XNumberFormatter >(
1457 [ + - ]: 2 : m_xServiceFactory->createInstance(FM_NUMBER_FORMATTER),
1458 [ + - ][ + - ]: 2 : UNO_QUERY);
[ + - ][ + - ]
1459 [ + - ]: 2 : if (m_xFormatter.is())
1460 : : {
1461 [ + - ][ + - ]: 2 : m_xFormatter->attachNumberFormatsSupplier(xSupplier);
1462 : :
1463 : : // retrieve the datebase of the Numberformatter
1464 : : try
1465 : : {
1466 [ + - ][ + - ]: 2 : xSupplier->getNumberFormatSettings()->getPropertyValue(rtl::OUString("NullDate")) >>= m_aNullDate;
[ + - ][ + - ]
[ + - ][ # # ]
1467 : : }
1468 [ # # ]: 0 : catch(Exception&)
1469 : : {
1470 : : }
1471 : : }
1472 : : }
1473 : :
1474 [ + - ][ + - ]: 2 : m_pDataCursor = new CursorWrapper(_xCursor);
1475 : :
1476 : : // now create a cursor for painting rows
1477 : : // we need that cursor only if we are not in insert only mode
1478 : 2 : Reference< XResultSet > xClone;
1479 [ + - ]: 2 : Reference< XResultSetAccess > xAccess( _xCursor, UNO_QUERY );
1480 : : try
1481 : : {
1482 [ + - ][ + - ]: 2 : xClone = xAccess.is() ? xAccess->createResultSet() : Reference< XResultSet > ();
[ + - ][ + - ]
[ # # ]
1483 : : }
1484 [ # # ]: 0 : catch(Exception&)
1485 : : {
1486 : : }
1487 [ + - ]: 2 : if (xClone.is())
1488 [ + - ][ + - ]: 2 : m_pSeekCursor = new CursorWrapper(xClone);
1489 : :
1490 : : // property listening on the data source
1491 : : // (Normally one class would be sufficient : the multiplexer which could forward the property change to us.
1492 : : // But for that we would have been derived from ::comphelper::OPropertyChangeListener, which isn't exported.
1493 : : // So we introduce a second class, which is a ::comphelper::OPropertyChangeListener (in the implementation file we know this class)
1494 : : // and forwards the property changes to a our special method "DataSourcePropertyChanged".)
1495 [ + - ]: 2 : if (m_pDataCursor)
1496 : : {
1497 [ + - ][ + - ]: 2 : m_pDataSourcePropListener = new FmXGridSourcePropListener(this);
1498 [ + - ]: 2 : m_pDataSourcePropMultiplexer = new ::comphelper::OPropertyChangeMultiplexer(m_pDataSourcePropListener, m_pDataCursor->getPropertySet() );
1499 : 2 : m_pDataSourcePropMultiplexer->acquire();
1500 [ + - ][ + - ]: 2 : m_pDataSourcePropMultiplexer->addProperty(FM_PROP_ISMODIFIED);
1501 [ + - ][ + - ]: 2 : m_pDataSourcePropMultiplexer->addProperty(FM_PROP_ISNEW);
1502 : : }
1503 : :
1504 : 2 : BrowserMode nOldMode = m_nMode;
1505 [ + - ]: 2 : if (m_pSeekCursor)
1506 : : {
1507 : : try
1508 : : {
1509 [ + - ]: 2 : Reference< XPropertySet > xSet(_xCursor, UNO_QUERY);
1510 [ + - ]: 2 : if (xSet.is())
1511 : : {
1512 : : // feststellen welche Updatemoeglichkeiten bestehen
1513 : 2 : sal_Int32 nConcurrency = ResultSetConcurrency::READ_ONLY;
1514 [ + - ][ + - ]: 2 : xSet->getPropertyValue(FM_PROP_RESULTSET_CONCURRENCY) >>= nConcurrency;
[ + - ]
1515 : :
1516 [ + - ]: 2 : if ( ResultSetConcurrency::UPDATABLE == nConcurrency )
1517 : : {
1518 : 2 : sal_Int32 nPrivileges = 0;
1519 [ + - ][ + - ]: 2 : xSet->getPropertyValue(FM_PROP_PRIVILEGES) >>= nPrivileges;
[ + - ]
1520 : :
1521 : : // Insert Option should be set if insert only otherwise you won't see any rows
1522 : : // and no insertion is possible
1523 [ + - ][ + - ]: 2 : if ((m_nOptionMask & OPT_INSERT) && ((nPrivileges & Privilege::INSERT) == Privilege::INSERT) && (nOpts & OPT_INSERT))
[ + - ]
1524 : 2 : m_nOptions |= OPT_INSERT;
1525 [ + - ][ + - ]: 2 : if ((m_nOptionMask & OPT_UPDATE) && ((nPrivileges & Privilege::UPDATE) == Privilege::UPDATE) && (nOpts & OPT_UPDATE))
[ + - ]
1526 : 2 : m_nOptions |= OPT_UPDATE;
1527 [ + - ][ + - ]: 2 : if ((m_nOptionMask & OPT_DELETE) && ((nPrivileges & Privilege::DELETE) == Privilege::DELETE) && (nOpts & OPT_DELETE))
[ + - ]
1528 : 2 : m_nOptions |= OPT_DELETE;
1529 : : }
1530 [ # # ]: 2 : }
1531 : : }
1532 [ # # ]: 0 : catch( const Exception& )
1533 : : {
1534 : : DBG_UNHANDLED_EXCEPTION();
1535 : : }
1536 : :
1537 [ + - ]: 2 : sal_Bool bPermanentCursor = IsPermanentCursorEnabled();
1538 : 2 : m_nMode = DEFAULT_BROWSE_MODE;
1539 : :
1540 [ - + ]: 2 : if ( bPermanentCursor )
1541 : : {
1542 : 0 : m_nMode |= BROWSER_CURSOR_WO_FOCUS;
1543 : 0 : m_nMode &= ~BROWSER_HIDECURSOR;
1544 : : }
1545 : : else
1546 : : {
1547 : : // Duerfen Updates gemacht werden, kein Focus-RechtEck
1548 [ + - ]: 2 : if ( m_nOptions & OPT_UPDATE )
1549 : 2 : m_nMode |= BROWSER_HIDECURSOR;
1550 : : }
1551 : :
1552 [ + - ]: 2 : if ( m_bMultiSelection )
1553 : 2 : m_nMode |= BROWSER_MULTISELECTION;
1554 : : else
1555 : 0 : m_nMode &= ~BROWSER_MULTISELECTION;
1556 : :
1557 : 2 : adjustModeForScrollbars( m_nMode, m_bNavigationBar, m_bHideScrollbars );
1558 : :
1559 [ + - ]: 2 : Reference< XColumnsSupplier > xSupplyColumns(_xCursor, UNO_QUERY);
1560 [ + - ]: 2 : if (xSupplyColumns.is())
1561 [ + - ][ + - ]: 2 : InitColumnsByFields(Reference< XIndexAccess > (xSupplyColumns->getColumns(), UNO_QUERY));
[ + - ][ + - ]
1562 : :
1563 [ + - ]: 2 : ConnectToFields();
1564 : : }
1565 : :
1566 : 2 : sal_uInt32 nRecordCount(0);
1567 : :
1568 [ + - ]: 2 : if (m_pSeekCursor)
1569 : : {
1570 : 2 : Reference< XPropertySet > xSet = m_pDataCursor->getPropertySet();
1571 [ + - ][ + - ]: 2 : xSet->getPropertyValue(FM_PROP_ROWCOUNT) >>= nRecordCount;
[ + - ]
1572 [ + - ][ + - ]: 2 : m_bRecordCountFinal = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ROWCOUNTFINAL));
[ + - ][ + - ]
1573 : :
1574 [ + - ][ + - ]: 2 : m_xRowSetListener = new RowSetEventListener(this);
[ + - ]
1575 [ + - ]: 2 : Reference< XRowsChangeBroadcaster> xChangeBroad(xSet,UNO_QUERY);
1576 [ + - ]: 2 : if ( xChangeBroad.is( ) )
1577 [ + - ][ + - ]: 2 : xChangeBroad->addRowsChangeListener(m_xRowSetListener);
1578 : :
1579 : :
1580 : : // insert the currently known rows
1581 : : // and one row if we are able to insert rows
1582 [ + - ]: 2 : if (m_nOptions & OPT_INSERT)
1583 : : {
1584 : : // insert the empty row for insertion
1585 [ + - ][ + - ]: 2 : m_xEmptyRow = new DbGridRow();
[ + - ]
1586 : 2 : ++nRecordCount;
1587 : : }
1588 [ + - ]: 2 : if (nRecordCount)
1589 : : {
1590 [ + - ][ + - ]: 2 : m_xPaintRow = m_xSeekRow = new DbGridRow(m_pSeekCursor, sal_True);
[ + - ][ + - ]
1591 [ + - ][ + - ]: 2 : m_xDataRow = new DbGridRow(m_pDataCursor, sal_False);
[ + - # # ]
1592 [ + - ]: 2 : RowInserted(0, nRecordCount, sal_False);
1593 : :
1594 [ + - ]: 2 : if (m_xSeekRow->IsValid())
1595 : : try
1596 : : {
1597 [ + - ]: 2 : m_nSeekPos = m_pSeekCursor->getRow() - 1;
1598 : : }
1599 [ # # ]: 0 : catch( const Exception& )
1600 : : {
1601 : : DBG_UNHANDLED_EXCEPTION();
1602 : 0 : m_nSeekPos = -1;
1603 : : }
1604 : : }
1605 : : else
1606 : : {
1607 : : // no rows so we don't need a seekcursor
1608 [ # # ][ # # ]: 0 : DELETEZ(m_pSeekCursor);
1609 : 2 : }
1610 : : }
1611 : :
1612 : : // Zur alten Spalte gehen
1613 [ - + ][ # # ]: 2 : if (nCurPos == BROWSER_INVALIDID || nCurPos >= ColCount())
[ # # ][ + - ]
1614 : 2 : nCurPos = 0;
1615 : :
1616 : : // there are rows so go to the selected current column
1617 [ + - ]: 2 : if (nRecordCount)
1618 [ + - ][ + - ]: 2 : GoToRowColumnId(0, GetColumnId(nCurPos));
1619 : : // else stop the editing if neccessary
1620 [ # # ]: 0 : else if (IsEditing())
1621 [ # # ]: 0 : DeactivateCell();
1622 : :
1623 : : // now reset the mode
1624 [ + - ]: 2 : if (m_nMode != nOldMode)
1625 [ + - ]: 2 : SetMode(m_nMode);
1626 : :
1627 : : // beim Resizen wird RecalcRows gerufen
1628 [ + - ][ + - ]: 2 : if (!IsResizing() && GetRowCount())
[ + - ][ + - ]
1629 [ + - ][ + - ]: 2 : RecalcRows(GetTopRow(), GetVisibleRows(), sal_True);
1630 : :
1631 [ + - ]: 2 : m_aBar.InvalidateAll(m_nCurrentPos, sal_True);
1632 [ + - ]: 2 : SetUpdateMode(sal_True);
1633 : :
1634 : : // start listening on the seek cursor
1635 [ + - ]: 2 : if (m_pSeekCursor)
1636 [ + - ][ + - ]: 8 : m_pCursorDisposeListener = new DisposeListenerGridBridge(*this, Reference< XComponent > ((Reference< XInterface >)*m_pSeekCursor, UNO_QUERY), 0);
[ + - ][ + - ]
1637 : : }
1638 : :
1639 : : //------------------------------------------------------------------------------
1640 : 42 : void DbGridControl::RemoveColumns()
1641 : : {
1642 [ - + ]: 42 : if ( IsEditing() )
1643 : 0 : DeactivateCell();
1644 : :
1645 [ + + ]: 160 : for (size_t i = 0, n = m_aColumns.size(); i < n; i++)
1646 [ + - ]: 118 : delete m_aColumns[ i ];
1647 : 42 : m_aColumns.clear();
1648 : :
1649 : 42 : DbGridControl_Base::RemoveColumns();
1650 : 42 : }
1651 : :
1652 : : //------------------------------------------------------------------------------
1653 : 138 : DbGridColumn* DbGridControl::CreateColumn(sal_uInt16 nId) const
1654 : : {
1655 [ + - ]: 138 : return new DbGridColumn(nId, *(DbGridControl*)this);
1656 : : }
1657 : :
1658 : : //------------------------------------------------------------------------------
1659 : 138 : sal_uInt16 DbGridControl::AppendColumn(const XubString& rName, sal_uInt16 nWidth, sal_uInt16 nModelPos, sal_uInt16 nId)
1660 : : {
1661 : : DBG_ASSERT(nId == BROWSER_INVALIDID, "DbGridControl::AppendColumn : I want to set the ID myself ...");
1662 : 138 : sal_uInt16 nRealPos = nModelPos;
1663 [ + + ]: 138 : if (nModelPos != HEADERBAR_APPEND)
1664 : : {
1665 : : // calc the view pos. we can't use our converting functions because the new column
1666 : : // has no VCL-representation, yet.
1667 : 102 : sal_Int16 nViewPos = nModelPos;
1668 [ + + ]: 1068 : while (nModelPos--)
1669 : : {
1670 [ - + ]: 966 : if ( m_aColumns[ nModelPos ]->IsHidden() )
1671 : 0 : --nViewPos;
1672 : : }
1673 : : // restore nModelPos, we need it later
1674 : 102 : nModelPos = nRealPos;
1675 : : // the position the base class gets is the view pos + 1 (because of the handle column)
1676 : 102 : nRealPos = nViewPos + 1;
1677 : : }
1678 : :
1679 : : // calculate the new id
1680 [ + + ][ + - ]: 1124 : for (nId=1; (GetModelColumnPos(nId) != GRID_COLUMN_NOT_FOUND) && (nId <= m_aColumns.size()); ++nId)
[ + + ]
1681 : : ;
1682 : : DBG_ASSERT(GetViewColumnPos(nId) == GRID_COLUMN_NOT_FOUND, "DbGridControl::AppendColumn : inconsistent internal state !");
1683 : : // my column's models say "there is no column with id nId", but the view (the base class) says "there is a column ..."
1684 : :
1685 : 138 : DbGridControl_Base::AppendColumn(rName, nWidth, nRealPos, nId);
1686 [ + + ]: 138 : if (nModelPos == HEADERBAR_APPEND)
1687 [ + - ]: 36 : m_aColumns.push_back( CreateColumn(nId) );
1688 : : else
1689 : : {
1690 : 102 : DbGridColumns::iterator it = m_aColumns.begin();
1691 [ + - ]: 102 : ::std::advance( it, nModelPos );
1692 [ + - ][ + - ]: 102 : m_aColumns.insert( it, CreateColumn(nId) );
1693 : : }
1694 : :
1695 : 138 : return nId;
1696 : : }
1697 : :
1698 : : //------------------------------------------------------------------------------
1699 : 44 : void DbGridControl::RemoveColumn(sal_uInt16 nId)
1700 : : {
1701 : 44 : DbGridControl_Base::RemoveColumn(nId);
1702 : :
1703 : 44 : const sal_uInt16 nIndex = GetModelColumnPos(nId);
1704 [ + + ]: 44 : if(nIndex != GRID_COLUMN_NOT_FOUND)
1705 : : {
1706 [ + - ]: 20 : delete m_aColumns[nIndex];
1707 [ + - ][ + - ]: 20 : m_aColumns.erase( m_aColumns.begin()+nIndex );
1708 : : }
1709 : 44 : }
1710 : :
1711 : : //------------------------------------------------------------------------------
1712 : 0 : void DbGridControl::ColumnMoved(sal_uInt16 nId)
1713 : : {
1714 [ # # ]: 0 : DbGridControl_Base::ColumnMoved(nId);
1715 : :
1716 : : // remove the col from the model
1717 [ # # ]: 0 : sal_uInt16 nOldModelPos = GetModelColumnPos(nId);
1718 : : #ifdef DBG_UTIL
1719 : : DbGridColumn* pCol = m_aColumns[ (sal_uInt32)nOldModelPos ];
1720 : : DBG_ASSERT(!pCol->IsHidden(), "DbGridControl::ColumnMoved : moved a hidden col ? how this ?");
1721 : : #endif
1722 : :
1723 : : // for the new model pos we can't use GetModelColumnPos because we are altering the model at the moment
1724 : : // so the method won't work (in fact it would return the old model pos)
1725 : :
1726 : : // the new view pos is calculated easily
1727 [ # # ]: 0 : sal_uInt16 nNewViewPos = GetViewColumnPos(nId);
1728 : :
1729 : : // from that we can compute the new model pos
1730 : : sal_uInt16 nNewModelPos;
1731 [ # # ]: 0 : for (nNewModelPos = 0; nNewModelPos < m_aColumns.size(); ++nNewModelPos)
1732 : : {
1733 [ # # ]: 0 : if (!m_aColumns[ nNewModelPos ]->IsHidden())
1734 : : {
1735 [ # # ]: 0 : if (!nNewViewPos)
1736 : 0 : break;
1737 : : else
1738 : 0 : --nNewViewPos;
1739 : : }
1740 : : }
1741 : : DBG_ASSERT( nNewModelPos < m_aColumns.size(), "DbGridControl::ColumnMoved : could not find the new model position !");
1742 : :
1743 : : // this will work. of course the model isn't fully consistent with our view right now, but let's
1744 : : // look at the situation : a column has been moved with in the VIEW from pos m to n, say m<n (in the
1745 : : // other case we can use analogue arguments).
1746 : : // All cols k with m<k<=n have been shifted left on pos, the former col m now has pos n.
1747 : : // In the model this affects a range of cols x to y, where x<=m and y<=n. And the number of hidden cols
1748 : : // within this range is constant, so we may calculate the view pos from the model pos in the above way.
1749 : : //
1750 : : // for instance, let's look at a grid with six columns where the third one is hidden. this will
1751 : : // initially look like this :
1752 : : //
1753 : : // +---+---+---+---+---+---+
1754 : : // model pos | 0 | 1 |*2*| 3 | 4 | 5 |
1755 : : // +---+---+---+---+---+---+
1756 : : // ID | 1 | 2 | 3 | 4 | 5 | 6 |
1757 : : // +---+---+---+---+---+---+
1758 : : // view pos | 0 | 1 | - | 2 | 3 | 4 |
1759 : : // +---+---+---+---+---+---+
1760 : : //
1761 : : // if we move the column at (view) pos 1 to (view) pos 3 we have :
1762 : : //
1763 : : // +---+---+---+---+---+---+
1764 : : // model pos | 0 | 3 |*2*| 4 | 1 | 5 | // not reflecting the changes, yet
1765 : : // +---+---+---+---+---+---+
1766 : : // ID | 1 | 4 | 3 | 5 | 2 | 6 | // already reflecting the changes
1767 : : // +---+---+---+---+---+---+
1768 : : // view pos | 0 | 1 | - | 2 | 3 | 4 |
1769 : : // +---+---+---+---+---+---+
1770 : : //
1771 : : // or, sorted by the out-of-date model positions :
1772 : : //
1773 : : // +---+---+---+---+---+---+
1774 : : // model pos | 0 | 1 |*2*| 3 | 4 | 5 |
1775 : : // +---+---+---+---+---+---+
1776 : : // ID | 1 | 2 | 3 | 4 | 5 | 6 |
1777 : : // +---+---+---+---+---+---+
1778 : : // view pos | 0 | 3 | - | 1 | 2 | 4 |
1779 : : // +---+---+---+---+---+---+
1780 : : //
1781 : : // We know the new view pos (3) of the moved column because our base class tells us. So we look at our
1782 : : // model for the 4th (the pos is zero-based) visible column, it is at (model) position 4. And this is
1783 : : // exactly the pos where we have to re-insert our column's model, so it looks ike this :
1784 : : //
1785 : : // +---+---+---+---+---+---+
1786 : : // model pos | 0 |*1*| 2 | 3 | 4 | 5 |
1787 : : // +---+---+---+---+---+---+
1788 : : // ID | 1 | 3 | 4 | 5 | 2 | 6 |
1789 : : // +---+---+---+---+---+---+
1790 : : // view pos | 0 | - | 1 | 2 | 3 | 4 |
1791 : : // +---+---+---+---+---+---+
1792 : : //
1793 : : // Now, all is consistent again.
1794 : : // (except of the hidden column : The cycling of the cols occurred on the model, not on the view. maybe
1795 : : // the user expected the latter but there really is no good argument against our method ;) ...)
1796 : : //
1797 : : // And no, this large explanation isn't just because I wanted to play a board game or something like
1798 : : // that. It's because it took me a while to see it myself, and the whole theme (hidden cols, model col
1799 : : // positions, view col positions) is really painful (at least for me) so the above pictures helped me a lot ;)
1800 : :
1801 : :
1802 : 0 : DbGridColumn* temp = m_aColumns[ nOldModelPos ];
1803 : :
1804 : 0 : DbGridColumns::iterator it = m_aColumns.begin();
1805 [ # # ]: 0 : ::std::advance( it, nOldModelPos );
1806 [ # # ]: 0 : m_aColumns.erase( it );
1807 : :
1808 : 0 : it = m_aColumns.begin();
1809 [ # # ]: 0 : ::std::advance( it, nNewModelPos );
1810 [ # # ]: 0 : m_aColumns.insert( it, temp );
1811 : 0 : }
1812 : :
1813 : : //------------------------------------------------------------------------------
1814 : 16 : sal_Bool DbGridControl::SeekRow(long nRow)
1815 : : {
1816 : : // in filter mode or in insert only mode we don't have any cursor!
1817 [ - + ]: 16 : if ( !SeekCursor( nRow ) )
1818 : 0 : return sal_False;
1819 : :
1820 [ - + ]: 16 : if ( IsFilterMode() )
1821 : : {
1822 : : DBG_ASSERT( IsFilterRow( nRow ), "DbGridControl::SeekRow(): No filter row, wrong mode" );
1823 : 0 : m_xPaintRow = m_xEmptyRow;
1824 : : }
1825 : : else
1826 : : {
1827 : : // on the current position we have to take the current row for display as we want
1828 : : // to have the most recent values for display
1829 [ + + ][ + - ]: 16 : if ( ( nRow == m_nCurrentPos ) && getDisplaySynchron() )
[ + + ]
1830 : 2 : m_xPaintRow = m_xCurrentRow;
1831 : : // seek to the empty insert row
1832 [ - + ]: 14 : else if ( IsInsertionRow( nRow ) )
1833 : 0 : m_xPaintRow = m_xEmptyRow;
1834 : : else
1835 : : {
1836 : 14 : m_xSeekRow->SetState( m_pSeekCursor, sal_True );
1837 : 14 : m_xPaintRow = m_xSeekRow;
1838 : : }
1839 : : }
1840 : :
1841 : 16 : DbGridControl_Base::SeekRow(nRow);
1842 : :
1843 : 16 : return m_nSeekPos >= 0;
1844 : : }
1845 : : //------------------------------------------------------------------------------
1846 : : // Wird aufgerufen, wenn die dargestellte Datenmenge sich aendert
1847 : : //------------------------------------------------------------------------------
1848 : 115 : void DbGridControl::VisibleRowsChanged( long nNewTopRow, sal_uInt16 nLinesOnScreen )
1849 : : {
1850 : 115 : RecalcRows(nNewTopRow, nLinesOnScreen , sal_False);
1851 : 115 : }
1852 : :
1853 : : //------------------------------------------------------------------------------
1854 : 117 : void DbGridControl::RecalcRows(long nNewTopRow, sal_uInt16 nLinesOnScreen, sal_Bool bUpdateCursor)
1855 : : {
1856 : : DBG_CHKTHIS( DbGridControl, NULL );
1857 : : // Wenn kein Cursor -> keine Rows im Browser.
1858 [ + + ]: 117 : if (!m_pSeekCursor)
1859 : : {
1860 : : DBG_ASSERT(GetRowCount() == 0,"DbGridControl: ohne Cursor darf es keine Rows geben");
1861 : 117 : return;
1862 : : }
1863 : :
1864 : : // ignore any updates implicit made
1865 [ - + ][ # # ]: 2 : sal_Bool bDisablePaint = !bUpdateCursor && IsPaintEnabled();
[ # # ]
1866 [ - + ]: 2 : if (bDisablePaint)
1867 [ # # ]: 0 : EnablePaint(sal_False);
1868 : :
1869 : : // Cache an den sichtbaren Bereich anpassen
1870 : 2 : Reference< XPropertySet > xSet = m_pSeekCursor->getPropertySet();
1871 : 2 : sal_Int32 nCacheSize = 0;
1872 [ + - ][ + - ]: 2 : xSet->getPropertyValue(FM_PROP_FETCHSIZE) >>= nCacheSize;
[ + - ]
1873 : 2 : sal_Bool bCacheAligned = sal_False;
1874 : : // Nach der Initialisierung (m_nSeekPos < 0) keine Cursorbewegung, da bereits auf den ersten
1875 : : // Satz positioniert
1876 : 2 : long nDelta = nNewTopRow - GetTopRow();
1877 : : // Limit fuer relative Positionierung
1878 [ + - ]: 2 : long nLimit = (nCacheSize) ? nCacheSize / 2 : 0;
1879 : :
1880 : : // mehr Zeilen auf dem Bildschirm als im Cache
1881 [ - + ]: 2 : if (nLimit < nLinesOnScreen)
1882 : : {
1883 : 0 : Any aCacheSize;
1884 [ # # ]: 0 : aCacheSize <<= sal_Int32(nLinesOnScreen*2);
1885 [ # # ][ # # ]: 0 : xSet->setPropertyValue(FM_PROP_FETCHSIZE, aCacheSize);
[ # # ]
1886 : : // jetzt auf alle Faelle den Cursor anpassen
1887 : 0 : bUpdateCursor = sal_True;
1888 : 0 : bCacheAligned = sal_True;
1889 : 0 : nLimit = nLinesOnScreen;
1890 : : }
1891 : :
1892 : : // Im folgenden werden die Positionierungen so vorgenommen, da� sichergestellt ist
1893 : : // da� ausreichend Zeilen im DatenCache vorhanden sind
1894 : :
1895 : : // Fenster geht nach unten, weniger als zwei Fenster Differenz
1896 : : // oder Cache angepasst und noch kein Rowcount
1897 [ + - ][ + - ]: 2 : if (nDelta < nLimit && (nDelta > 0
[ - + ][ # # ]
1898 : : || (bCacheAligned && m_nTotalCount < 0)) )
1899 [ # # ]: 0 : SeekCursor(nNewTopRow + nLinesOnScreen - 1, sal_False);
1900 [ - + ][ # # ]: 2 : else if (nDelta < 0 && Abs(nDelta) < nLimit)
[ - + ]
1901 [ # # ]: 0 : SeekCursor(nNewTopRow, sal_False);
1902 [ + - ][ + - ]: 2 : else if (nDelta != 0 || bUpdateCursor)
1903 [ + - ]: 2 : SeekCursor(nNewTopRow, sal_True);
1904 : :
1905 [ + - ]: 2 : AdjustRows();
1906 : :
1907 : : // ignore any updates implicit made
1908 [ + - ]: 117 : EnablePaint(sal_True);
1909 : : }
1910 : :
1911 : : //------------------------------------------------------------------------------
1912 : 2 : void DbGridControl::RowInserted(long nRow, long nNumRows, sal_Bool bDoPaint, sal_Bool bKeepSelection)
1913 : : {
1914 [ + - ]: 2 : if (nNumRows)
1915 : : {
1916 [ + - ][ + - ]: 2 : if (m_bRecordCountFinal && m_nTotalCount < 0)
1917 : : {
1918 : : // if we have an insert row we have to reduce to count by 1
1919 : : // as the total count reflects only the existing rows in database
1920 : 2 : m_nTotalCount = GetRowCount() + nNumRows;
1921 [ + - ]: 4 : if (m_xEmptyRow.Is())
1922 : 2 : --m_nTotalCount;
1923 : : }
1924 [ # # ]: 0 : else if (m_nTotalCount >= 0)
1925 : 0 : m_nTotalCount += nNumRows;
1926 : :
1927 : 2 : DbGridControl_Base::RowInserted(nRow, nNumRows, bDoPaint, bKeepSelection);
1928 : 2 : m_aBar.InvalidateState(NavigationBar::RECORD_COUNT);
1929 : : }
1930 : 2 : }
1931 : :
1932 : : //------------------------------------------------------------------------------
1933 : 0 : void DbGridControl::RowRemoved(long nRow, long nNumRows, sal_Bool bDoPaint)
1934 : : {
1935 [ # # ]: 0 : if (nNumRows)
1936 : : {
1937 [ # # ][ # # ]: 0 : if (m_bRecordCountFinal && m_nTotalCount < 0)
1938 : : {
1939 : 0 : m_nTotalCount = GetRowCount() - nNumRows;
1940 : : // if we have an insert row reduce by 1
1941 [ # # ]: 0 : if (m_xEmptyRow.Is())
1942 : 0 : --m_nTotalCount;
1943 : : }
1944 [ # # ]: 0 : else if (m_nTotalCount >= 0)
1945 : 0 : m_nTotalCount -= nNumRows;
1946 : :
1947 : 0 : DbGridControl_Base::RowRemoved(nRow, nNumRows, bDoPaint);
1948 : 0 : m_aBar.InvalidateState(NavigationBar::RECORD_COUNT);
1949 : : }
1950 : 0 : }
1951 : :
1952 : : //------------------------------------------------------------------------------
1953 : 10 : void DbGridControl::AdjustRows()
1954 : : {
1955 [ + + ]: 10 : if (!m_pSeekCursor)
1956 : 10 : return;
1957 : :
1958 : 2 : Reference< XPropertySet > xSet = m_pDataCursor->getPropertySet();
1959 : :
1960 : : // Aktualisieren des RecordCounts
1961 : 2 : sal_Int32 nRecordCount = 0;
1962 [ + - ][ + - ]: 2 : xSet->getPropertyValue(FM_PROP_ROWCOUNT) >>= nRecordCount;
[ + - ]
1963 [ - + ]: 2 : if (!m_bRecordCountFinal)
1964 [ # # ][ # # ]: 0 : m_bRecordCountFinal = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ROWCOUNTFINAL));
[ # # ][ # # ]
1965 : :
1966 : : // hat sich die aktuelle Anzahl Rows veraendert
1967 : : // hierbei muss auch beruecksichtigt werden,
1968 : : // das eine zusaetzliche Zeile zum einfuegen von Datensaetzen vorhanden sein kann
1969 : :
1970 : : // zusaetzliche AppendRow fuers einfuegen
1971 [ + - ]: 2 : if (m_nOptions & OPT_INSERT)
1972 : 2 : ++nRecordCount;
1973 : :
1974 : : // wird gerade eingefuegt, dann gehoert die gerade hinzuzufuegende
1975 : : // Zeile nicht zum RecordCount und die Appendrow ebenfalls nicht
1976 [ + - ][ + - ]: 2 : if (!IsUpdating() && m_bRecordCountFinal && IsModified() && m_xCurrentRow != m_xEmptyRow &&
[ + - ][ - + ]
[ # # # # ]
[ - + ]
1977 : 0 : m_xCurrentRow->IsNew())
1978 : 0 : ++nRecordCount;
1979 : : // das ist mit !m_bUpdating abgesichert : innerhalb von SaveRow (m_bUpdating == sal_True) wuerde sonst der Datensatz, den ich editiere
1980 : : // (und den SaveRow gerade angefuegt hat, wodurch diese Methode hier getriggert wurde), doppelt zaehlen : einmal ist er schon
1981 : : // in dem normalen RecordCount drin, zum zweiten wuerde er hier gezaehlt werden (60787 - FS)
1982 : :
1983 [ + - ][ - + ]: 2 : if (nRecordCount != GetRowCount())
1984 : : {
1985 [ # # ]: 0 : long nDelta = GetRowCount() - (long)nRecordCount;
1986 [ # # ]: 0 : if (nDelta > 0) // zuviele
1987 : : {
1988 [ # # ][ # # ]: 0 : RowRemoved(GetRowCount() - nDelta, nDelta, sal_False);
1989 : : // es sind Zeilen weggefallen, dann ab der aktuellen Position neu zeichen
1990 [ # # ]: 0 : Invalidate();
1991 : :
1992 [ # # ]: 0 : sal_Int32 nNewPos = AlignSeekCursor();
1993 [ # # ]: 0 : if (m_bSynchDisplay)
1994 [ # # ]: 0 : DbGridControl_Base::GoToRow(nNewPos);
1995 : :
1996 [ # # ]: 0 : SetCurrent(nNewPos);
1997 : : // there are rows so go to the selected current column
1998 [ # # ]: 0 : if (nRecordCount)
1999 [ # # ][ # # ]: 0 : GoToRowColumnId(nNewPos, GetColumnId(GetCurColumnId()));
2000 [ # # ][ # # ]: 0 : if (!IsResizing() && GetRowCount())
[ # # ][ # # ]
2001 [ # # ][ # # ]: 0 : RecalcRows(GetTopRow(), GetVisibleRows(), sal_True);
2002 [ # # ]: 0 : m_aBar.InvalidateAll(m_nCurrentPos, sal_True);
2003 : : }
2004 : : else // zuwenig
2005 [ # # ][ # # ]: 0 : RowInserted(GetRowCount(), -nDelta, sal_True);
2006 : : }
2007 : :
2008 [ + - ][ - + ]: 2 : if (m_bRecordCountFinal && m_nTotalCount < 0)
2009 : : {
2010 [ # # ]: 0 : if (m_nOptions & OPT_INSERT)
2011 [ # # ]: 0 : m_nTotalCount = GetRowCount() - 1;
2012 : : else
2013 [ # # ]: 0 : m_nTotalCount = GetRowCount();
2014 : : }
2015 [ + - ]: 10 : m_aBar.InvalidateState(NavigationBar::RECORD_COUNT);
2016 : : }
2017 : :
2018 : : //------------------------------------------------------------------------------
2019 : 16 : DbGridControl_Base::RowStatus DbGridControl::GetRowStatus(long nRow) const
2020 : : {
2021 [ - + ]: 16 : if (IsFilterRow(nRow))
2022 : 0 : return DbGridControl_Base::FILTER;
2023 [ + - ][ + + ]: 16 : else if (m_nCurrentPos >= 0 && nRow == m_nCurrentPos)
2024 : : {
2025 : : // neue Zeile
2026 [ - + ]: 2 : if (!IsValid(m_xCurrentRow))
2027 : 0 : return DbGridControl_Base::DELETED;
2028 [ - + ]: 2 : else if (IsModified())
2029 : 0 : return DbGridControl_Base::MODIFIED;
2030 [ - + ]: 2 : else if (m_xCurrentRow->IsNew())
2031 : 0 : return DbGridControl_Base::CURRENTNEW;
2032 : : else
2033 : 2 : return DbGridControl_Base::CURRENT;
2034 : : }
2035 [ - + ]: 14 : else if (IsInsertionRow(nRow))
2036 : 0 : return DbGridControl_Base::NEW;
2037 [ - + ]: 14 : else if (!IsValid(m_xSeekRow))
2038 : 0 : return DbGridControl_Base::DELETED;
2039 : : else
2040 : 16 : return DbGridControl_Base::CLEAN;
2041 : : }
2042 : :
2043 : : //------------------------------------------------------------------------------
2044 : 16 : void DbGridControl::PaintStatusCell(OutputDevice& rDev, const Rectangle& rRect) const
2045 : : {
2046 : 16 : DbGridControl_Base::PaintStatusCell(rDev, rRect);
2047 : 16 : }
2048 : :
2049 : : //------------------------------------------------------------------------------
2050 : 112 : void DbGridControl::PaintCell(OutputDevice& rDev, const Rectangle& rRect, sal_uInt16 nColumnId) const
2051 : : {
2052 [ - + ]: 112 : if (!IsValid(m_xPaintRow))
2053 : 112 : return;
2054 : :
2055 : 112 : size_t Location = GetModelColumnPos(nColumnId);
2056 [ + - ]: 112 : DbGridColumn* pColumn = (Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
2057 [ + - ]: 112 : if (pColumn)
2058 : : {
2059 : 112 : Rectangle aArea(rRect);
2060 [ - + ]: 112 : if ((GetMode() & BROWSER_CURSOR_WO_FOCUS) == BROWSER_CURSOR_WO_FOCUS)
2061 : : {
2062 : 0 : aArea.Top() += 1;
2063 : 0 : aArea.Bottom() -= 1;
2064 : : }
2065 [ + - ]: 112 : pColumn->Paint(rDev, aArea, m_xPaintRow, getNumberFormatter());
2066 : : }
2067 : : }
2068 : :
2069 : : //------------------------------------------------------------------------------
2070 : 2 : sal_Bool DbGridControl::CursorMoving(long nNewRow, sal_uInt16 nNewCol)
2071 : : {
2072 : : DBG_CHKTHIS( DbGridControl, NULL );
2073 : :
2074 : 2 : DeactivateCell( sal_False );
2075 : :
2076 [ + - - + ]: 4 : if ( m_pDataCursor
[ - + ][ + - ]
2077 : : && ( m_nCurrentPos != nNewRow )
2078 : 2 : && !SetCurrent( nNewRow )
2079 : : )
2080 : : {
2081 : 0 : ActivateCell();
2082 : 0 : return sal_False;
2083 : : }
2084 : :
2085 [ - + ]: 2 : if ( !DbGridControl_Base::CursorMoving( nNewRow, nNewCol ) )
2086 : 0 : return sal_False;
2087 : :
2088 : 2 : return sal_True;
2089 : : }
2090 : :
2091 : : //------------------------------------------------------------------------------
2092 : 2 : sal_Bool DbGridControl::SetCurrent(long nNewRow)
2093 : : {
2094 : : // Each movement of the datacursor must start with BeginCursorAction and end with
2095 : : // EndCursorAction to block all notifications during the movement
2096 : 2 : BeginCursorAction();
2097 : :
2098 : : try
2099 : : {
2100 : : // Abgleichen der Positionen
2101 [ + - ][ + - ]: 2 : if (SeekCursor(nNewRow))
2102 : : {
2103 [ - + ]: 2 : if (IsFilterRow(nNewRow)) // special mode for filtering
2104 : : {
2105 [ # # ][ # # ]: 0 : m_xCurrentRow = m_xDataRow = m_xPaintRow = m_xEmptyRow;
[ # # ]
2106 : 0 : m_nCurrentPos = nNewRow;
2107 : : }
2108 : : else
2109 : : {
2110 : 2 : sal_Bool bNewRowInserted = sal_False;
2111 : : // Should we go to the insertrow ?
2112 [ + - ][ - + ]: 2 : if (IsInsertionRow(nNewRow))
2113 : : {
2114 : : // to we need to move the cursor to the insert row?
2115 : : // we need to insert the if the current row isn't the insert row or if the
2116 : : // cursor triggered the move by itselt and we need a reinitialization of the row
2117 : 0 : Reference< XPropertySet > xCursorProps = m_pDataCursor->getPropertySet();
2118 [ # # ][ # # ]: 0 : if ( !::comphelper::getBOOL(xCursorProps->getPropertyValue(FM_PROP_ISNEW)) )
[ # # ][ # # ]
[ # # ]
2119 : : {
2120 [ # # ]: 0 : Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY);
2121 [ # # ][ # # ]: 0 : xUpdateCursor->moveToInsertRow();
2122 : : }
2123 : 0 : bNewRowInserted = sal_True;
2124 : : }
2125 : : else
2126 : : {
2127 : :
2128 [ + - ][ + - ]: 2 : if ( !m_pSeekCursor->isBeforeFirst() && !m_pSeekCursor->isAfterLast() )
[ + - ][ + - ]
[ + - ]
2129 : : {
2130 [ + - ]: 2 : Any aBookmark = m_pSeekCursor->getBookmark();
2131 [ - + ][ # # ]: 2 : if (!m_xCurrentRow || m_xCurrentRow->IsNew() || !CompareBookmark(aBookmark, m_pDataCursor->getBookmark()))
[ # # ][ # # ]
[ # # ][ - + ]
[ + - # # ]
2132 : : {
2133 : : // adjust the cursor to the new desired row
2134 [ + - ][ - + ]: 2 : if (!m_pDataCursor->moveToBookmark(aBookmark))
2135 : : {
2136 [ # # ]: 0 : EndCursorAction();
2137 : 2 : return sal_False;
2138 : : }
2139 [ + - ]: 2 : }
2140 : : }
2141 : : }
2142 [ + - ]: 2 : m_xDataRow->SetState(m_pDataCursor, sal_False);
2143 [ + - ]: 2 : m_xCurrentRow = m_xDataRow;
2144 : :
2145 : 2 : long nPaintPos = -1;
2146 : : // do we have to repaint the last regular row in case of setting defaults or autovalues
2147 [ - + ][ # # ]: 2 : if (m_nCurrentPos >= 0 && m_nCurrentPos >= (GetRowCount() - 2))
[ # # ][ - + ]
2148 : 0 : nPaintPos = m_nCurrentPos;
2149 : :
2150 : 2 : m_nCurrentPos = nNewRow;
2151 : :
2152 : : // repaint the new row to display all defaults
2153 [ - + ]: 2 : if (bNewRowInserted)
2154 [ # # ]: 0 : RowModified(m_nCurrentPos);
2155 [ - + ]: 2 : if (nPaintPos >= 0)
2156 [ # # ]: 0 : RowModified(nPaintPos);
2157 : : }
2158 : : }
2159 : : else
2160 : : {
2161 : : OSL_FAIL("DbGridControl::SetCurrent : SeekRow failed !");
2162 [ # # ]: 0 : EndCursorAction();
2163 : 0 : return sal_False;
2164 : : }
2165 : : }
2166 [ # # ]: 0 : catch ( const Exception& )
2167 : : {
2168 : : DBG_UNHANDLED_EXCEPTION();
2169 [ # # ]: 0 : EndCursorAction();
2170 : 0 : return sal_False;
2171 : : }
2172 : :
2173 : 2 : EndCursorAction();
2174 : 2 : return sal_True;
2175 : : }
2176 : :
2177 : : //------------------------------------------------------------------------------
2178 : 75 : void DbGridControl::CursorMoved()
2179 : : {
2180 : : DBG_CHKTHIS( DbGridControl, NULL );
2181 : :
2182 : : // CursorBewegung durch loeschen oder einfuegen von Zeilen
2183 [ + + ][ - + ]: 75 : if (m_pDataCursor && m_nCurrentPos != GetCurRow())
[ - + ]
2184 : : {
2185 : 0 : DeactivateCell(sal_True);
2186 : 0 : SetCurrent(GetCurRow());
2187 : : }
2188 : :
2189 : 75 : DbGridControl_Base::CursorMoved();
2190 : 75 : m_aBar.InvalidateAll(m_nCurrentPos);
2191 : :
2192 : : // select the new column when they moved
2193 [ - + ][ # # ]: 75 : if ( IsDesignMode() && GetSelectedColumnCount() > 0 && GetCurColumnId() )
[ - + ][ + + ]
2194 : : {
2195 : 0 : SelectColumnId( GetCurColumnId() );
2196 : : }
2197 : :
2198 [ + + ]: 75 : if ( m_nLastColId != GetCurColumnId() )
2199 : 2 : onColumnChange();
2200 : 75 : m_nLastColId = GetCurColumnId();
2201 : :
2202 [ + + ]: 75 : if ( m_nLastRowId != GetCurRow() )
2203 : 4 : onRowChange();
2204 : 75 : m_nLastRowId = GetCurRow();
2205 : 75 : }
2206 : :
2207 : : //------------------------------------------------------------------------------
2208 : 0 : void DbGridControl::onRowChange()
2209 : : {
2210 : : // not interested in
2211 : 0 : }
2212 : :
2213 : : //------------------------------------------------------------------------------
2214 : 0 : void DbGridControl::onColumnChange()
2215 : : {
2216 [ # # ]: 0 : if ( m_pGridListener )
2217 : 0 : m_pGridListener->columnChanged();
2218 : 0 : }
2219 : :
2220 : : //------------------------------------------------------------------------------
2221 : 54 : void DbGridControl::setDisplaySynchron(sal_Bool bSync)
2222 : : {
2223 [ + + ]: 54 : if (bSync != m_bSynchDisplay)
2224 : : {
2225 : 24 : m_bSynchDisplay = bSync;
2226 [ + + ]: 24 : if (m_bSynchDisplay)
2227 : 8 : AdjustDataSource(sal_False);
2228 : : }
2229 : 54 : }
2230 : :
2231 : : //------------------------------------------------------------------------------
2232 : 8 : void DbGridControl::AdjustDataSource(sal_Bool bFull)
2233 : : {
2234 : : TRACE_RANGE("DbGridControl::AdjustDataSource");
2235 [ + - ]: 8 : SolarMutexGuard aGuard;
2236 : : // wird die aktuelle Zeile gerade neu bestimmt,
2237 : : // wird kein abgleich vorgenommen
2238 : :
2239 [ - + ]: 8 : if (bFull)
2240 [ # # ]: 0 : m_xCurrentRow = NULL;
2241 : : // if we are on the same row only repaint
2242 : : // but this is only possible for rows which are not inserted, in that case the comparision result
2243 : : // may not be correct
2244 : : else
2245 [ - + # # ]: 8 : if ( m_xCurrentRow.Is()
[ # # ][ # # ]
[ # # ][ - + ]
2246 : 0 : && !m_xCurrentRow->IsNew()
2247 [ # # ]: 0 : && !m_pDataCursor->isBeforeFirst()
2248 [ # # ]: 0 : && !m_pDataCursor->isAfterLast()
2249 [ # # ]: 0 : && !m_pDataCursor->rowDeleted()
2250 : : )
2251 : : {
2252 [ # # ][ # # ]: 0 : sal_Bool bEqualBookmarks = CompareBookmark( m_xCurrentRow->GetBookmark(), m_pDataCursor->getBookmark() );
2253 : :
2254 : 0 : sal_Bool bDataCursorIsOnNew = sal_False;
2255 [ # # ][ # # ]: 0 : m_pDataCursor->getPropertySet()->getPropertyValue( FM_PROP_ISNEW ) >>= bDataCursorIsOnNew;
[ # # ]
2256 : :
2257 [ # # ][ # # ]: 0 : if ( bEqualBookmarks && !bDataCursorIsOnNew )
2258 : : {
2259 : : // position of my data cursor is the same as the position our current row points tpo
2260 : : // sync the status, repaint, done
2261 : : DBG_ASSERT(m_xDataRow == m_xCurrentRow, "Fehler in den Datenzeilen");
2262 : : TRACE_RANGE_MESSAGE1("same position, new state : %s", ROWSTATUS(m_xCurrentRow));
2263 [ # # ]: 0 : RowModified(m_nCurrentPos);
2264 : : return;
2265 : : }
2266 : : }
2267 : :
2268 : : // weg von der Row des DatenCursors
2269 [ + - ]: 8 : if (m_xPaintRow == m_xCurrentRow)
2270 [ + - ]: 8 : m_xPaintRow = m_xSeekRow;
2271 : :
2272 : : // keine aktuelle Zeile dann komplett anpassen
2273 [ + - ]: 8 : if (!m_xCurrentRow)
2274 [ + - ]: 8 : AdjustRows();
2275 : :
2276 [ + - ]: 8 : sal_Int32 nNewPos = AlignSeekCursor();
2277 [ + - ]: 8 : if (nNewPos < 0) // keine Position gefunden
2278 : : return;
2279 : :
2280 : 0 : m_bInAdjustDataSource = sal_True;
2281 [ # # ]: 0 : if (nNewPos != m_nCurrentPos)
2282 : : {
2283 [ # # ]: 0 : if (m_bSynchDisplay)
2284 [ # # ]: 0 : DbGridControl_Base::GoToRow(nNewPos);
2285 : :
2286 [ # # ]: 0 : if (!m_xCurrentRow.Is())
2287 : : // das tritt zum Beispiel auf, wenn man die n (n>1) letzten Datensaetze geloescht hat, waehrend der Cursor auf dem letzten
2288 : : // steht : AdjustRows entfernt dann zwei Zeilen aus der BrowseBox, wodurch diese ihre CurrentRow um zwei nach unten
2289 : : // korrigiert, so dass dann das GoToRow in's Leere laeuft (da wir uns ja angeblich schon an der richtigen Position
2290 : : // befinden)
2291 [ # # ]: 0 : SetCurrent(nNewPos);
2292 : : }
2293 : : else
2294 : : {
2295 [ # # ]: 0 : SetCurrent(nNewPos);
2296 [ # # ]: 0 : RowModified(nNewPos);
2297 : : }
2298 : 0 : m_bInAdjustDataSource = sal_False;
2299 : :
2300 : : // Wird der DatenCursor von aussen bewegt, wird die selektion aufgehoben
2301 [ # # ]: 0 : SetNoSelection();
2302 [ # # ][ + - ]: 8 : m_aBar.InvalidateAll(m_nCurrentPos, m_xCurrentRow.Is());
[ - + ]
2303 : : }
2304 : :
2305 : : //------------------------------------------------------------------------------
2306 : 8 : sal_Int32 DbGridControl::AlignSeekCursor()
2307 : : {
2308 : : DBG_CHKTHIS( DbGridControl, NULL );
2309 : : // Positioniert den SeekCursor auf den DatenCursor, Daten werden nicht uebertragen
2310 : :
2311 [ + - ]: 8 : if (!m_pSeekCursor)
2312 : 8 : return -1;
2313 : :
2314 : 0 : Reference< XPropertySet > xSet = m_pDataCursor->getPropertySet();
2315 : :
2316 : : // jetzt den seekcursor an den DatenCursor angleichen
2317 [ # # ][ # # ]: 0 : if (::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISNEW)))
[ # # ][ # # ]
[ # # ]
2318 [ # # ]: 0 : m_nSeekPos = GetRowCount() - 1;
2319 : : else
2320 : : {
2321 : : try
2322 : : {
2323 [ # # ][ # # ]: 0 : if ( m_pDataCursor->isBeforeFirst() )
2324 : : {
2325 : : // this is somewhat strange, but can nevertheless happen
2326 : : DBG_WARNING( "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (before first)!" );
2327 [ # # ]: 0 : m_pSeekCursor->first();
2328 [ # # ]: 0 : m_pSeekCursor->previous();
2329 : 0 : m_nSeekPos = -1;
2330 : : }
2331 [ # # ][ # # ]: 0 : else if ( m_pDataCursor->isAfterLast() )
2332 : : {
2333 : : DBG_WARNING( "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (after last)!" );
2334 [ # # ]: 0 : m_pSeekCursor->last();
2335 [ # # ]: 0 : m_pSeekCursor->next();
2336 : 0 : m_nSeekPos = -1;
2337 : : }
2338 : : else
2339 : : {
2340 [ # # ][ # # ]: 0 : m_pSeekCursor->moveToBookmark(m_pDataCursor->getBookmark());
2341 [ # # ][ # # ]: 0 : if (!CompareBookmark(m_pDataCursor->getBookmark(), m_pSeekCursor->getBookmark()))
[ # # ][ # # ]
2342 : : // dummerweise kann das moveToBookmark indirekt dazu fuehren, dass der Seek-Cursor wieder neu positoniert wird (wenn
2343 : : // naemlich das mit all seinen zu feuernden Events relativ komplexe moveToBookmark irgendwo ein Update ausloest),
2344 : : // also muss ich es nochmal versuchen
2345 [ # # ][ # # ]: 0 : m_pSeekCursor->moveToBookmark(m_pDataCursor->getBookmark());
[ # # ]
2346 : : // Nicht dass das jetzt nicht auch schief gegangen sein koennte, aber es ist zumindest unwahrscheinlicher geworden.
2347 : : // Und die Alternative waere eine Schleife so lange bis es stimmt, und das kann auch nicht die Loesung sein
2348 [ # # ]: 0 : m_nSeekPos = m_pSeekCursor->getRow() - 1;
2349 : : }
2350 : : }
2351 [ # # ]: 0 : catch(Exception&)
2352 : : {
2353 : : }
2354 : : }
2355 : 8 : return m_nSeekPos;
2356 : : }
2357 : : //------------------------------------------------------------------------------
2358 : 20 : sal_Bool DbGridControl::SeekCursor(long nRow, sal_Bool bAbsolute)
2359 : : {
2360 : : DBG_CHKTHIS( DbGridControl, NULL );
2361 : : // Positioniert den SeekCursor, Daten werden nicht uebertragen
2362 : :
2363 : : // additions for the filtermode
2364 [ - + ]: 20 : if (IsFilterRow(nRow))
2365 : : {
2366 : 0 : m_nSeekPos = 0;
2367 : 0 : return sal_True;
2368 : : }
2369 : :
2370 [ - + ]: 20 : if (!m_pSeekCursor)
2371 : 0 : return sal_False;
2372 : :
2373 : : // Befinden wir uns gerade beim Einfuegen
2374 [ + + ][ - + ]: 20 : if (IsValid(m_xCurrentRow) && m_xCurrentRow->IsNew() &&
[ # # ][ - + ]
2375 : : nRow >= m_nCurrentPos)
2376 : : {
2377 : : // dann darf auf alle Faelle nicht weiter nach unten gescrollt werden
2378 : : // da der letzte Datensatz bereits erreicht wurde!
2379 [ # # ]: 0 : if (nRow == m_nCurrentPos)
2380 : : {
2381 : : // auf die aktuelle Zeile bewegt, dann muß kein abgleich gemacht werden, wenn
2382 : : // gerade ein Datensatz eingefuegt wird
2383 : 0 : m_nSeekPos = nRow;
2384 : : }
2385 [ # # ]: 0 : else if (IsInsertionRow(nRow)) // Leerzeile zum Einfuegen von Datensaetzen
2386 : 0 : m_nSeekPos = nRow;
2387 : : }
2388 [ - + ]: 20 : else if (IsInsertionRow(nRow)) // Leerzeile zum Einfuegen von Datensaetzen
2389 : 0 : m_nSeekPos = nRow;
2390 [ - + ][ # # ]: 20 : else if ((-1 == nRow) && (GetRowCount() == ((m_nOptions & OPT_INSERT) ? 1 : 0)) && m_pSeekCursor->isAfterLast())
[ # # ][ - + ]
2391 : 0 : m_nSeekPos = nRow;
2392 : : else
2393 : : {
2394 : :
2395 : 20 : sal_Bool bSuccess=sal_False;
2396 : 20 : long nSteps = 0;
2397 : : try
2398 : : {
2399 [ + - ][ - + ]: 20 : if ( m_pSeekCursor->rowDeleted() )
2400 : : {
2401 : : // somebody deleted the current row of the seek cursor. Move it away from this row.
2402 [ # # ]: 0 : m_pSeekCursor->next();
2403 [ # # ][ # # ]: 0 : if ( m_pSeekCursor->isAfterLast() || m_pSeekCursor->isBeforeFirst() )
[ # # ][ # # ]
[ # # ]
2404 : 0 : bAbsolute = sal_True;
2405 : : }
2406 : :
2407 [ + + ]: 20 : if ( !bAbsolute )
2408 : : {
2409 : : DBG_ASSERT( !m_pSeekCursor->isAfterLast() && !m_pSeekCursor->isBeforeFirst(),
2410 : : "DbGridControl::SeekCursor: how did the seek cursor get to this position?!" );
2411 [ + - ]: 18 : nSteps = nRow - (m_pSeekCursor->getRow() - 1);
2412 [ + - ][ - + ]: 18 : bAbsolute = bAbsolute || (abs(nSteps) > 100);
2413 : : }
2414 : :
2415 [ + + ]: 20 : if ( bAbsolute )
2416 : : {
2417 [ + - ]: 2 : bSuccess = m_pSeekCursor->absolute(nRow + 1);
2418 [ + - ]: 2 : if (bSuccess)
2419 : 2 : m_nSeekPos = nRow;
2420 : : }
2421 : : else
2422 : : {
2423 [ + + ]: 18 : if (nSteps > 0) // auf den letzten benoetigten Datensatz positionieren
2424 : : {
2425 [ + - ][ - + ]: 14 : if (m_pSeekCursor->isAfterLast())
2426 : 0 : bSuccess = sal_False;
2427 [ + - ][ - + ]: 14 : else if (m_pSeekCursor->isBeforeFirst())
2428 [ # # ]: 0 : bSuccess = m_pSeekCursor->absolute(nSteps);
2429 : : else
2430 [ + - ]: 14 : bSuccess = m_pSeekCursor->relative(nSteps);
2431 : : }
2432 [ - + ]: 4 : else if (nSteps < 0)
2433 : : {
2434 [ # # ][ # # ]: 0 : if (m_pSeekCursor->isBeforeFirst())
2435 : 0 : bSuccess = sal_False;
2436 [ # # ][ # # ]: 0 : else if (m_pSeekCursor->isAfterLast())
2437 [ # # ]: 0 : bSuccess = m_pSeekCursor->absolute(nSteps);
2438 : : else
2439 [ # # ]: 0 : bSuccess = m_pSeekCursor->relative(nSteps);
2440 : : }
2441 : : else
2442 : : {
2443 : 4 : m_nSeekPos = nRow;
2444 : 4 : return sal_True;
2445 : : }
2446 : : }
2447 : : }
2448 [ # # ]: 0 : catch(Exception&)
2449 : : {
2450 : : OSL_FAIL("DbGridControl::SeekCursor : failed ...");
2451 : : }
2452 : :
2453 : : try
2454 : : {
2455 [ - + ]: 16 : if (!bSuccess)
2456 : : {
2457 [ # # ][ # # ]: 0 : if (bAbsolute || nSteps > 0)
2458 [ # # ]: 0 : bSuccess = m_pSeekCursor->last();
2459 : : else
2460 [ # # ]: 0 : bSuccess = m_pSeekCursor->first();
2461 : : }
2462 : :
2463 [ + - ]: 16 : if (bSuccess)
2464 [ + - ]: 16 : m_nSeekPos = m_pSeekCursor->getRow() - 1;
2465 : : else
2466 : 0 : m_nSeekPos = -1;
2467 : : }
2468 : 0 : catch(Exception&)
2469 : : {
2470 : : OSL_FAIL("DbGridControl::SeekCursor : failed ...");
2471 : : DBG_UNHANDLED_EXCEPTION();
2472 : 0 : m_nSeekPos = -1; // kein Datensatz mehr vorhanden
2473 : : }
2474 : : }
2475 [ # # ]: 20 : return m_nSeekPos == nRow;
2476 : : }
2477 : : //------------------------------------------------------------------------------
2478 : 0 : void DbGridControl::MoveToFirst()
2479 : : {
2480 [ # # ][ # # ]: 0 : if (m_pSeekCursor && (GetCurRow() != 0))
[ # # ]
2481 : 0 : MoveToPosition(0);
2482 : 0 : }
2483 : :
2484 : : //------------------------------------------------------------------------------
2485 : 0 : void DbGridControl::MoveToLast()
2486 : : {
2487 [ # # ]: 0 : if (!m_pSeekCursor)
2488 [ # # ]: 0 : return;
2489 : :
2490 [ # # ]: 0 : if (m_nTotalCount < 0) // RecordCount steht noch nicht fest
2491 : : {
2492 : : try
2493 : : {
2494 [ # # ]: 0 : sal_Bool bRes = m_pSeekCursor->last();
2495 : :
2496 [ # # ]: 0 : if (bRes)
2497 : : {
2498 [ # # ]: 0 : m_nSeekPos = m_pSeekCursor->getRow() - 1;
2499 [ # # ]: 0 : AdjustRows();
2500 : : }
2501 : : }
2502 : 0 : catch(Exception&)
2503 : : {
2504 : : }
2505 : : }
2506 : :
2507 : : // auf den letzen Datensatz positionieren, nicht auf die Leerzeile
2508 [ # # ]: 0 : if (m_nOptions & OPT_INSERT)
2509 : : {
2510 [ # # ]: 0 : if ((GetRowCount() - 1) > 0)
2511 : 0 : MoveToPosition(GetRowCount() - 2);
2512 : : }
2513 [ # # ]: 0 : else if (GetRowCount())
2514 : 0 : MoveToPosition(GetRowCount() - 1);
2515 : : }
2516 : :
2517 : : //------------------------------------------------------------------------------
2518 : 0 : void DbGridControl::MoveToPrev()
2519 : : {
2520 [ # # ]: 0 : long nNewRow = std::max(GetCurRow() - 1L, 0L);
2521 [ # # ]: 0 : if (GetCurRow() != nNewRow)
2522 : 0 : MoveToPosition(nNewRow);
2523 : 0 : }
2524 : :
2525 : : //------------------------------------------------------------------------------
2526 : 0 : void DbGridControl::MoveToNext()
2527 : : {
2528 [ # # ]: 0 : if (!m_pSeekCursor)
2529 : 0 : return;
2530 : :
2531 [ # # ]: 0 : if (m_nTotalCount > 0)
2532 : : {
2533 : : // move the data cursor to the right position
2534 [ # # ]: 0 : long nNewRow = std::min(GetRowCount() - 1, GetCurRow() + 1);
[ # # # # ]
2535 [ # # ]: 0 : if (GetCurRow() != nNewRow)
2536 : 0 : MoveToPosition(nNewRow);
2537 : : }
2538 : : else
2539 : : {
2540 : 0 : sal_Bool bOk = sal_False;
2541 : : try
2542 : : {
2543 : : // try to move to next row
2544 : : // when not possible our paint cursor is already on the last row
2545 : : // then we must be sure that the data cursor is on the position
2546 : : // we call ourself again
2547 [ # # ]: 0 : bOk = m_pSeekCursor->next();
2548 [ # # ]: 0 : if (bOk)
2549 : : {
2550 [ # # ]: 0 : m_nSeekPos = m_pSeekCursor->getRow() - 1;
2551 [ # # ]: 0 : MoveToPosition(GetCurRow() + 1);
2552 : : }
2553 : : }
2554 : 0 : catch(SQLException &)
2555 : : {
2556 : : DBG_UNHANDLED_EXCEPTION();
2557 : : }
2558 : :
2559 [ # # ]: 0 : if(!bOk)
2560 : : {
2561 : 0 : AdjustRows();
2562 [ # # ]: 0 : if (m_nTotalCount > 0) // only to avoid infinte recursion
2563 : 0 : MoveToNext();
2564 : : }
2565 : : }
2566 : : }
2567 : :
2568 : : //------------------------------------------------------------------------------
2569 : 0 : void DbGridControl::MoveToPosition(sal_uInt32 nPos)
2570 : : {
2571 [ # # ]: 0 : if (!m_pSeekCursor)
2572 : 0 : return;
2573 : :
2574 [ # # ][ # # ]: 0 : if (m_nTotalCount < 0 && (long)nPos >= GetRowCount())
[ # # ]
2575 : : {
2576 : : try
2577 : : {
2578 [ # # ][ # # ]: 0 : if (!m_pSeekCursor->absolute(nPos + 1))
2579 : : {
2580 [ # # ]: 0 : AdjustRows();
2581 : 0 : return;
2582 : : }
2583 : : else
2584 : : {
2585 [ # # ]: 0 : m_nSeekPos = m_pSeekCursor->getRow() - 1;
2586 [ # # ]: 0 : AdjustRows();
2587 : : }
2588 : : }
2589 : 0 : catch(Exception&)
2590 : : {
2591 : : return;
2592 : : }
2593 : : }
2594 : 0 : DbGridControl_Base::GoToRow(nPos);
2595 [ # # ]: 0 : m_aBar.InvalidateAll(m_nCurrentPos);
2596 : : }
2597 : :
2598 : : //------------------------------------------------------------------------------
2599 : 0 : void DbGridControl::AppendNew()
2600 : : {
2601 [ # # ][ # # ]: 0 : if (!m_pSeekCursor || !(m_nOptions & OPT_INSERT))
2602 : 0 : return;
2603 : :
2604 [ # # ]: 0 : if (m_nTotalCount < 0) // RecordCount steht noch nicht fest
2605 : : {
2606 : : try
2607 : : {
2608 [ # # ]: 0 : sal_Bool bRes = m_pSeekCursor->last();
2609 : :
2610 [ # # ]: 0 : if (bRes)
2611 : : {
2612 [ # # ]: 0 : m_nSeekPos = m_pSeekCursor->getRow() - 1;
2613 [ # # ]: 0 : AdjustRows();
2614 : : }
2615 : : }
2616 : 0 : catch(Exception&)
2617 : : {
2618 : : return;
2619 : : }
2620 : : }
2621 : :
2622 : 0 : long nNewRow = m_nTotalCount + 1;
2623 [ # # ][ # # ]: 0 : if (nNewRow > 0 && GetCurRow() != nNewRow)
[ # # ]
2624 [ # # ]: 0 : MoveToPosition(nNewRow - 1);
2625 : : }
2626 : :
2627 : : //------------------------------------------------------------------------------
2628 : 42 : void DbGridControl::SetDesignMode(sal_Bool bMode)
2629 : : {
2630 [ + - ]: 42 : if (IsDesignMode() != bMode)
2631 : : {
2632 : : // Enable/Disable f�r den Designmode anpassen damit die Headerbar konfigurierbar bleibt
2633 [ + + ]: 42 : if (bMode)
2634 : : {
2635 [ + + ]: 40 : if (!IsEnabled())
2636 : : {
2637 : 6 : Enable();
2638 : 6 : GetDataWindow().Disable();
2639 : : }
2640 : : }
2641 : : else
2642 : : {
2643 : : // komplett disablen
2644 [ - + ]: 2 : if (!GetDataWindow().IsEnabled())
2645 : 0 : Disable();
2646 : : }
2647 : :
2648 : 42 : m_bDesignMode = bMode;
2649 : 42 : GetDataWindow().SetMouseTransparent(bMode);
2650 : 42 : SetMouseTransparent(bMode);
2651 : :
2652 : 42 : m_aBar.InvalidateAll(m_nCurrentPos, sal_True);
2653 : : }
2654 : 42 : }
2655 : :
2656 : : //------------------------------------------------------------------------------
2657 : 0 : void DbGridControl::SetFilterMode(sal_Bool bMode)
2658 : : {
2659 [ # # ]: 0 : if (IsFilterMode() != bMode)
2660 : : {
2661 : 0 : m_bFilterMode = bMode;
2662 : :
2663 [ # # ]: 0 : if (bMode)
2664 : : {
2665 : 0 : SetUpdateMode(sal_False);
2666 : :
2667 : : // es gibt kein Cursor mehr
2668 [ # # ]: 0 : if (IsEditing())
2669 : 0 : DeactivateCell();
2670 : 0 : RemoveRows(sal_False);
2671 : :
2672 [ # # ]: 0 : m_xEmptyRow = new DbGridRow();
2673 : :
2674 : : // setting the new filter controls
2675 [ # # ]: 0 : for ( size_t i = 0; i < m_aColumns.size(); ++i )
2676 : : {
2677 : 0 : DbGridColumn* pCurCol = m_aColumns[ i ];
2678 [ # # ]: 0 : if (!pCurCol->IsHidden())
2679 : 0 : pCurCol->UpdateControl();
2680 : : }
2681 : :
2682 : : // one row for filtering
2683 : 0 : RowInserted(0, 1, sal_True);
2684 : 0 : SetUpdateMode(sal_True);
2685 : : }
2686 : : else
2687 [ # # ]: 0 : setDataSource(Reference< XRowSet > ());
2688 : : }
2689 : 0 : }
2690 : : // -----------------------------------------------------------------------------
2691 : 0 : String DbGridControl::GetCellText(long _nRow, sal_uInt16 _nColId) const
2692 : : {
2693 : 0 : size_t Location = GetModelColumnPos( _nColId );
2694 [ # # ]: 0 : DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
2695 : 0 : String sRet;
2696 [ # # ][ # # ]: 0 : if ( const_cast<DbGridControl*>(this)->SeekRow(_nRow) )
2697 [ # # ][ # # ]: 0 : sRet = GetCurrentRowCellText(pColumn, m_xPaintRow);
[ # # ]
2698 : 0 : return sRet;
2699 : : }
2700 : : //------------------------------------------------------------------------------
2701 : 0 : XubString DbGridControl::GetCurrentRowCellText(DbGridColumn* pColumn,const DbGridRowRef& _rRow) const
2702 : : {
2703 : : // Ausgabe des Textes fuer eine Zelle
2704 : 0 : XubString aText;
2705 [ # # ][ # # ]: 0 : if ( pColumn && IsValid(m_xPaintRow) )
[ # # ]
2706 [ # # ][ # # ]: 0 : aText = pColumn->GetCellText(_rRow, m_xFormatter);
[ # # ]
2707 : 0 : return aText;
2708 : : }
2709 : :
2710 : : //------------------------------------------------------------------------------
2711 : 0 : sal_uInt32 DbGridControl::GetTotalCellWidth(long nRow, sal_uInt16 nColId)
2712 : : {
2713 [ # # ]: 0 : if (SeekRow(nRow))
2714 : : {
2715 : 0 : size_t Location = GetModelColumnPos( nColId );
2716 [ # # ]: 0 : DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
2717 [ # # ]: 0 : return GetDataWindow().GetTextWidth(GetCurrentRowCellText(pColumn,m_xPaintRow));
2718 : : }
2719 : : else
2720 : 0 : return 30; //xxxx
2721 : : }
2722 : :
2723 : : //------------------------------------------------------------------------------
2724 : 0 : void DbGridControl::PreExecuteRowContextMenu(sal_uInt16 /*nRow*/, PopupMenu& rMenu)
2725 : : {
2726 [ # # ][ # # ]: 0 : sal_Bool bDelete = (m_nOptions & OPT_DELETE) && GetSelectRowCount() && !IsCurrentAppending();
[ # # ]
2727 : : // ist nur die Leerzeile selektiert, dann nicht loeschen
2728 [ # # ][ # # ]: 0 : bDelete = bDelete && !((m_nOptions & OPT_INSERT) && GetSelectRowCount() == 1 && IsRowSelected(GetRowCount() - 1));
[ # # ][ # # ]
2729 : :
2730 : 0 : rMenu.EnableItem(SID_FM_DELETEROWS, bDelete);
2731 : 0 : rMenu.EnableItem(SID_FM_RECORD_SAVE, IsModified());
2732 : :
2733 : : // the undo is more difficult
2734 : 0 : sal_Bool bCanUndo = IsModified();
2735 : 0 : long nState = -1;
2736 [ # # ]: 0 : if (m_aMasterStateProvider.IsSet())
2737 : 0 : nState = m_aMasterStateProvider.Call((void*)SID_FM_RECORD_UNDO);
2738 : 0 : bCanUndo &= ( 0 != nState );
2739 : :
2740 : 0 : rMenu.EnableItem(SID_FM_RECORD_UNDO, bCanUndo);
2741 : 0 : }
2742 : :
2743 : : //------------------------------------------------------------------------------
2744 : 0 : void DbGridControl::PostExecuteRowContextMenu(sal_uInt16 /*nRow*/, const PopupMenu& /*rMenu*/, sal_uInt16 nExecutionResult)
2745 : : {
2746 [ # # # # ]: 0 : switch (nExecutionResult)
2747 : : {
2748 : : case SID_FM_DELETEROWS:
2749 : : // delete asynchron
2750 [ # # ]: 0 : if (m_nDeleteEvent)
2751 : 0 : Application::RemoveUserEvent(m_nDeleteEvent);
2752 [ # # ]: 0 : m_nDeleteEvent = Application::PostUserEvent(LINK(this,DbGridControl,OnDelete));
2753 : 0 : break;
2754 : : case SID_FM_RECORD_UNDO:
2755 : 0 : Undo();
2756 : 0 : break;
2757 : : case SID_FM_RECORD_SAVE:
2758 : 0 : SaveRow();
2759 : 0 : break;
2760 : : default:
2761 : 0 : break;
2762 : : }
2763 : 0 : }
2764 : :
2765 : : //------------------------------------------------------------------------------
2766 : 0 : void DbGridControl::DataSourcePropertyChanged(const PropertyChangeEvent& evt) throw( RuntimeException )
2767 : : {
2768 : : TRACE_RANGE("DbGridControl::DataSourcePropertyChanged");
2769 [ # # ]: 0 : SolarMutexGuard aGuard;
2770 : : // prop "IsModified" changed ?
2771 : : // during update don't care about the modified state
2772 [ # # ][ # # ]: 0 : if (!IsUpdating() && evt.PropertyName.compareTo(FM_PROP_ISMODIFIED) == COMPARE_EQUAL)
[ # # ][ # # ]
[ # # # # ]
2773 : : {
2774 [ # # ]: 0 : Reference< XPropertySet > xSource(evt.Source, UNO_QUERY);
2775 : : DBG_ASSERT( xSource.is(), "DbGridControl::DataSourcePropertyChanged: invalid event source!" );
2776 : 0 : sal_Bool bIsNew = sal_False;
2777 [ # # ]: 0 : if (xSource.is())
2778 [ # # ][ # # ]: 0 : bIsNew = ::comphelper::getBOOL(xSource->getPropertyValue(FM_PROP_ISNEW));
[ # # ][ # # ]
2779 : :
2780 [ # # ][ # # ]: 0 : if (bIsNew && m_xCurrentRow.Is())
[ # # ]
2781 : : {
2782 : : 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 !");
2783 : 0 : sal_Int32 nRecordCount = 0;
2784 [ # # ][ # # ]: 0 : xSource->getPropertyValue(FM_PROP_ROWCOUNT) >>= nRecordCount;
[ # # ]
2785 [ # # ][ # # ]: 0 : if (::comphelper::getBOOL(evt.NewValue))
2786 : : { // modified state changed from sal_False to sal_True and we're on a insert row
2787 : : // -> we've to add a new grid row
2788 [ # # ][ # # ]: 0 : if ((nRecordCount == GetRowCount() - 1) && m_xCurrentRow->IsNew())
[ # # ][ # # ]
2789 : : {
2790 [ # # ][ # # ]: 0 : RowInserted(GetRowCount(), 1, sal_True);
2791 [ # # ]: 0 : InvalidateStatusCell(m_nCurrentPos);
2792 [ # # ]: 0 : m_aBar.InvalidateAll(m_nCurrentPos);
2793 : : }
2794 : : }
2795 : : else
2796 : : { // modified state changed from sal_True to sal_False and we're on a insert row
2797 : : // we have two "new row"s at the moment : the one we're editing currently (where the current
2798 : : // column is the only dirty element) and a "new new" row which is completely clean. As the first
2799 : : // one is about to be cleaned, too, the second one is obsolet now.
2800 [ # # ][ # # ]: 0 : if (m_xCurrentRow->IsNew() && nRecordCount == (GetRowCount() - 2))
[ # # ][ # # ]
2801 : : {
2802 [ # # ][ # # ]: 0 : RowRemoved(GetRowCount() - 1, 1, sal_True);
2803 [ # # ]: 0 : InvalidateStatusCell(m_nCurrentPos);
2804 [ # # ]: 0 : m_aBar.InvalidateAll(m_nCurrentPos);
2805 : : }
2806 : : }
2807 : : }
2808 [ # # ]: 0 : if (m_xCurrentRow.Is())
2809 : : {
2810 [ # # ][ # # ]: 0 : m_xCurrentRow->SetStatus(::comphelper::getBOOL(evt.NewValue) ? GRS_MODIFIED : GRS_CLEAN);
2811 : 0 : m_xCurrentRow->SetNew( bIsNew );
2812 [ # # ]: 0 : InvalidateStatusCell(m_nCurrentPos);
2813 : : TRACE_RANGE_MESSAGE1("modified flag changed, new state : %s", ROWSTATUS(m_xCurrentRow));
2814 : 0 : }
2815 [ # # ]: 0 : }
2816 : 0 : }
2817 : :
2818 : : //------------------------------------------------------------------------------
2819 : 0 : void DbGridControl::StartDrag( sal_Int8 /*nAction*/, const Point& rPosPixel )
2820 : : {
2821 [ # # ][ # # ]: 0 : if (!m_pSeekCursor || IsResizing())
[ # # ]
2822 : 0 : return;
2823 : :
2824 : 0 : sal_uInt16 nColId = GetColumnAtXPosPixel(rPosPixel.X());
2825 : 0 : long nRow = GetRowAtYPosPixel(rPosPixel.Y());
2826 [ # # ][ # # ]: 0 : if (nColId != HandleColumnId && nRow >= 0)
2827 : : {
2828 [ # # ][ # # ]: 0 : if (GetDataWindow().IsMouseCaptured())
2829 [ # # ]: 0 : GetDataWindow().ReleaseMouse();
2830 : :
2831 [ # # ]: 0 : size_t Location = GetModelColumnPos( nColId );
2832 [ # # ]: 0 : DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
2833 [ # # ][ # # ]: 0 : OStringTransferable* pTransferable = new OStringTransferable(GetCurrentRowCellText(pColumn,m_xPaintRow));
[ # # ][ # # ]
2834 [ # # ][ # # ]: 0 : Reference< XTransferable > xEnsureDelete(pTransferable);
2835 [ # # ]: 0 : pTransferable->StartDrag(this, DND_ACTION_COPY);
2836 : : }
2837 : : }
2838 : :
2839 : : //------------------------------------------------------------------------------
2840 : 13 : sal_Bool DbGridControl::canCopyCellText(sal_Int32 _nRow, sal_Int16 _nColId)
2841 : : {
2842 : : return (_nRow >= 0)
2843 : 13 : && (_nRow < GetRowCount())
2844 : : && (_nColId != HandleColumnId)
2845 [ + - + - ]: 26 : && (_nColId <= ColCount());
[ + - ][ + - ]
2846 : : }
2847 : :
2848 : : //------------------------------------------------------------------------------
2849 : 0 : void DbGridControl::copyCellText(sal_Int32 _nRow, sal_Int16 _nColId)
2850 : : {
2851 : : DBG_ASSERT(canCopyCellText(_nRow, _nColId), "DbGridControl::copyCellText: invalid call!");
2852 : 0 : DbGridColumn* pColumn = m_aColumns[ GetModelColumnPos(_nColId) ];
2853 : 0 : SeekRow(_nRow);
2854 [ # # ][ # # ]: 0 : OStringTransfer::CopyString( GetCurrentRowCellText( pColumn,m_xPaintRow ), this );
2855 : 0 : }
2856 : :
2857 : : //------------------------------------------------------------------------------
2858 : 0 : void DbGridControl::executeRowContextMenu( long _nRow, const Point& _rPreferredPos )
2859 : : {
2860 [ # # ][ # # ]: 0 : PopupMenu aContextMenu( SVX_RES( RID_SVXMNU_ROWS ) );
2861 : :
2862 [ # # ]: 0 : PreExecuteRowContextMenu( (sal_uInt16)_nRow, aContextMenu );
2863 [ # # ]: 0 : aContextMenu.RemoveDisabledEntries( sal_True, sal_True );
2864 [ # # ][ # # ]: 0 : PostExecuteRowContextMenu( (sal_uInt16)_nRow, aContextMenu, aContextMenu.Execute( this, _rPreferredPos ) );
[ # # ]
2865 : :
2866 : : // TODO: why this weird cast to sal_uInt16? What if we really have more than 65535 lines?
2867 : : // -> change this to sal_uInt32
2868 : 0 : }
2869 : :
2870 : : //------------------------------------------------------------------------------
2871 : 0 : void DbGridControl::Command(const CommandEvent& rEvt)
2872 : : {
2873 [ # # ]: 0 : switch (rEvt.GetCommand())
2874 : : {
2875 : : case COMMAND_CONTEXTMENU:
2876 : : {
2877 [ # # ]: 0 : if ( !m_pSeekCursor )
2878 : : {
2879 : 0 : DbGridControl_Base::Command(rEvt);
2880 : 0 : return;
2881 : : }
2882 : :
2883 [ # # ]: 0 : if ( !rEvt.IsMouseEvent() )
2884 : : { // context menu requested by keyboard
2885 [ # # ]: 0 : if ( GetSelectRowCount() )
2886 : : {
2887 [ # # ]: 0 : long nRow = FirstSelectedRow( );
2888 : :
2889 [ # # ]: 0 : ::Rectangle aRowRect( GetRowRectPixel( nRow, sal_True ) );
2890 [ # # ][ # # ]: 0 : executeRowContextMenu( nRow, aRowRect.LeftCenter() );
2891 : :
2892 : : // handled
2893 : : return;
2894 : : }
2895 : : }
2896 : :
2897 : 0 : sal_uInt16 nColId = GetColumnAtXPosPixel(rEvt.GetMousePosPixel().X());
2898 : 0 : long nRow = GetRowAtYPosPixel(rEvt.GetMousePosPixel().Y());
2899 : :
2900 [ # # ]: 0 : if (nColId == HandleColumnId)
2901 : : {
2902 : 0 : executeRowContextMenu( nRow, rEvt.GetMousePosPixel() );
2903 : : }
2904 [ # # ]: 0 : else if (canCopyCellText(nRow, nColId))
2905 : : {
2906 [ # # ][ # # ]: 0 : PopupMenu aContextMenu(SVX_RES(RID_SVXMNU_CELL));
2907 [ # # ]: 0 : aContextMenu.RemoveDisabledEntries(sal_True, sal_True);
2908 [ # # ][ # # ]: 0 : switch (aContextMenu.Execute(this, rEvt.GetMousePosPixel()))
2909 : : {
2910 : : case SID_COPY:
2911 [ # # ]: 0 : copyCellText(nRow, nColId);
2912 : 0 : break;
2913 [ # # ]: 0 : }
2914 : : }
2915 : : else
2916 : : {
2917 : 0 : DbGridControl_Base::Command(rEvt);
2918 : 0 : return;
2919 : : }
2920 : : }
2921 : : default:
2922 : 0 : DbGridControl_Base::Command(rEvt);
2923 : : }
2924 : : }
2925 : :
2926 : : //------------------------------------------------------------------------------
2927 : 0 : IMPL_LINK(DbGridControl, OnDelete, void*, /*EMPTYTAG*/ )
2928 : : {
2929 : : DBG_CHKTHIS(DbGridControl, NULL );
2930 : 0 : m_nDeleteEvent = 0;
2931 : 0 : DeleteSelectedRows();
2932 : 0 : return 0;
2933 : : }
2934 : :
2935 : : //------------------------------------------------------------------------------
2936 : 0 : void DbGridControl::DeleteSelectedRows()
2937 : : {
2938 : : DBG_ASSERT(GetSelection(), "keine selection!!!");
2939 : :
2940 [ # # ]: 0 : if (!m_pSeekCursor)
2941 : 0 : return;
2942 : : }
2943 : :
2944 : : //------------------------------------------------------------------------------
2945 : 0 : CellController* DbGridControl::GetController(long /*nRow*/, sal_uInt16 nColumnId)
2946 : : {
2947 [ # # ][ # # ]: 0 : if (!IsValid(m_xCurrentRow) || !IsEnabled())
[ # # ]
2948 : 0 : return NULL;
2949 : :
2950 : 0 : size_t Location = GetModelColumnPos(nColumnId);
2951 [ # # ]: 0 : DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
2952 [ # # ]: 0 : if (!pColumn)
2953 : 0 : return NULL;
2954 : :
2955 : 0 : CellController* pReturn = NULL;
2956 [ # # ]: 0 : if (IsFilterMode())
2957 : 0 : pReturn = &pColumn->GetController();
2958 : : else
2959 : : {
2960 [ # # ][ # # ]: 0 : if (::comphelper::hasProperty(FM_PROP_ENABLED, pColumn->getModel()))
2961 : : {
2962 [ # # ][ # # ]: 0 : if (!::comphelper::getBOOL(pColumn->getModel()->getPropertyValue(FM_PROP_ENABLED)))
[ # # ]
2963 : 0 : return NULL;
2964 : : }
2965 : :
2966 [ # # ][ # # ]: 0 : sal_Bool bInsert = (m_xCurrentRow->IsNew() && (m_nOptions & OPT_INSERT));
2967 [ # # ][ # # ]: 0 : sal_Bool bUpdate = (!m_xCurrentRow->IsNew() && (m_nOptions & OPT_UPDATE));
2968 : :
2969 [ # # ][ # # ]: 0 : if ((bInsert && !pColumn->IsAutoValue()) || bUpdate || m_bForceROController)
[ # # ][ # # ]
[ # # ]
2970 : : {
2971 : 0 : pReturn = &pColumn->GetController();
2972 [ # # ]: 0 : if (pReturn)
2973 : : {
2974 : : // wenn es eine Edit-Zeile ist, kann ich ihr das forced read-only mitgeben
2975 [ # # ][ # # ]: 0 : if (!pReturn->ISA(EditCellController) && !pReturn->ISA(SpinCellController))
[ # # ]
2976 : : // ich konnte den Controller in forceROController nicht auf ReadOnly setzen
2977 [ # # ][ # # ]: 0 : if (!bInsert && !bUpdate)
2978 : : // ich bin nur hier, da m_bForceROController gesetzt war
2979 : : // -> lieber kein Controller als einer ohne RO
2980 : 0 : pReturn = NULL;
2981 : : }
2982 : : }
2983 : : }
2984 : 0 : return pReturn;
2985 : : }
2986 : :
2987 : : //------------------------------------------------------------------------------
2988 : 0 : void DbGridControl::InitController(CellControllerRef& /*rController*/, long /*nRow*/, sal_uInt16 nColumnId)
2989 : : {
2990 : 0 : size_t Location = GetModelColumnPos(nColumnId);
2991 [ # # ]: 0 : DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
2992 [ # # ]: 0 : if (pColumn)
2993 : 0 : pColumn->UpdateFromField(m_xCurrentRow, m_xFormatter);
2994 : 0 : }
2995 : :
2996 : : //------------------------------------------------------------------------------
2997 : 0 : void DbGridControl::CellModified()
2998 : : {
2999 : : TRACE_RANGE("DbGridControl::CellModified");
3000 : :
3001 : : {
3002 [ # # ]: 0 : ::osl::MutexGuard aGuard(m_aAdjustSafety);
3003 [ # # ]: 0 : if (m_nAsynAdjustEvent)
3004 : : {
3005 : : TRACE_RANGE_MESSAGE1("forcing a synchron call to ", m_bPendingAdjustRows ? "AdjustRows" : "AdustDataSource");
3006 [ # # ]: 0 : RemoveUserEvent(m_nAsynAdjustEvent);
3007 : 0 : m_nAsynAdjustEvent = 0;
3008 : :
3009 : : // force the call : this should be no problem as we're probably running in the solar thread here
3010 : : // (cell modified is triggered by user actions)
3011 [ # # ]: 0 : if (m_bPendingAdjustRows)
3012 [ # # ]: 0 : AdjustRows();
3013 : : else
3014 [ # # ]: 0 : AdjustDataSource();
3015 [ # # ]: 0 : }
3016 : : }
3017 : :
3018 [ # # ][ # # ]: 0 : if (!IsFilterMode() && IsValid(m_xCurrentRow) && !m_xCurrentRow->IsModified())
[ # # ][ # # ]
3019 : : {
3020 : : // Einschalten des Editiermodus
3021 : : // Datensatz soll eingefuegt werden
3022 [ # # ]: 0 : if (m_xCurrentRow->IsNew())
3023 : : {
3024 : 0 : m_xCurrentRow->SetStatus(GRS_MODIFIED);
3025 : : TRACE_RANGE_MESSAGE("current row is new, new state : MODIFIED");
3026 : : // wenn noch keine Zeile hinzugefuegt wurde, dann neue hinzunehmen
3027 [ # # ]: 0 : if (m_nCurrentPos == GetRowCount() - 1)
3028 : : {
3029 : : // RowCount um einen erhoehen
3030 : 0 : RowInserted(GetRowCount(), 1, sal_True);
3031 : 0 : InvalidateStatusCell(m_nCurrentPos);
3032 : 0 : m_aBar.InvalidateAll(m_nCurrentPos);
3033 : : }
3034 : : }
3035 [ # # ]: 0 : else if (m_xCurrentRow->GetStatus() != GRS_MODIFIED)
3036 : : {
3037 : 0 : m_xCurrentRow->SetState(m_pDataCursor, sal_False);
3038 : : TRACE_RANGE_MESSAGE1("current row is not new, after SetState, new state : %s", ROWSTATUS(m_xCurrentRow));
3039 : 0 : m_xCurrentRow->SetStatus(GRS_MODIFIED);
3040 : : TRACE_RANGE_MESSAGE("current row is not new, new state : MODIFIED");
3041 : 0 : InvalidateStatusCell(m_nCurrentPos);
3042 : : }
3043 : : }
3044 : 0 : }
3045 : :
3046 : : //------------------------------------------------------------------------------
3047 : 0 : void DbGridControl::Dispatch(sal_uInt16 nId)
3048 : : {
3049 [ # # ]: 0 : if (nId == BROWSER_CURSORENDOFFILE)
3050 : : {
3051 [ # # ]: 0 : if (m_nOptions & OPT_INSERT)
3052 : 0 : AppendNew();
3053 : : else
3054 : 0 : MoveToLast();
3055 : : }
3056 : : else
3057 : 0 : DbGridControl_Base::Dispatch(nId);
3058 : 0 : }
3059 : :
3060 : : //------------------------------------------------------------------------------
3061 : 0 : void DbGridControl::Undo()
3062 : : {
3063 [ # # ][ # # ]: 0 : if (!IsFilterMode() && IsValid(m_xCurrentRow) && IsModified())
[ # # ][ # # ]
3064 : : {
3065 : : // check if we have somebody doin' the UNDO for us
3066 : 0 : long nState = -1;
3067 [ # # ]: 0 : if (m_aMasterStateProvider.IsSet())
3068 : 0 : nState = m_aMasterStateProvider.Call((void*)SID_FM_RECORD_UNDO);
3069 [ # # ]: 0 : if (nState>0)
3070 : : { // yes, we have, and the slot is enabled
3071 : : DBG_ASSERT(m_aMasterSlotExecutor.IsSet(), "DbGridControl::Undo : a state, but no execute link ?");
3072 : 0 : long lResult = m_aMasterSlotExecutor.Call((void*)SID_FM_RECORD_UNDO);
3073 [ # # ]: 0 : if (lResult)
3074 : : // handled
3075 : 0 : return;
3076 : : }
3077 [ # # ]: 0 : else if (nState == 0)
3078 : : // yes, we have, and the slot is disabled
3079 : 0 : return;
3080 : :
3081 : 0 : BeginCursorAction();
3082 : :
3083 : 0 : sal_Bool bAppending = m_xCurrentRow->IsNew();
3084 : 0 : sal_Bool bDirty = m_xCurrentRow->IsModified();
3085 : :
3086 : : try
3087 : : {
3088 : : // Editieren abbrechen
3089 [ # # ]: 0 : Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY);
3090 : : // no effects if we're not updating currently
3091 [ # # ]: 0 : if (bAppending)
3092 : : // just refresh the row
3093 [ # # ][ # # ]: 0 : xUpdateCursor->moveToInsertRow();
3094 : : else
3095 [ # # ][ # # ]: 0 : xUpdateCursor->cancelRowUpdates();
[ # # ]
3096 : :
3097 : : }
3098 : 0 : catch(Exception&)
3099 : : {
3100 : : DBG_UNHANDLED_EXCEPTION();
3101 : : }
3102 : :
3103 : 0 : EndCursorAction();
3104 : :
3105 : 0 : m_xDataRow->SetState(m_pDataCursor, sal_False);
3106 [ # # ]: 0 : if (&m_xPaintRow == &m_xCurrentRow)
3107 : 0 : m_xPaintRow = m_xCurrentRow = m_xDataRow;
3108 : : else
3109 : 0 : m_xCurrentRow = m_xDataRow;
3110 : :
3111 [ # # ][ # # ]: 0 : if (bAppending && (DbGridControl_Base::IsModified() || bDirty))
[ # # ][ # # ]
3112 : : // remove the row
3113 [ # # ]: 0 : if (m_nCurrentPos == GetRowCount() - 2)
3114 : : { // maybe we already removed it (in resetCurrentRow, called if the above moveToInsertRow
3115 : : // caused our data source form to be reset - which should be the usual case ....)
3116 : 0 : RowRemoved(GetRowCount() - 1, 1, sal_True);
3117 : 0 : m_aBar.InvalidateAll(m_nCurrentPos);
3118 : : }
3119 : :
3120 : 0 : RowModified(m_nCurrentPos);
3121 : : }
3122 : : }
3123 : :
3124 : : //------------------------------------------------------------------------------
3125 : 4 : void DbGridControl::resetCurrentRow()
3126 : : {
3127 [ - + ]: 4 : if (IsModified())
3128 : : {
3129 : : // scenario : we're on the insert row, the row is dirty, and thus there exists a "second" insert row (which
3130 : : // is clean). Normally in DataSourcePropertyChanged we would remove this second row if the modified state of
3131 : : // the insert row changes from sal_True to sal_False. But if our current cell is the only modified element (means the
3132 : : // data source isn't modified) and we're reset this DataSourcePropertyChanged would never be called, so we
3133 : : // would never delete the obsolet "second insert row". Thus in this special case this method here
3134 : : // is the only possibility to determine the redundance of the row (resetCurrentRow is called when the
3135 : : // "first insert row" is about to be cleaned, so of course the "second insert row" is redundant now)
3136 : 0 : Reference< XPropertySet > xDataSource = getDataSource()->getPropertySet();
3137 [ # # ][ # # ]: 0 : if (xDataSource.is() && !::comphelper::getBOOL(xDataSource->getPropertyValue(FM_PROP_ISMODIFIED)))
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # ]
[ # # ]
3138 : : {
3139 : : // are we on a new row currently ?
3140 [ # # ]: 0 : if (m_xCurrentRow->IsNew())
3141 : : {
3142 [ # # ][ # # ]: 0 : if (m_nCurrentPos == GetRowCount() - 2)
3143 : : {
3144 [ # # ][ # # ]: 0 : RowRemoved(GetRowCount() - 1, 1, sal_True);
3145 [ # # ]: 0 : m_aBar.InvalidateAll(m_nCurrentPos);
3146 : : }
3147 : : }
3148 : : }
3149 : :
3150 : : // update the rows
3151 [ # # ]: 0 : m_xDataRow->SetState(m_pDataCursor, sal_False);
3152 [ # # ]: 0 : if (&m_xPaintRow == &m_xCurrentRow)
3153 [ # # ][ # # ]: 0 : m_xPaintRow = m_xCurrentRow = m_xDataRow;
3154 : : else
3155 [ # # ]: 0 : m_xCurrentRow = m_xDataRow;
3156 : : }
3157 : :
3158 : 4 : RowModified(GetCurRow()); // will update the current controller if affected
3159 : 4 : }
3160 : :
3161 : : //------------------------------------------------------------------------------
3162 : 4 : void DbGridControl::RowModified( long nRow, sal_uInt16 /*nColId*/ )
3163 : : {
3164 [ + - ][ - + ]: 4 : if (nRow == m_nCurrentPos && IsEditing())
[ - + ]
3165 : : {
3166 [ # # ]: 0 : CellControllerRef aTmpRef = Controller();
3167 [ # # ]: 0 : aTmpRef->ClearModified();
3168 [ # # ][ # # ]: 0 : InitController(aTmpRef, m_nCurrentPos, GetCurColumnId());
3169 : : }
3170 : 4 : DbGridControl_Base::RowModified(nRow);
3171 : 4 : }
3172 : :
3173 : : //------------------------------------------------------------------------------
3174 : 10 : sal_Bool DbGridControl::IsModified() const
3175 : : {
3176 [ + - ][ + + ]: 10 : return !IsFilterMode() && IsValid(m_xCurrentRow) && (m_xCurrentRow->IsModified() || DbGridControl_Base::IsModified());
[ + - ][ - + ]
3177 : : }
3178 : :
3179 : : //------------------------------------------------------------------------------
3180 : 6 : sal_Bool DbGridControl::IsCurrentAppending() const
3181 : : {
3182 [ + - ][ - + ]: 6 : return m_xCurrentRow.Is() && m_xCurrentRow->IsNew();
3183 : : }
3184 : :
3185 : : //------------------------------------------------------------------------------
3186 : 50 : sal_Bool DbGridControl::IsInsertionRow(long nRow) const
3187 : : {
3188 [ + - ][ + - ]: 50 : return (m_nOptions & OPT_INSERT) && m_nTotalCount >= 0 && (nRow == GetRowCount() - 1);
[ - + ]
3189 : : }
3190 : :
3191 : : //------------------------------------------------------------------------------
3192 : 0 : sal_Bool DbGridControl::SaveModified()
3193 : : {
3194 : : TRACE_RANGE("DbGridControl::SaveModified");
3195 : : DBG_ASSERT(IsValid(m_xCurrentRow), "GridControl:: Invalid row");
3196 [ # # ]: 0 : if (!IsValid(m_xCurrentRow))
3197 : 0 : return sal_True;
3198 : :
3199 : : // Uebernimmt die Dateneingabe fuer das Feld
3200 : : // Hat es aenderungen im aktuellen Eingabefeld gegeben ?
3201 [ # # ]: 0 : if (!DbGridControl_Base::IsModified())
3202 : 0 : return sal_True;
3203 : :
3204 : 0 : size_t Location = GetModelColumnPos( GetCurColumnId() );
3205 [ # # ]: 0 : DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
3206 : 0 : sal_Bool bOK = pColumn->Commit();
3207 : : DBG_ASSERT( Controller().Is(), "DbGridControl::SaveModified: was modified, by have no controller?!" );
3208 [ # # ]: 0 : if ( !Controller().Is() )
3209 : : // this might happen if the callbacks implicitly triggered by Commit
3210 : : // fiddled with the form or the control ...
3211 : : // (Note that this here is a workaround, at most. We need a general concept how
3212 : : // to treat this, you can imagine an arbitrary number of scenarios where a callback
3213 : : // triggers something which leaves us in an expected state.)
3214 : : // #i67147# / 2006-07-17 / frank.schoenheit@sun.com
3215 : 0 : return bOK;
3216 : :
3217 [ # # ]: 0 : if (bOK)
3218 : : {
3219 [ # # ]: 0 : Controller()->ClearModified();
3220 : :
3221 [ # # ]: 0 : if ( IsValid(m_xCurrentRow) )
3222 : : {
3223 : 0 : m_xCurrentRow->SetState(m_pDataCursor, sal_False);
3224 : : TRACE_RANGE_MESSAGE1("explicit SetState, new state : %s", ROWSTATUS(m_xCurrentRow));
3225 : 0 : InvalidateStatusCell( m_nCurrentPos );
3226 : : }
3227 : : #ifdef DBG_UTIL
3228 : : else
3229 : : {
3230 : : TRACE_RANGE_MESSAGE1("no SetState, new state : %s", ROWSTATUS(m_xCurrentRow));
3231 : : }
3232 : : #endif
3233 : : }
3234 : : else
3235 : : {
3236 : : // reset the modified flag ....
3237 [ # # ]: 0 : Controller()->SetModified();
3238 : : }
3239 : :
3240 : 0 : return bOK;
3241 : : }
3242 : :
3243 : : //------------------------------------------------------------------------------
3244 : 0 : sal_Bool DbGridControl::SaveRow()
3245 : : {
3246 : : TRACE_RANGE("DbGridControl::SaveRow");
3247 : : // gueltige Zeile
3248 [ # # ][ # # ]: 0 : if (!IsValid(m_xCurrentRow) || !IsModified())
[ # # ]
3249 : 0 : return sal_True;
3250 : : // Wert des Controllers noch nicht gespeichert
3251 [ # # ][ # # ]: 0 : else if (Controller().Is() && Controller()->IsModified())
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # # #
# # ]
3252 : : {
3253 [ # # ]: 0 : if (!SaveModified())
3254 : 0 : return sal_False;
3255 : : }
3256 : 0 : m_bUpdating = sal_True;
3257 : :
3258 : 0 : BeginCursorAction();
3259 : 0 : sal_Bool bAppending = m_xCurrentRow->IsNew();
3260 : 0 : sal_Bool bSuccess = sal_False;
3261 : : try
3262 : : {
3263 [ # # ]: 0 : Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY);
3264 [ # # ]: 0 : if (bAppending)
3265 [ # # ][ # # ]: 0 : xUpdateCursor->insertRow();
3266 : : else
3267 [ # # ][ # # ]: 0 : xUpdateCursor->updateRow();
3268 : 0 : bSuccess = sal_True;
3269 : : }
3270 [ # # ]: 0 : catch(SQLException&)
3271 : : {
3272 [ # # ]: 0 : EndCursorAction();
3273 : 0 : m_bUpdating = sal_False;
3274 : 0 : return sal_False;
3275 : : }
3276 : :
3277 : : try
3278 : : {
3279 [ # # ]: 0 : if (bSuccess)
3280 : : {
3281 : : // if we are appending we still sit on the insert row
3282 : : // we don't move just clear the flags not to move on the current row
3283 [ # # ]: 0 : m_xCurrentRow->SetState(m_pDataCursor, sal_False);
3284 : : TRACE_RANGE_MESSAGE1("explicit SetState after a successfull update, new state : %s", ROWSTATUS(m_xCurrentRow));
3285 : 0 : m_xCurrentRow->SetNew(sal_False);
3286 : :
3287 : : // adjust the seekcursor if it is on the same position as the datacursor
3288 [ # # ][ # # ]: 0 : if (m_nSeekPos == m_nCurrentPos || bAppending)
3289 : : {
3290 : : // get the bookmark to refetch the data
3291 : : // in insert mode we take the new bookmark of the data cursor
3292 [ # # ][ # # ]: 0 : Any aBookmark = bAppending ? m_pDataCursor->getBookmark() : m_pSeekCursor->getBookmark();
[ # # ]
3293 [ # # ]: 0 : m_pSeekCursor->moveToBookmark(aBookmark);
3294 : : // get the data
3295 [ # # ]: 0 : m_xSeekRow->SetState(m_pSeekCursor, sal_True);
3296 [ # # ][ # # ]: 0 : m_nSeekPos = m_pSeekCursor->getRow() - 1;
3297 : : }
3298 : : }
3299 : : // and repaint the row
3300 [ # # ]: 0 : RowModified(m_nCurrentPos);
3301 : : }
3302 : 0 : catch(Exception&)
3303 : : {
3304 : : }
3305 : :
3306 : 0 : m_bUpdating = sal_False;
3307 : 0 : EndCursorAction();
3308 : :
3309 : : // The old code returned (nRecords != 0) here.
3310 : : // Me thinks this is wrong : If something goes wrong while update the record, an exception will be thrown,
3311 : : // which results in a "return sal_False" (see above). If no exception is thrown, everything is fine. If nRecords
3312 : : // is zero, this simply means all fields had their original values.
3313 : : // FS - 06.12.99 - 70502
3314 : 0 : return sal_True;
3315 : : }
3316 : :
3317 : : //------------------------------------------------------------------------------
3318 : 0 : long DbGridControl::PreNotify(NotifyEvent& rEvt)
3319 : : {
3320 : : // keine Events der Navbar behandeln
3321 [ # # ]: 0 : if (m_aBar.IsWindowOrChild(rEvt.GetWindow()))
3322 : 0 : return BrowseBox::PreNotify(rEvt);
3323 : :
3324 [ # # ]: 0 : switch (rEvt.GetType())
3325 : : {
3326 : : case EVENT_KEYINPUT:
3327 : : {
3328 : 0 : const KeyEvent* pKeyEvent = rEvt.GetKeyEvent();
3329 : :
3330 : 0 : sal_uInt16 nCode = pKeyEvent->GetKeyCode().GetCode();
3331 : 0 : sal_Bool bShift = pKeyEvent->GetKeyCode().IsShift();
3332 : 0 : sal_Bool bCtrl = pKeyEvent->GetKeyCode().IsMod1();
3333 : 0 : sal_Bool bAlt = pKeyEvent->GetKeyCode().IsMod2();
3334 [ # # ][ # # ]: 0 : if ( ( KEY_TAB == nCode ) && bCtrl && !bAlt )
[ # # ]
3335 : : {
3336 : : // Ctrl-Tab is used to step out of the control, without traveling to the
3337 : : // remaining cells first
3338 : : // -> build a new key event without the Ctrl-key, and let the very base class handle it
3339 [ # # ]: 0 : KeyCode aNewCode( KEY_TAB, bShift, sal_False, sal_False, sal_False );
3340 [ # # ]: 0 : KeyEvent aNewEvent( pKeyEvent->GetCharCode(), aNewCode );
3341 : :
3342 : : // call the Control - our direct base class will interpret this in a way we do not want (and do
3343 : : // a cell traveling)
3344 [ # # ]: 0 : Control::KeyInput( aNewEvent );
3345 : 0 : return 1;
3346 : : }
3347 : :
3348 [ # # ][ # # ]: 0 : if ( !bShift && !bCtrl && ( KEY_ESCAPE == nCode ) )
[ # # ]
3349 : : {
3350 [ # # ]: 0 : if (IsModified())
3351 : : {
3352 : 0 : Undo();
3353 : 0 : return 1;
3354 : : }
3355 : : }
3356 [ # # ][ # # ]: 0 : else if ( ( KEY_DELETE == nCode ) && !bShift && !bCtrl ) // delete rows
[ # # ]
3357 : : {
3358 [ # # ][ # # ]: 0 : if ((m_nOptions & OPT_DELETE) && GetSelectRowCount())
[ # # ]
3359 : : {
3360 : : // delete asynchron
3361 [ # # ]: 0 : if (m_nDeleteEvent)
3362 : 0 : Application::RemoveUserEvent(m_nDeleteEvent);
3363 [ # # ]: 0 : m_nDeleteEvent = Application::PostUserEvent(LINK(this,DbGridControl,OnDelete));
3364 : 0 : return 1;
3365 : : }
3366 : : }
3367 : : } // kein break!
3368 : : default:
3369 : 0 : return DbGridControl_Base::PreNotify(rEvt);
3370 : : }
3371 : : }
3372 : :
3373 : : //------------------------------------------------------------------------------
3374 : 0 : sal_Bool DbGridControl::IsTabAllowed(sal_Bool bRight) const
3375 : : {
3376 [ # # ]: 0 : if (bRight)
3377 : : // Tab nur wenn nicht auf der letzten Zelle
3378 : 0 : return GetCurRow() < (GetRowCount() - 1) || !m_bRecordCountFinal ||
3379 [ # # ][ # # ]: 0 : GetViewColumnPos(GetCurColumnId()) < (GetViewColCount() - 1);
[ # # ]
3380 : : else
3381 : : {
3382 : : // Tab nur wenn nicht auf der ersten Zelle
3383 [ # # ][ # # ]: 0 : return GetCurRow() > 0 || (GetCurColumnId() && GetViewColumnPos(GetCurColumnId()) > 0);
[ # # ]
3384 : : }
3385 : : }
3386 : :
3387 : : //------------------------------------------------------------------------------
3388 : 0 : void DbGridControl::KeyInput( const KeyEvent& rEvt )
3389 : : {
3390 [ # # ]: 0 : if (rEvt.GetKeyCode().GetFunction() == KEYFUNC_COPY)
3391 : : {
3392 : 0 : long nRow = GetCurRow();
3393 : 0 : sal_uInt16 nColId = GetCurColumnId();
3394 [ # # ][ # # ]: 0 : if (nRow >= 0 && nRow < GetRowCount() && nColId < ColCount())
[ # # ][ # # ]
3395 : : {
3396 : 0 : size_t Location = GetModelColumnPos( nColId );
3397 [ # # ]: 0 : DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
3398 [ # # ][ # # ]: 0 : OStringTransfer::CopyString( GetCurrentRowCellText( pColumn,m_xPaintRow ), this );
3399 : 0 : return;
3400 : : }
3401 : : }
3402 : 0 : DbGridControl_Base::KeyInput(rEvt);
3403 : : }
3404 : :
3405 : : //------------------------------------------------------------------------------
3406 : 0 : void DbGridControl::HideColumn(sal_uInt16 nId)
3407 : : {
3408 : 0 : DeactivateCell();
3409 : :
3410 : : // determine the col for the focus to set to after removal
3411 : 0 : sal_uInt16 nPos = GetViewColumnPos(nId);
3412 : 0 : sal_uInt16 nNewColId = nPos == (ColCount()-1)
3413 : 0 : ? GetColumnIdFromViewPos(nPos-1) // last col is to be removed -> take the previous
3414 [ # # ]: 0 : : GetColumnIdFromViewPos(nPos+1); // take the next
3415 : :
3416 : 0 : long lCurrentWidth = GetColumnWidth(nId);
3417 : 0 : DbGridControl_Base::RemoveColumn(nId);
3418 : : // don't use my own RemoveColumn, this would remove it from m_aColumns, too
3419 : :
3420 : : // update my model
3421 : 0 : size_t Location = GetModelColumnPos( nId );
3422 [ # # ]: 0 : DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
3423 : : DBG_ASSERT(pColumn, "DbGridControl::HideColumn : somebody did hide a nonexistent column !");
3424 [ # # ]: 0 : if (pColumn)
3425 : : {
3426 : 0 : pColumn->m_bHidden = sal_True;
3427 : 0 : pColumn->m_nLastVisibleWidth = CalcReverseZoom(lCurrentWidth);
3428 : : }
3429 : :
3430 : : // and reset the focus
3431 [ # # ]: 0 : if ( nId == GetCurColumnId() )
3432 : 0 : GoToColumnId( nNewColId );
3433 : 0 : }
3434 : :
3435 : : //------------------------------------------------------------------------------
3436 : 0 : void DbGridControl::ShowColumn(sal_uInt16 nId)
3437 : : {
3438 [ # # ]: 0 : sal_uInt16 nPos = GetModelColumnPos(nId);
3439 : : DBG_ASSERT(nPos != GRID_COLUMN_NOT_FOUND, "DbGridControl::ShowColumn : invalid argument !");
3440 [ # # ]: 0 : if (nPos == GRID_COLUMN_NOT_FOUND)
3441 : : return;
3442 : :
3443 : 0 : DbGridColumn* pColumn = m_aColumns[ nPos ];
3444 [ # # ]: 0 : if (!pColumn->IsHidden())
3445 : : {
3446 : : DBG_ASSERT(GetViewColumnPos(nId) != GRID_COLUMN_NOT_FOUND, "DbGridControl::ShowColumn : inconsistent internal state !");
3447 : : // if the column isn't marked as hidden, it should be visible, shouldn't it ?
3448 : : return;
3449 : : }
3450 : : DBG_ASSERT(GetViewColumnPos(nId) == GRID_COLUMN_NOT_FOUND, "DbGridControl::ShowColumn : inconsistent internal state !");
3451 : : // the opposite situation ...
3452 : :
3453 : : // to determine the new view position we need an adjacent non-hidden column
3454 : 0 : sal_uInt16 nNextNonHidden = BROWSER_INVALIDID;
3455 : : // first search the cols to the right
3456 [ # # ]: 0 : for ( size_t i = nPos + 1; i < m_aColumns.size(); ++i )
3457 : : {
3458 : 0 : DbGridColumn* pCurCol = m_aColumns[ i ];
3459 [ # # ]: 0 : if (!pCurCol->IsHidden())
3460 : : {
3461 : 0 : nNextNonHidden = i;
3462 : 0 : break;
3463 : : }
3464 : : }
3465 [ # # ][ # # ]: 0 : if ((nNextNonHidden == BROWSER_INVALIDID) && (nPos > 0))
3466 : : {
3467 : : // then to the left
3468 [ # # ]: 0 : for ( size_t i = nPos; i > 0; --i )
3469 : : {
3470 : 0 : DbGridColumn* pCurCol = m_aColumns[ i-1 ];
3471 [ # # ]: 0 : if (!pCurCol->IsHidden())
3472 : : {
3473 : 0 : nNextNonHidden = i-1;
3474 : 0 : break;
3475 : : }
3476 : : }
3477 : : }
3478 : : sal_uInt16 nNewViewPos = (nNextNonHidden == BROWSER_INVALIDID)
3479 : : ? 1 // there is no visible column -> insert behinde the handle col
3480 [ # # ][ # # ]: 0 : : GetViewColumnPos( m_aColumns[ nNextNonHidden ]->GetId() ) + 1;
3481 : : // the first non-handle col has "view pos" 0, but the pos arg for InsertDataColumn expects
3482 : : // a position 1 for the first non-handle col -> +1
3483 : : DBG_ASSERT(nNewViewPos != GRID_COLUMN_NOT_FOUND, "DbGridControl::ShowColumn : inconsistent internal state !");
3484 : : // we found a col marked as visible but got no view pos for it ...
3485 : :
3486 [ # # ][ # # ]: 0 : if ((nNextNonHidden<nPos) && (nNextNonHidden != BROWSER_INVALIDID))
3487 : : // nNextNonHidden is a column to the left, so we want to insert the new col _right_ beside it's pos
3488 : 0 : ++nNewViewPos;
3489 : :
3490 [ # # ]: 0 : DeactivateCell();
3491 : :
3492 : 0 : ::rtl::OUString aName;
3493 [ # # ][ # # ]: 0 : pColumn->getModel()->getPropertyValue(FM_PROP_LABEL) >>= aName;
[ # # ]
3494 [ # # ][ # # ]: 0 : InsertDataColumn(nId, aName, CalcZoom(pColumn->m_nLastVisibleWidth), HIB_CENTER | HIB_VCENTER | HIB_CLICKABLE, nNewViewPos);
[ # # ][ # # ]
3495 : 0 : pColumn->m_bHidden = sal_False;
3496 : :
3497 [ # # ]: 0 : ActivateCell();
3498 [ # # ]: 0 : Invalidate();
3499 : : }
3500 : :
3501 : : //------------------------------------------------------------------------------
3502 : 20 : sal_uInt16 DbGridControl::GetColumnIdFromModelPos( sal_uInt16 nPos ) const
3503 : : {
3504 [ - + ]: 20 : if (nPos >= m_aColumns.size())
3505 : : {
3506 : : OSL_FAIL("DbGridControl::GetColumnIdFromModelPos : invalid argument !");
3507 : 0 : return GRID_COLUMN_NOT_FOUND;
3508 : : }
3509 : :
3510 : 20 : DbGridColumn* pCol = m_aColumns[ nPos ];
3511 : : #if (OSL_DEBUG_LEVEL > 0) || defined DBG_UTIL
3512 : : // in der Debug-Version rechnen wir die ModelPos in eine ViewPos um und vergleichen das mit dem Wert,
3513 : : // den wir zurueckliefern werden (nId an der entsprechenden Col in m_aColumns)
3514 : :
3515 : : if (!pCol->IsHidden())
3516 : : { // macht nur Sinn, wenn die Spalte sichtbar ist
3517 : : sal_uInt16 nViewPos = nPos;
3518 : : for ( size_t i = 0; i < m_aColumns.size() && i < nPos; ++i)
3519 : : if ( m_aColumns[ i ]->IsHidden())
3520 : : --nViewPos;
3521 : :
3522 : : DBG_ASSERT(pCol && GetColumnIdFromViewPos(nViewPos) == pCol->GetId(),
3523 : : "DbGridControl::GetColumnIdFromModelPos : this isn't consistent .... did I misunderstand something ?");
3524 : : }
3525 : : #endif
3526 : 20 : return pCol->GetId();
3527 : : }
3528 : :
3529 : : //------------------------------------------------------------------------------
3530 : 1307 : sal_uInt16 DbGridControl::GetModelColumnPos( sal_uInt16 nId ) const
3531 : : {
3532 [ + + ]: 11701 : for ( size_t i = 0; i < m_aColumns.size(); ++i )
3533 [ + + ]: 11539 : if ( m_aColumns[ i ]->GetId() == nId )
3534 : 1145 : return i;
3535 : :
3536 : 1307 : return GRID_COLUMN_NOT_FOUND;
3537 : : }
3538 : :
3539 : : //------------------------------------------------------------------------------
3540 : 0 : void DbGridControl::implAdjustInSolarThread(sal_Bool _bRows)
3541 : : {
3542 : : TRACE_RANGE("DbGridControl::implAdjustInSolarThread");
3543 [ # # ]: 0 : ::osl::MutexGuard aGuard(m_aAdjustSafety);
3544 [ # # ][ # # ]: 0 : if (::osl::Thread::getCurrentIdentifier() != Application::GetMainThreadIdentifier())
[ # # ]
3545 : : {
3546 [ # # ][ # # ]: 0 : m_nAsynAdjustEvent = PostUserEvent(LINK(this, DbGridControl, OnAsyncAdjust), reinterpret_cast< void* >( _bRows ));
3547 : 0 : m_bPendingAdjustRows = _bRows;
3548 : : #ifdef DBG_UTIL
3549 : : if (_bRows)
3550 : : TRACE_RANGE_MESSAGE("posting an AdjustRows")
3551 : : else
3552 : : TRACE_RANGE_MESSAGE("posting an AdjustDataSource")
3553 : : #endif
3554 : : }
3555 : : else
3556 : : {
3557 : : #ifdef DBG_UTIL
3558 : : if (_bRows)
3559 : : TRACE_RANGE_MESSAGE("doing an AdjustRows")
3560 : : else
3561 : : TRACE_RANGE_MESSAGE("doing an AdjustDataSource")
3562 : : #endif
3563 : : // always adjust the rows before adjusting the data source
3564 : : // If this is not necessary (because the row count did not change), nothing is done
3565 : : // The problem is that we can't rely on the order of which the calls come in: If the cursor was moved
3566 : : // to a position behind row count know 'til now, the cursorMoved notification may come before the
3567 : : // RowCountChanged notification
3568 : : // 94093 - 02.11.2001 - frank.schoenheit@sun.com
3569 [ # # ]: 0 : AdjustRows();
3570 : :
3571 [ # # ]: 0 : if ( !_bRows )
3572 [ # # ]: 0 : AdjustDataSource();
3573 [ # # ]: 0 : }
3574 : 0 : }
3575 : :
3576 : : //------------------------------------------------------------------------------
3577 : 0 : IMPL_LINK(DbGridControl, OnAsyncAdjust, void*, pAdjustWhat)
3578 : : {
3579 : 0 : m_nAsynAdjustEvent = 0;
3580 : :
3581 : 0 : AdjustRows();
3582 : : // see implAdjustInSolarThread for a comment why we do this every time
3583 : :
3584 [ # # ]: 0 : if ( !pAdjustWhat )
3585 : 0 : AdjustDataSource();
3586 : :
3587 : 0 : return 0L;
3588 : : }
3589 : :
3590 : : //------------------------------------------------------------------------------
3591 : 2 : void DbGridControl::BeginCursorAction()
3592 : : {
3593 [ + - ]: 2 : if (m_pFieldListeners)
3594 : : {
3595 : 2 : ColumnFieldValueListeners* pListeners = (ColumnFieldValueListeners*)m_pFieldListeners;
3596 : 2 : ConstColumnFieldValueListenersIterator aIter = pListeners->begin();
3597 [ + + ]: 64 : while (aIter != pListeners->end())
3598 : : {
3599 : 62 : GridFieldValueListener* pCurrent = (*aIter).second;
3600 [ + - ]: 62 : if (pCurrent)
3601 : 62 : pCurrent->suspend();
3602 : 62 : ++aIter;
3603 : : }
3604 : : }
3605 : :
3606 [ + - ]: 2 : if (m_pDataSourcePropListener)
3607 : 2 : m_pDataSourcePropListener->suspend();
3608 : 2 : }
3609 : :
3610 : : //------------------------------------------------------------------------------
3611 : 2 : void DbGridControl::EndCursorAction()
3612 : : {
3613 [ + - ]: 2 : if (m_pFieldListeners)
3614 : : {
3615 : 2 : ColumnFieldValueListeners* pListeners = (ColumnFieldValueListeners*)m_pFieldListeners;
3616 : 2 : ConstColumnFieldValueListenersIterator aIter = pListeners->begin();
3617 [ + + ]: 64 : while (aIter != pListeners->end())
3618 : : {
3619 : 62 : GridFieldValueListener* pCurrent = (*aIter).second;
3620 [ + - ]: 62 : if (pCurrent)
3621 : 62 : pCurrent->resume();
3622 : 62 : ++aIter;
3623 : : }
3624 : : }
3625 : :
3626 [ + - ]: 2 : if (m_pDataSourcePropListener)
3627 : 2 : m_pDataSourcePropListener->resume();
3628 : 2 : }
3629 : :
3630 : : //------------------------------------------------------------------------------
3631 : 2 : void DbGridControl::ConnectToFields()
3632 : : {
3633 : 2 : ColumnFieldValueListeners* pListeners = (ColumnFieldValueListeners*)m_pFieldListeners;
3634 : : DBG_ASSERT(!pListeners || pListeners->empty(), "DbGridControl::ConnectToFields : please call DisconnectFromFields first !");
3635 : :
3636 [ + - ]: 2 : if (!pListeners)
3637 : : {
3638 [ + - ]: 2 : pListeners = new ColumnFieldValueListeners;
3639 : 2 : m_pFieldListeners = pListeners;
3640 : : }
3641 : :
3642 [ + + ]: 64 : for ( size_t i = 0; i < m_aColumns.size(); ++i )
3643 : : {
3644 : 62 : DbGridColumn* pCurrent = m_aColumns[ i ];
3645 [ + - ][ + - ]: 62 : sal_uInt16 nViewPos = pCurrent ? GetViewColumnPos(pCurrent->GetId()) : GRID_COLUMN_NOT_FOUND;
3646 [ - + ]: 62 : if (GRID_COLUMN_NOT_FOUND == nViewPos)
3647 : 0 : continue;
3648 : :
3649 : 62 : Reference< XPropertySet > xField = pCurrent->GetField();
3650 [ - + ]: 62 : if (!xField.is())
3651 : 0 : continue;
3652 : :
3653 : : // column is visible and bound here
3654 [ + - ]: 62 : GridFieldValueListener*& rpListener = (*pListeners)[pCurrent->GetId()];
3655 : : DBG_ASSERT(!rpListener, "DbGridControl::ConnectToFields : already a listener for this column ?!");
3656 [ + - ][ + - ]: 124 : rpListener = new GridFieldValueListener(*this, xField, pCurrent->GetId());
[ + - ]
3657 : 62 : }
3658 : 2 : }
3659 : :
3660 : : //------------------------------------------------------------------------------
3661 : 4 : void DbGridControl::DisconnectFromFields()
3662 : : {
3663 [ + + ]: 4 : if (!m_pFieldListeners)
3664 : 4 : return;
3665 : :
3666 : 2 : ColumnFieldValueListeners* pListeners = (ColumnFieldValueListeners*)m_pFieldListeners;
3667 [ + + ]: 64 : while (pListeners->size())
3668 : : {
3669 : : #ifdef DBG_UTIL
3670 : : sal_Int32 nOldSize = pListeners->size();
3671 : : #endif
3672 [ + - ]: 62 : pListeners->begin()->second->dispose();
3673 : : DBG_ASSERT(nOldSize > (sal_Int32)pListeners->size(), "DbGridControl::DisconnectFromFields : dispose on a listener should result in a removal from my list !");
3674 : : }
3675 : :
3676 [ + - ]: 2 : delete pListeners;
3677 : 2 : m_pFieldListeners = NULL;
3678 : : }
3679 : :
3680 : : //------------------------------------------------------------------------------
3681 : 0 : void DbGridControl::FieldValueChanged(sal_uInt16 _nId, const PropertyChangeEvent& /*_evt*/)
3682 : : {
3683 [ # # ]: 0 : osl::MutexGuard aPreventDestruction(m_aDestructionSafety);
3684 : : // needed as this may run in a thread other than the main one
3685 [ # # ][ # # ]: 0 : if (GetRowStatus(GetCurRow()) != DbGridControl_Base::MODIFIED)
3686 : : // all other cases are handled elsewhere
3687 : : return;
3688 : :
3689 [ # # ]: 0 : size_t Location = GetModelColumnPos( _nId );
3690 [ # # ]: 0 : DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
3691 [ # # ]: 0 : if (pColumn)
3692 : : {
3693 : 0 : sal_Bool bAcquiredPaintSafety = sal_False;
3694 [ # # ][ # # ]: 0 : while (!m_bWantDestruction && !bAcquiredPaintSafety)
[ # # ]
3695 [ # # ][ # # ]: 0 : bAcquiredPaintSafety = Application::GetSolarMutex().tryToAcquire();
3696 : :
3697 [ # # ]: 0 : if (m_bWantDestruction)
3698 : : { // at this moment, within another thread, our destructor tries to destroy the listener which called this method
3699 : : // => don't do anything
3700 : : // 73365 - 23.02.00 - FS
3701 [ # # ]: 0 : if (bAcquiredPaintSafety)
3702 : : // though the above while-loop suggests that (m_bWantDestruction && bAcquiredPaintSafety) is impossible,
3703 : : // it isnt't, as m_bWantDestruction isn't protected with any mutex
3704 [ # # ][ # # ]: 0 : Application::GetSolarMutex().release();
3705 : : return;
3706 : : }
3707 : : // here we got the solar mutex, transfer it to a guard for safety reasons
3708 [ # # ]: 0 : SolarMutexGuard aPaintSafety;
3709 [ # # ][ # # ]: 0 : Application::GetSolarMutex().release();
3710 : :
3711 : : // and finally do the update ...
3712 [ # # ]: 0 : pColumn->UpdateFromField(m_xCurrentRow, m_xFormatter);
3713 [ # # ][ # # ]: 0 : RowModified(GetCurRow(), _nId);
3714 [ # # ][ # # ]: 0 : }
3715 : : }
3716 : :
3717 : : //------------------------------------------------------------------------------
3718 : 62 : void DbGridControl::FieldListenerDisposing(sal_uInt16 _nId)
3719 : : {
3720 : 62 : ColumnFieldValueListeners* pListeners = (ColumnFieldValueListeners*)m_pFieldListeners;
3721 [ + - ]: 62 : if (!pListeners)
3722 : : {
3723 : : OSL_FAIL("DbGridControl::FieldListenerDisposing : invalid call (have no listener array) !");
3724 : : return;
3725 : : }
3726 : :
3727 [ + - ]: 62 : ColumnFieldValueListenersIterator aPos = pListeners->find(_nId);
3728 [ + - ]: 62 : if (aPos == pListeners->end())
3729 : : {
3730 : : OSL_FAIL("DbGridControl::FieldListenerDisposing : invalid call (did not find the listener) !");
3731 : : return;
3732 : : }
3733 : :
3734 [ + - ][ + - ]: 62 : delete aPos->second;
3735 : :
3736 [ + - ]: 62 : pListeners->erase(aPos);
3737 : : }
3738 : :
3739 : : //------------------------------------------------------------------------------
3740 : 2 : void DbGridControl::disposing(sal_uInt16 _nId, const EventObject& /*_rEvt*/)
3741 : : {
3742 [ + - ]: 2 : if (_nId == 0)
3743 : : { // the seek cursor is beeing disposed
3744 [ + - ]: 2 : ::osl::MutexGuard aGuard(m_aAdjustSafety);
3745 [ + - ][ + - ]: 2 : setDataSource(NULL,0); // our clone was disposed so we set our datasource to null to avoid later acces to it
3746 [ - + ]: 2 : if (m_nAsynAdjustEvent)
3747 : : {
3748 [ # # ]: 0 : RemoveUserEvent(m_nAsynAdjustEvent);
3749 : 0 : m_nAsynAdjustEvent = 0;
3750 [ + - ]: 2 : }
3751 : : }
3752 : 2 : }
3753 : : // -----------------------------------------------------------------------------
3754 : 0 : sal_Int32 DbGridControl::GetAccessibleControlCount() const
3755 : : {
3756 : 0 : return DbGridControl_Base::GetAccessibleControlCount() + 1; // the navigation control
3757 : : }
3758 : : // -----------------------------------------------------------------------------
3759 : 0 : Reference<XAccessible > DbGridControl::CreateAccessibleControl( sal_Int32 _nIndex )
3760 : : {
3761 : 0 : Reference<XAccessible > xRet;
3762 [ # # ][ # # ]: 0 : if ( _nIndex == DbGridControl_Base::GetAccessibleControlCount() )
3763 : : {
3764 [ # # ][ # # ]: 0 : xRet = m_aBar.GetAccessible();
3765 : : }
3766 : : else
3767 [ # # ][ # # ]: 0 : xRet = DbGridControl_Base::CreateAccessibleControl( _nIndex );
3768 : 0 : return xRet;
3769 : : }
3770 : : // -----------------------------------------------------------------------------
3771 : 0 : Reference< XAccessible > DbGridControl::CreateAccessibleCell( sal_Int32 _nRow, sal_uInt16 _nColumnPos )
3772 : : {
3773 : 0 : sal_uInt16 nColumnId = GetColumnId( _nColumnPos );
3774 : 0 : size_t Location = GetModelColumnPos(nColumnId);
3775 [ # # ]: 0 : DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
3776 [ # # ]: 0 : if ( pColumn )
3777 : : {
3778 [ # # ][ # # ]: 0 : Reference< ::com::sun::star::awt::XControl> xInt(pColumn->GetCell());
3779 [ # # ]: 0 : Reference< ::com::sun::star::awt::XCheckBox> xBox(xInt,UNO_QUERY);
3780 [ # # ]: 0 : if ( xBox.is() )
3781 : : {
3782 : 0 : TriState eValue = STATE_NOCHECK;
3783 [ # # ][ # # ]: 0 : switch( xBox->getState() )
[ # # # # ]
3784 : : {
3785 : : case 0:
3786 : 0 : eValue = STATE_NOCHECK;
3787 : 0 : break;
3788 : : case 1:
3789 : 0 : eValue = STATE_CHECK;
3790 : 0 : break;
3791 : : case 2:
3792 : 0 : eValue = STATE_DONTKNOW;
3793 : 0 : break;
3794 : : }
3795 [ # # ]: 0 : return DbGridControl_Base::CreateAccessibleCheckBoxCell( _nRow, _nColumnPos,eValue,sal_True );
3796 [ # # ][ # # ]: 0 : }
3797 : : }
3798 : 0 : return DbGridControl_Base::CreateAccessibleCell( _nRow, _nColumnPos );
3799 : : }
3800 : : // -----------------------------------------------------------------------------
3801 : :
3802 : :
3803 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|