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

Generated by: LCOV version 1.11