LCOV - code coverage report
Current view: top level - svx/source/fmcomp - gridctrl.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 846 1733 48.8 %
Date: 2014-11-03 Functions: 85 142 59.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10