1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "svx/fmgridif.hxx"
21 #include "fmitems.hxx"
23 #include "svx/fmtools.hxx"
24 #include "svx/fmresids.hrc"
25 #include "fmservs.hxx"
27 #include "formcontrolfactory.hxx"
28 #include "gridcell.hxx"
29 #include "gridcols.hxx"
30 #include "svx/dbaexchange.hxx"
31 #include "svx/dialmgr.hxx"
32 #include "svx/dialogs.hrc"
33 #include "svx/fmgridcl.hxx"
34 #include "svx/svxdlg.hxx"
35 #include "svx/svxids.hrc"
37 #include <com/sun/star/form/XConfirmDeleteListener.hpp>
38 #include <com/sun/star/form/XFormComponent.hpp>
39 #include <com/sun/star/form/XGridColumnFactory.hpp>
40 #include <com/sun/star/io/XPersistObject.hpp>
41 #include <com/sun/star/sdb/CommandType.hpp>
42 #include <com/sun/star/sdb/RowChangeAction.hpp>
43 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
44 #include <com/sun/star/sdbc/DataType.hpp>
45 #include <com/sun/star/sdbc/XPreparedStatement.hpp>
46 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
47 #include <com/sun/star/sdbcx/XDeleteRows.hpp>
48 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
49 #include <com/sun/star/uno/XNamingService.hpp>
50 #include <com/sun/star/util/XNumberFormats.hpp>
51 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
52 #include <com/sun/star/util/URLTransformer.hpp>
53 #include <com/sun/star/util/XURLTransformer.hpp>
54 #include <com/sun/star/view/XSelectionSupplier.hpp>
55 #include <comphelper/extract.hxx>
56 #include <comphelper/numbers.hxx>
57 #include <comphelper/processfactory.hxx>
58 #include <comphelper/property.hxx>
59 #include <comphelper/string.hxx>
60 #include <connectivity/dbtools.hxx>
61 #include <sfx2/dispatch.hxx>
62 #include <sfx2/viewfrm.hxx>
63 #include <svl/eitem.hxx>
64 #include <svtools/fmtfield.hxx>
65 #include <svl/numuno.hxx>
66 #include <tools/multisel.hxx>
67 #include <tools/shl.hxx>
68 #include <tools/diagnose_ex.h>
69 #include <vcl/help.hxx>
70 #include <vcl/image.hxx>
71 #include <vcl/longcurr.hxx>
72 #include <vcl/menu.hxx>
76 using namespace ::com::sun::star::uno
;
77 using namespace ::com::sun::star::view
;
78 using namespace ::com::sun::star::beans
;
79 using namespace ::com::sun::star::lang
;
80 using namespace ::com::sun::star::sdbcx
;
81 using namespace ::com::sun::star::sdbc
;
82 using namespace ::com::sun::star::sdb
;
83 using namespace ::com::sun::star::form
;
84 using namespace ::com::sun::star::util
;
85 using namespace ::com::sun::star::container
;
86 using namespace ::cppu
;
87 using namespace ::svxform
;
88 using namespace ::svx
;
90 //==============================================================================
91 //------------------------------------------------------------------------------
92 OUString
FieldServiceFromId(sal_Int32 nID
)
96 case SID_FM_EDIT
: return FM_COL_TEXTFIELD
;
97 case SID_FM_COMBOBOX
: return FM_COL_COMBOBOX
;
98 case SID_FM_LISTBOX
: return FM_COL_LISTBOX
;
99 case SID_FM_CHECKBOX
: return FM_COL_CHECKBOX
;
100 case SID_FM_DATEFIELD
: return FM_COL_DATEFIELD
;
101 case SID_FM_TIMEFIELD
: return FM_COL_TIMEFIELD
;
102 case SID_FM_NUMERICFIELD
: return FM_COL_NUMERICFIELD
;
103 case SID_FM_CURRENCYFIELD
: return FM_COL_CURRENCYFIELD
;
104 case SID_FM_PATTERNFIELD
: return FM_COL_PATTERNFIELD
;
105 case SID_FM_FORMATTEDFIELD
: return FM_COL_FORMATTEDFIELD
;
110 //==============================================================================
111 struct FmGridHeaderData
113 ODataAccessDescriptor aDropData
;
115 sal_Int8 nDropAction
;
116 Reference
< XInterface
> xDroppedStatement
;
117 Reference
< XInterface
> xDroppedResultSet
;
120 //==============================================================================
121 //------------------------------------------------------------------------------
122 const sal_Int16 nChangeTypeOffset
= 1000;
123 void SetMenuItem(const ImageList
& rList
, sal_uInt16 nID
, Menu
* pMenu
, Menu
& rNewMenu
, sal_Bool bDesignMode
= sal_True
, sal_Int16 nOffset
= nChangeTypeOffset
)
125 pMenu
->SetItemImage(nID
, rList
.GetImage(nID
));
126 pMenu
->EnableItem(nID
, bDesignMode
);
127 rNewMenu
.InsertItem(nID
+ nOffset
, pMenu
->GetItemText(nID
));
128 rNewMenu
.SetItemImage(nID
+ nOffset
, rList
.GetImage(nID
));
129 rNewMenu
.SetHelpId(nID
+ nOffset
, pMenu
->GetHelpId(nID
));
130 rNewMenu
.EnableItem(nID
+ nOffset
, bDesignMode
);
133 //------------------------------------------------------------------------------
134 FmGridHeader::FmGridHeader( BrowseBox
* pParent
, WinBits nWinBits
)
135 :EditBrowserHeader(pParent
, nWinBits
)
136 ,DropTargetHelper(this)
137 ,m_pImpl(new FmGridHeaderData
)
141 //------------------------------------------------------------------------------
142 FmGridHeader::~FmGridHeader()
147 //------------------------------------------------------------------------------
148 sal_uInt16
FmGridHeader::GetModelColumnPos(sal_uInt16 nId
) const
150 return static_cast<FmGridControl
*>(GetParent())->GetModelColumnPos(nId
);
152 //---------------------------------------------------------------------------------------
153 void FmGridHeader::notifyColumnSelect(sal_uInt16 nColumnId
)
155 sal_uInt16 nPos
= GetModelColumnPos(nColumnId
);
156 Reference
< XIndexAccess
> xColumns(((FmGridControl
*)GetParent())->GetPeer()->getColumns(), UNO_QUERY
);
157 if ( nPos
< xColumns
->getCount() )
159 Reference
< XSelectionSupplier
> xSelSupplier(xColumns
, UNO_QUERY
);
160 if ( xSelSupplier
.is() )
162 Reference
< XPropertySet
> xColumn
;
163 xColumns
->getByIndex(nPos
) >>= xColumn
;
164 xSelSupplier
->select(makeAny(xColumn
));
168 //------------------------------------------------------------------------------
169 void FmGridHeader::Select()
171 EditBrowserHeader::Select();
172 notifyColumnSelect(GetCurItemId());
175 //------------------------------------------------------------------------------
176 void FmGridHeader::RequestHelp( const HelpEvent
& rHEvt
)
178 sal_uInt16 nItemId
= GetItemId( ScreenToOutputPixel( rHEvt
.GetMousePosPixel() ) );
181 if ( rHEvt
.GetMode() & (HELPMODE_QUICK
| HELPMODE_BALLOON
) )
183 Rectangle aItemRect
= GetItemRect( nItemId
);
184 Point aPt
= OutputToScreenPixel( aItemRect
.TopLeft() );
185 aItemRect
.Left() = aPt
.X();
186 aItemRect
.Top() = aPt
.Y();
187 aPt
= OutputToScreenPixel( aItemRect
.BottomRight() );
188 aItemRect
.Right() = aPt
.X();
189 aItemRect
.Bottom() = aPt
.Y();
191 sal_uInt16 nPos
= GetModelColumnPos(nItemId
);
192 Reference
< ::com::sun::star::container::XIndexContainer
> xColumns(static_cast<FmGridControl
*>(GetParent())->GetPeer()->getColumns());
195 Reference
< ::com::sun::star::beans::XPropertySet
> xColumn(xColumns
->getByIndex(nPos
),UNO_QUERY
);
197 xColumn
->getPropertyValue(FM_PROP_HELPTEXT
) >>= aHelpText
;
198 if ( aHelpText
.isEmpty() )
199 xColumn
->getPropertyValue(FM_PROP_DESCRIPTION
) >>= aHelpText
;
200 if ( !aHelpText
.isEmpty() )
202 if ( rHEvt
.GetMode() & HELPMODE_BALLOON
)
203 Help::ShowBalloon( this, aItemRect
.Center(), aItemRect
, aHelpText
);
205 Help::ShowQuickHelp( this, aItemRect
, aHelpText
);
215 EditBrowserHeader::RequestHelp( rHEvt
);
218 //------------------------------------------------------------------------------
219 sal_Int8
FmGridHeader::AcceptDrop( const AcceptDropEvent
& rEvt
)
221 // drop allowed in design mode only
222 if (!static_cast<FmGridControl
*>(GetParent())->IsDesignMode())
223 return DND_ACTION_NONE
;
225 // search for recognized formats
226 const DataFlavorExVector
& rFlavors
= GetDataFlavorExVector();
227 if (OColumnTransferable::canExtractColumnDescriptor(rFlavors
, CTF_COLUMN_DESCRIPTOR
| CTF_FIELD_DESCRIPTOR
))
228 return rEvt
.mnAction
;
230 return DND_ACTION_NONE
;
233 //------------------------------------------------------------------------------
234 sal_Int8
FmGridHeader::ExecuteDrop( const ExecuteDropEvent
& _rEvt
)
236 if (!static_cast<FmGridControl
*>(GetParent())->IsDesignMode())
237 return DND_ACTION_NONE
;
239 TransferableDataHelper
aDroppedData(_rEvt
.maDropEvent
.Transferable
);
242 sal_Bool bColumnDescriptor
= OColumnTransferable::canExtractColumnDescriptor(aDroppedData
.GetDataFlavorExVector(), CTF_COLUMN_DESCRIPTOR
);
243 sal_Bool bFieldDescriptor
= OColumnTransferable::canExtractColumnDescriptor(aDroppedData
.GetDataFlavorExVector(), CTF_FIELD_DESCRIPTOR
);
244 if (!bColumnDescriptor
&& !bFieldDescriptor
)
246 OSL_FAIL("FmGridHeader::ExecuteDrop: should never have reached this (no extractable format)!");
247 return DND_ACTION_NONE
;
250 // extract the descriptor
251 OUString sDatasouce
, sCommand
, sFieldName
,sDatabaseLocation
,sConnnectionResource
;
252 sal_Int32 nCommandType
= CommandType::COMMAND
;
253 Reference
< XPreparedStatement
> xStatement
;
254 Reference
< XResultSet
> xResultSet
;
255 Reference
< XPropertySet
> xField
;
256 Reference
< XConnection
> xConnection
;
258 ODataAccessDescriptor aColumn
= OColumnTransferable::extractColumnDescriptor(aDroppedData
);
259 if (aColumn
.has(daDataSource
)) aColumn
[daDataSource
] >>= sDatasouce
;
260 if (aColumn
.has(daDatabaseLocation
)) aColumn
[daDatabaseLocation
] >>= sDatabaseLocation
;
261 if (aColumn
.has(daConnectionResource
)) aColumn
[daConnectionResource
] >>= sConnnectionResource
;
262 if (aColumn
.has(daCommand
)) aColumn
[daCommand
] >>= sCommand
;
263 if (aColumn
.has(daCommandType
)) aColumn
[daCommandType
] >>= nCommandType
;
264 if (aColumn
.has(daColumnName
)) aColumn
[daColumnName
] >>= sFieldName
;
265 if (aColumn
.has(daColumnObject
))aColumn
[daColumnObject
] >>= xField
;
266 if (aColumn
.has(daConnection
)) aColumn
[daConnection
] >>= xConnection
;
268 if ( sFieldName
.isEmpty()
269 || sCommand
.isEmpty()
270 || ( sDatasouce
.isEmpty()
271 && sDatabaseLocation
.isEmpty()
276 OSL_FAIL( "FmGridHeader::ExecuteDrop: somebody started a nonsense drag operation!!" );
277 return DND_ACTION_NONE
;
283 if (!xConnection
.is())
284 { // the transferable did not contain the connection -> build an own one
287 OUString
sSignificantSource( sDatasouce
.isEmpty() ? sDatabaseLocation
: sDatasouce
);
288 xConnection
= OStaticDataAccessTools().getConnection_withFeedback(sSignificantSource
, OUString(), OUString(),
289 static_cast<FmGridControl
*>(GetParent())->getContext() );
291 catch(NoSuchElementException
&)
292 { // allowed, means sDatasouce isn't a valid data source name ....
296 OSL_FAIL("FmGridHeader::ExecuteDrop: could not retrieve the database access object !");
299 if (!xConnection
.is())
301 OSL_FAIL("FmGridHeader::ExecuteDrop: could not retrieve the database access object !");
302 return DND_ACTION_NONE
;
306 // try to obtain the column object
310 Reference
< XServiceInfo
> xServiceInfo(xConnection
, UNO_QUERY
);
311 DBG_ASSERT(xServiceInfo
.is() && xServiceInfo
->supportsService(SRV_SDB_CONNECTION
), "FmGridHeader::ExecuteDrop: invalid connection (no database access connection !)");
314 Reference
< XNameAccess
> xFields
;
315 switch (nCommandType
)
317 case CommandType::TABLE
:
319 Reference
< XTablesSupplier
> xSupplyTables(xConnection
, UNO_QUERY
);
320 Reference
< XColumnsSupplier
> xSupplyColumns
;
321 xSupplyTables
->getTables()->getByName(sCommand
) >>= xSupplyColumns
;
322 xFields
= xSupplyColumns
->getColumns();
325 case CommandType::QUERY
:
327 Reference
< XQueriesSupplier
> xSupplyQueries(xConnection
, UNO_QUERY
);
328 Reference
< XColumnsSupplier
> xSupplyColumns
;
329 xSupplyQueries
->getQueries()->getByName(sCommand
) >>= xSupplyColumns
;
330 xFields
= xSupplyColumns
->getColumns();
335 xStatement
= xConnection
->prepareStatement(sCommand
);
336 // not interested in any results
338 Reference
< XPropertySet
> xStatProps(xStatement
,UNO_QUERY
);
339 xStatProps
->setPropertyValue(OUString("MaxRows"), makeAny(sal_Int32(0)));
341 xResultSet
= xStatement
->executeQuery();
342 Reference
< XColumnsSupplier
> xSupplyCols(xResultSet
, UNO_QUERY
);
343 if (xSupplyCols
.is())
344 xFields
= xSupplyCols
->getColumns();
348 if (xFields
.is() && xFields
->hasByName(sFieldName
))
349 xFields
->getByName(sFieldName
) >>= xField
;
353 ::comphelper::disposeComponent(xStatement
);
354 return DND_ACTION_NONE
;
358 // do the drop asynchronously
359 // (85957 - UI actions within the drop are not allowed, but we want to open a popup menu)
360 m_pImpl
->aDropData
= aColumn
;
361 m_pImpl
->aDropData
[daConnection
] <<= xConnection
;
362 m_pImpl
->aDropData
[daColumnObject
] <<= xField
;
364 m_pImpl
->nDropAction
= _rEvt
.mnAction
;
365 m_pImpl
->aDropPosPixel
= _rEvt
.maPosPixel
;
366 m_pImpl
->xDroppedStatement
= xStatement
;
367 m_pImpl
->xDroppedResultSet
= xResultSet
;
369 PostUserEvent(LINK(this, FmGridHeader
, OnAsyncExecuteDrop
));
373 OSL_FAIL("FmGridHeader::ExecuteDrop: caught an exception while creatin' the column !");
374 ::comphelper::disposeComponent(xStatement
);
378 return DND_ACTION_LINK
;
381 //------------------------------------------------------------------------------
382 IMPL_LINK( FmGridHeader
, OnAsyncExecuteDrop
, void*, /*NOTINTERESTEDIN*/ )
384 OUString sCommand
, sFieldName
,sURL
;
385 sal_Int32 nCommandType
= CommandType::COMMAND
;
386 Reference
< XPropertySet
> xField
;
387 Reference
< XConnection
> xConnection
;
389 OUString sDatasouce
= m_pImpl
->aDropData
.getDataSource();
390 if ( sDatasouce
.isEmpty() && m_pImpl
->aDropData
.has(daConnectionResource
) )
391 m_pImpl
->aDropData
[daConnectionResource
] >>= sURL
;
392 m_pImpl
->aDropData
[daCommand
] >>= sCommand
;
393 m_pImpl
->aDropData
[daCommandType
] >>= nCommandType
;
394 m_pImpl
->aDropData
[daColumnName
] >>= sFieldName
;
395 m_pImpl
->aDropData
[daConnection
] >>= xConnection
;
396 m_pImpl
->aDropData
[daColumnObject
] >>= xField
;
400 // need number formats
401 Reference
< XNumberFormatsSupplier
> xSupplier
= OStaticDataAccessTools().getNumberFormats(xConnection
, sal_True
);
402 Reference
< XNumberFormats
> xNumberFormats
;
404 xNumberFormats
= xSupplier
->getNumberFormats();
405 if (!xNumberFormats
.is())
407 ::comphelper::disposeComponent(m_pImpl
->xDroppedResultSet
);
408 ::comphelper::disposeComponent(m_pImpl
->xDroppedStatement
);
412 // Vom Feld werden nun zwei Informationen benoetigt:
413 // a.) Name des Feldes fuer Label und ControlSource
414 // b.) FormatKey, um festzustellen, welches Feld erzeugt werden soll
415 sal_Int32 nDataType
= 0;
416 xField
->getPropertyValue(FM_PROP_FIELDTYPE
) >>= nDataType
;
417 // diese Datentypen koennen im Gridcontrol nicht verarbeitet werden
421 case DataType::LONGVARBINARY
:
422 case DataType::BINARY
:
423 case DataType::VARBINARY
:
424 case DataType::OTHER
:
425 ::comphelper::disposeComponent(m_pImpl
->xDroppedResultSet
);
426 ::comphelper::disposeComponent(m_pImpl
->xDroppedStatement
);
430 // Erstellen der Column
431 Reference
< XIndexContainer
> xCols(static_cast<FmGridControl
*>(GetParent())->GetPeer()->getColumns());
432 Reference
< XGridColumnFactory
> xFactory(xCols
, UNO_QUERY
);
434 sal_uInt16 nColId
= GetItemId(m_pImpl
->aDropPosPixel
);
435 // EinfuegePosition, immer vor der aktuellen Spalte
436 sal_uInt16 nPos
= GetModelColumnPos(nColId
);
437 Reference
< XPropertySet
> xCol
, xSecondCol
;
439 // Create Column based on type, default textfield
440 std::vector
<sal_uInt16
> aPossibleTypes
;
444 case DataType::BOOLEAN
:
445 aPossibleTypes
.push_back(SID_FM_CHECKBOX
);
447 case DataType::TINYINT
:
448 case DataType::SMALLINT
:
449 case DataType::INTEGER
:
450 aPossibleTypes
.push_back(SID_FM_NUMERICFIELD
);
451 aPossibleTypes
.push_back(SID_FM_FORMATTEDFIELD
);
454 case DataType::DOUBLE
:
455 case DataType::NUMERIC
:
456 case DataType::DECIMAL
:
457 aPossibleTypes
.push_back(SID_FM_FORMATTEDFIELD
);
458 aPossibleTypes
.push_back(SID_FM_NUMERICFIELD
);
460 case DataType::TIMESTAMP
:
461 aPossibleTypes
.push_back(SID_FM_TWOFIELDS_DATE_N_TIME
);
462 aPossibleTypes
.push_back(SID_FM_DATEFIELD
);
463 aPossibleTypes
.push_back(SID_FM_TIMEFIELD
);
464 aPossibleTypes
.push_back(SID_FM_FORMATTEDFIELD
);
467 aPossibleTypes
.push_back(SID_FM_DATEFIELD
);
468 aPossibleTypes
.push_back(SID_FM_FORMATTEDFIELD
);
471 aPossibleTypes
.push_back(SID_FM_TIMEFIELD
);
472 aPossibleTypes
.push_back(SID_FM_FORMATTEDFIELD
);
475 case DataType::VARCHAR
:
476 case DataType::LONGVARCHAR
:
478 aPossibleTypes
.push_back(SID_FM_EDIT
);
479 aPossibleTypes
.push_back(SID_FM_FORMATTEDFIELD
);
482 // if it's a currency field, a a "currency field" option
485 if ( ::comphelper::hasProperty(FM_PROP_ISCURRENCY
, xField
)
486 && ::comphelper::getBOOL(xField
->getPropertyValue(FM_PROP_ISCURRENCY
)))
487 aPossibleTypes
.insert(aPossibleTypes
.begin(), SID_FM_CURRENCYFIELD
);
491 OSL_FAIL("FmGridHeader::ExecuteDrop: Exception occurred!");
494 sal_Bool bDateNTimeCol
= sal_False
;
495 if (!aPossibleTypes
.empty())
497 sal_Int32 nPreferedType
= aPossibleTypes
[0];
498 if ((m_pImpl
->nDropAction
== DND_ACTION_LINK
) && (aPossibleTypes
.size() > 1))
500 ImageList
aImageList( SVX_RES(RID_SVXIMGLIST_FMEXPL
) );
502 PopupMenu
aInsertMenu(SVX_RES(RID_SVXMNU_COLS
));
504 PopupMenu
* pMenu
= aInsertMenu
.GetPopupMenu(SID_FM_INSERTCOL
);
505 for (std::vector
<sal_uInt16
>::const_iterator iter
= aPossibleTypes
.begin(); iter
!= aPossibleTypes
.end(); ++iter
)
506 SetMenuItem(aImageList
, *iter
, pMenu
, aTypeMenu
, sal_True
, 0);
507 nPreferedType
= aTypeMenu
.Execute(this, m_pImpl
->aDropPosPixel
);
510 bDateNTimeCol
= nPreferedType
== SID_FM_TWOFIELDS_DATE_N_TIME
;
511 sal_uInt16 nColCount
= bDateNTimeCol
? 2 : 1;
512 OUString sFieldService
;
516 nPreferedType
= nColCount
? SID_FM_DATEFIELD
: SID_FM_TIMEFIELD
;
518 sFieldService
= FieldServiceFromId(nPreferedType
);
519 Reference
< XPropertySet
> xThisRoundCol
;
520 if ( !sFieldService
.isEmpty() )
521 xThisRoundCol
= xFactory
->createColumn(sFieldService
);
523 xSecondCol
= xThisRoundCol
;
525 xCol
= xThisRoundCol
;
529 if (!xCol
.is() || (bDateNTimeCol
&& !xSecondCol
.is()))
531 ::comphelper::disposeComponent(xCol
); // in case only the creation of the second column failed
532 ::comphelper::disposeComponent(m_pImpl
->xDroppedResultSet
);
533 ::comphelper::disposeComponent(m_pImpl
->xDroppedStatement
);
539 String
sTimePostfix( SVX_RES( RID_STR_POSTFIX_TIME
) );
540 xCol
->setPropertyValue(FM_PROP_LABEL
, makeAny( OUString( sFieldName
+ sTimePostfix
) ) );
542 String
sDatePostfix( SVX_RES( RID_STR_POSTFIX_DATE
) );
543 xSecondCol
->setPropertyValue(FM_PROP_LABEL
, makeAny( OUString( sFieldName
+ sDatePostfix
) ) );
546 xCol
->setPropertyValue(FM_PROP_LABEL
, makeAny(sFieldName
));
548 FormControlFactory
aControlFactory( ::comphelper::getProcessServiceFactory() );
549 aControlFactory
.initializeControlModel( DocumentClassification::classifyHostDocument( xCols
), xCol
);
550 aControlFactory
.initializeFieldDependentProperties( xField
, xCol
, xNumberFormats
);
552 xCol
->setPropertyValue(FM_PROP_CONTROLSOURCE
, makeAny(sFieldName
));
553 if ( xSecondCol
.is() )
554 xSecondCol
->setPropertyValue(FM_PROP_CONTROLSOURCE
, makeAny(sFieldName
));
558 String sRealName
,sPurePostfix
;
560 String aPostfix
[] = {
561 String( SVX_RES( RID_STR_POSTFIX_DATE
) ),
562 String( SVX_RES( RID_STR_POSTFIX_TIME
) )
565 for ( size_t i
=0; i
<2; ++i
)
567 sPurePostfix
= comphelper::string::stripStart(aPostfix
[i
], ' ');
568 sPurePostfix
= comphelper::string::stripStart(sPurePostfix
, '(');
569 sPurePostfix
= comphelper::string::stripEnd(sPurePostfix
, ')');
570 sRealName
= sFieldName
;
572 sRealName
+= sPurePostfix
;
574 xSecondCol
->setPropertyValue(FM_PROP_NAME
, makeAny(OUString(sRealName
)));
576 xCol
->setPropertyValue(FM_PROP_NAME
, makeAny(OUString(sRealName
)));
580 xCol
->setPropertyValue(FM_PROP_NAME
, makeAny(sFieldName
));
585 xCols
->insertByIndex(nPos
, aElement
);
589 aElement
<<= xSecondCol
;
590 xCols
->insertByIndex(nPos
== (sal_uInt16
)-1 ? nPos
: ++nPos
, aElement
);
593 // ist die component::Form an die Datenbankangebunden?
594 Reference
< XFormComponent
> xFormCp(xCols
, UNO_QUERY
);
595 Reference
< XPropertySet
> xForm(xFormCp
->getParent(), UNO_QUERY
);
598 if (::comphelper::getString(xForm
->getPropertyValue(FM_PROP_DATASOURCE
)).isEmpty())
600 if ( !sDatasouce
.isEmpty() )
601 xForm
->setPropertyValue(FM_PROP_DATASOURCE
, makeAny(sDatasouce
));
603 xForm
->setPropertyValue(FM_PROP_URL
, makeAny(sURL
));
606 if (::comphelper::getString(xForm
->getPropertyValue(FM_PROP_COMMAND
)).isEmpty())
608 xForm
->setPropertyValue(FM_PROP_COMMAND
, makeAny(sCommand
));
610 switch (nCommandType
)
612 case CommandType::TABLE
:
613 aCommandType
<<= (sal_Int32
)CommandType::TABLE
;
615 case CommandType::QUERY
:
616 aCommandType
<<= (sal_Int32
)CommandType::QUERY
;
619 aCommandType
<<= (sal_Int32
)CommandType::COMMAND
;
620 xForm
->setPropertyValue(FM_PROP_ESCAPE_PROCESSING
, bool2any((sal_Bool
)(2 == nCommandType
)));
623 xForm
->setPropertyValue(FM_PROP_COMMANDTYPE
, aCommandType
);
629 OSL_FAIL("FmGridHeader::OnAsyncExecuteDrop: caught an exception while creatin' the column !");
630 ::comphelper::disposeComponent(m_pImpl
->xDroppedResultSet
);
631 ::comphelper::disposeComponent(m_pImpl
->xDroppedStatement
);
635 ::comphelper::disposeComponent(m_pImpl
->xDroppedResultSet
);
636 ::comphelper::disposeComponent(m_pImpl
->xDroppedStatement
);
640 //------------------------------------------------------------------------------
641 void FmGridHeader::PreExecuteColumnContextMenu(sal_uInt16 nColId
, PopupMenu
& rMenu
)
643 sal_Bool bDesignMode
= static_cast<FmGridControl
*>(GetParent())->IsDesignMode();
645 Reference
< ::com::sun::star::container::XIndexContainer
> xCols(static_cast<FmGridControl
*>(GetParent())->GetPeer()->getColumns());
646 // Aufbau des Insert Menues
647 // mark the column if nColId != HEADERBAR_ITEM_NOTFOUND
650 sal_uInt16 nPos2
= GetModelColumnPos(nColId
);
652 Reference
< ::com::sun::star::container::XIndexContainer
> xColumns(static_cast<FmGridControl
*>(GetParent())->GetPeer()->getColumns());
653 Reference
< ::com::sun::star::beans::XPropertySet
> xColumn
;
654 ::cppu::extractInterface(xColumn
, xColumns
->getByIndex(nPos2
));
655 Reference
< ::com::sun::star::view::XSelectionSupplier
> xSelSupplier(xColumns
, UNO_QUERY
);
656 if (xSelSupplier
.is())
657 xSelSupplier
->select(makeAny(xColumn
));
660 // EinfuegePosition, immer vor der aktuellen Spalte
661 sal_uInt16 nPos
= GetModelColumnPos(nColId
);
662 sal_Bool bMarked
= nColId
&& static_cast<FmGridControl
*>(GetParent())->isColumnMarked(nColId
);
664 ImageList
aImageList( SVX_RES(RID_SVXIMGLIST_FMEXPL
) );
665 PopupMenu
* pControlMenu
= new PopupMenu
;
667 PopupMenu
* pMenu
= rMenu
.GetPopupMenu(SID_FM_INSERTCOL
);
670 SetMenuItem(aImageList
, SID_FM_EDIT
, pMenu
, *pControlMenu
, bDesignMode
);
671 SetMenuItem(aImageList
, SID_FM_CHECKBOX
, pMenu
, *pControlMenu
, bDesignMode
);
672 SetMenuItem(aImageList
, SID_FM_COMBOBOX
, pMenu
, *pControlMenu
, bDesignMode
);
673 SetMenuItem(aImageList
, SID_FM_LISTBOX
, pMenu
, *pControlMenu
, bDesignMode
);
674 SetMenuItem(aImageList
, SID_FM_DATEFIELD
, pMenu
, *pControlMenu
, bDesignMode
);
675 SetMenuItem(aImageList
, SID_FM_TIMEFIELD
, pMenu
, *pControlMenu
, bDesignMode
);
676 SetMenuItem(aImageList
, SID_FM_NUMERICFIELD
, pMenu
, *pControlMenu
, bDesignMode
);
677 SetMenuItem(aImageList
, SID_FM_CURRENCYFIELD
, pMenu
, *pControlMenu
, bDesignMode
);
678 SetMenuItem(aImageList
, SID_FM_PATTERNFIELD
, pMenu
, *pControlMenu
, bDesignMode
);
679 SetMenuItem(aImageList
, SID_FM_FORMATTEDFIELD
, pMenu
, *pControlMenu
, bDesignMode
);
682 if (pMenu
&& xCols
.is() && nColId
)
684 Reference
< ::com::sun::star::beans::XPropertySet
> xSet
;
685 ::cppu::extractInterface(xSet
, xCols
->getByIndex(nPos
));
687 xSet
->getPropertyValue(FM_PROP_CLASSID
) >>= nClassId
;
689 Reference
< ::com::sun::star::io::XPersistObject
> xServiceQuestion(xSet
, UNO_QUERY
);
690 sal_Int32 nColType
= xServiceQuestion
.is() ? getColumnTypeByModelName(xServiceQuestion
->getServiceName()) : 0;
691 if (nColType
== TYPE_TEXTFIELD
)
692 { // edit fields and formatted fields have the same service name, thus getColumnTypeByModelName returns TYPE_TEXTFIELD
693 // in both cases. And as columns don't have an ::com::sun::star::lang::XServiceInfo interface, we have to distinguish both
694 // types via the existence of special properties
695 Reference
< ::com::sun::star::beans::XPropertySet
> xProps(xSet
, UNO_QUERY
);
698 Reference
< ::com::sun::star::beans::XPropertySetInfo
> xPropsInfo
= xProps
->getPropertySetInfo();
699 if (xPropsInfo
.is() && xPropsInfo
->hasPropertyByName(FM_PROP_FORMATSSUPPLIER
))
700 nColType
= TYPE_FORMATTEDFIELD
;
704 pControlMenu
->EnableItem(SID_FM_EDIT
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_TEXTFIELD
));
705 pControlMenu
->EnableItem(SID_FM_COMBOBOX
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_COMBOBOX
));
706 pControlMenu
->EnableItem(SID_FM_LISTBOX
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_LISTBOX
));
707 pControlMenu
->EnableItem(SID_FM_CHECKBOX
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_CHECKBOX
));
708 pControlMenu
->EnableItem(SID_FM_DATEFIELD
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_DATEFIELD
));
709 pControlMenu
->EnableItem(SID_FM_NUMERICFIELD
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_NUMERICFIELD
));
710 pControlMenu
->EnableItem(SID_FM_TIMEFIELD
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_TIMEFIELD
));
711 pControlMenu
->EnableItem(SID_FM_CURRENCYFIELD
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_CURRENCYFIELD
));
712 pControlMenu
->EnableItem(SID_FM_PATTERNFIELD
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_PATTERNFIELD
));
713 pControlMenu
->EnableItem(SID_FM_FORMATTEDFIELD
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_FORMATTEDFIELD
));
714 rMenu
.SetPopupMenu(SID_FM_CHANGECOL
, pControlMenu
);
717 rMenu
.EnableItem(SID_FM_INSERTCOL
, bDesignMode
&& xCols
.is());
718 rMenu
.EnableItem(SID_FM_DELETECOL
, bDesignMode
&& bMarked
&& xCols
.is());
719 rMenu
.EnableItem(SID_FM_CHANGECOL
, bDesignMode
&& bMarked
&& xCols
.is());
720 rMenu
.EnableItem(SID_FM_SHOW_PROPERTY_BROWSER
, bDesignMode
&& bMarked
&& xCols
.is());
722 PopupMenu
* pShowColsMenu
= rMenu
.GetPopupMenu(SID_FM_SHOWCOLS
);
723 sal_uInt16 nHiddenCols
= 0;
728 // check for hidden cols
729 Reference
< ::com::sun::star::beans::XPropertySet
> xCurCol
;
731 for (sal_uInt16 i
=0; i
<xCols
->getCount(); ++i
)
733 ::cppu::extractInterface(xCurCol
, xCols
->getByIndex(i
));
734 DBG_ASSERT(xCurCol
.is(), "FmGridHeader::PreExecuteColumnContextMenu : the Peer has invalid columns !");
735 aHidden
= xCurCol
->getPropertyValue(FM_PROP_HIDDEN
);
736 DBG_ASSERT(aHidden
.getValueType().getTypeClass() == TypeClass_BOOLEAN
,
737 "FmGridHeader::PreExecuteColumnContextMenu : the property 'hidden' should be boolean !");
738 if (::comphelper::getBOOL(aHidden
))
740 // put the column name into the 'show col' menu
741 if (nHiddenCols
< 16)
742 { // (only the first 16 items to keep the menu rather small)
743 aName
= xCurCol
->getPropertyValue(FM_PROP_LABEL
);
744 pShowColsMenu
->InsertItem(nHiddenCols
+ 1, ::comphelper::getString(aName
),
745 0, OString(), nHiddenCols
);
746 // the ID is arbitrary, but should be unique within the whole menu
752 pShowColsMenu
->EnableItem(SID_FM_SHOWCOLS_MORE
, xCols
.is() && (nHiddenCols
> 16));
753 pShowColsMenu
->EnableItem(SID_FM_SHOWALLCOLS
, xCols
.is() && (nHiddenCols
> 0));
756 // allow the 'hide column' item ?
757 sal_Bool bAllowHide
= bMarked
; // a column is marked
758 bAllowHide
= bAllowHide
|| (!bDesignMode
&& (nPos
!= (sal_uInt16
)-1)); // OR we are in alive mode and have hit a column
759 bAllowHide
= bAllowHide
&& xCols
.is(); // AND we have a column container
760 bAllowHide
= bAllowHide
&& (xCols
->getCount()-nHiddenCols
> 1); // AND there are at least two visible columns
761 rMenu
.EnableItem(SID_FM_HIDECOL
, bAllowHide
);
763 sal_Bool bChecked
= sal_False
;
767 SfxViewFrame
* pCurrentFrame
= SfxViewFrame::Current();
768 SfxItemState eState
= SFX_ITEM_UNKNOWN
;
769 // ask the bindings of the current view frame (which should be the one we're residing in) for the state
772 SfxPoolItem
* pItem
= NULL
;
773 eState
= pCurrentFrame
->GetBindings().QueryState(SID_FM_CTL_PROPERTIES
, pItem
);
775 if (eState
>= SFX_ITEM_AVAILABLE
&& pItem
)
777 bChecked
= pItem
->ISA(SfxBoolItem
) && ((SfxBoolItem
*)pItem
)->GetValue();
778 rMenu
.CheckItem(SID_FM_SHOW_PROPERTY_BROWSER
,bChecked
);
785 enum InspectorAction
{ eOpenInspector
, eCloseInspector
, eUpdateInspector
, eNone
};
787 //------------------------------------------------------------------------------
788 void FmGridHeader::PostExecuteColumnContextMenu(sal_uInt16 nColId
, const PopupMenu
& rMenu
, sal_uInt16 nExecutionResult
)
790 Reference
< ::com::sun::star::container::XIndexContainer
> xCols(static_cast<FmGridControl
*>(GetParent())->GetPeer()->getColumns());
791 sal_uInt16 nPos
= GetModelColumnPos(nColId
);
793 // remove and delet the menu we inserted in PreExecuteColumnContextMenu
794 PopupMenu
* pControlMenu
= rMenu
.GetPopupMenu(SID_FM_CHANGECOL
);
798 sal_Bool bReplace
= sal_False
;
799 InspectorAction eInspectorAction
= eNone
;
800 Reference
< XPropertySet
> xColumnToInspect
;
801 switch (nExecutionResult
)
803 case SID_FM_DELETECOL
:
805 Reference
< XInterface
> xCol
;
806 ::cppu::extractInterface(xCol
, xCols
->getByIndex(nPos
));
807 xCols
->removeByIndex(nPos
);
808 ::comphelper::disposeComponent(xCol
);
810 case SID_FM_SHOW_PROPERTY_BROWSER
:
811 eInspectorAction
= rMenu
.IsItemChecked( SID_FM_SHOW_PROPERTY_BROWSER
) ? eOpenInspector
: eCloseInspector
;
812 xColumnToInspect
.set( xCols
->getByIndex( nPos
), UNO_QUERY
);
814 case SID_FM_EDIT
+ nChangeTypeOffset
:
817 aFieldType
= FM_COL_TEXTFIELD
;
819 case SID_FM_COMBOBOX
+ nChangeTypeOffset
:
821 case SID_FM_COMBOBOX
:
822 aFieldType
= FM_COL_COMBOBOX
;
824 case SID_FM_LISTBOX
+ nChangeTypeOffset
:
827 aFieldType
= FM_COL_LISTBOX
;
829 case SID_FM_CHECKBOX
+ nChangeTypeOffset
:
831 case SID_FM_CHECKBOX
:
832 aFieldType
= FM_COL_CHECKBOX
;
834 case SID_FM_DATEFIELD
+ nChangeTypeOffset
:
836 case SID_FM_DATEFIELD
:
837 aFieldType
= FM_COL_DATEFIELD
;
839 case SID_FM_TIMEFIELD
+ nChangeTypeOffset
:
841 case SID_FM_TIMEFIELD
:
842 aFieldType
= FM_COL_TIMEFIELD
;
844 case SID_FM_NUMERICFIELD
+ nChangeTypeOffset
:
846 case SID_FM_NUMERICFIELD
:
847 aFieldType
= FM_COL_NUMERICFIELD
;
849 case SID_FM_CURRENCYFIELD
+ nChangeTypeOffset
:
851 case SID_FM_CURRENCYFIELD
:
852 aFieldType
= FM_COL_CURRENCYFIELD
;
854 case SID_FM_PATTERNFIELD
+ nChangeTypeOffset
:
856 case SID_FM_PATTERNFIELD
:
857 aFieldType
= FM_COL_PATTERNFIELD
;
859 case SID_FM_FORMATTEDFIELD
+ nChangeTypeOffset
:
861 case SID_FM_FORMATTEDFIELD
:
862 aFieldType
= FM_COL_FORMATTEDFIELD
;
866 Reference
< ::com::sun::star::beans::XPropertySet
> xCurCol
;
867 ::cppu::extractInterface(xCurCol
, xCols
->getByIndex(nPos
));
868 xCurCol
->setPropertyValue(FM_PROP_HIDDEN
, makeAny((sal_Bool
)sal_True
));
871 case SID_FM_SHOWCOLS_MORE
:
873 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
876 AbstractFmShowColsDialog
* pDlg
= pFact
->CreateFmShowColsDialog(NULL
);
877 DBG_ASSERT(pDlg
, "Dialogdiet fail!");
878 pDlg
->SetColumns(xCols
);
885 case SID_FM_SHOWALLCOLS
:
887 // just iterate through all the cols ...
888 Reference
< ::com::sun::star::beans::XPropertySet
> xCurCol
;
889 for (sal_uInt16 i
=0; i
<xCols
->getCount(); ++i
)
891 ::cppu::extractInterface(xCurCol
, xCols
->getByIndex(i
));
892 xCurCol
->setPropertyValue(FM_PROP_HIDDEN
, makeAny((sal_Bool
)sal_False
));
894 // TODO : there must be a more clever way to do this ....
895 // with the above the view is updated after every single model update ...
899 if (nExecutionResult
>0 && nExecutionResult
<=16)
900 { // it was a "show column/<colname>" command (there are at most 16 such items)
901 // search the nExecutionResult'th hidden col
902 Reference
< ::com::sun::star::beans::XPropertySet
> xCurCol
;
903 for (sal_uInt16 i
=0; i
<xCols
->getCount() && nExecutionResult
; ++i
)
905 ::cppu::extractInterface(xCurCol
, xCols
->getByIndex(i
));
906 Any aHidden
= xCurCol
->getPropertyValue(FM_PROP_HIDDEN
);
907 if (::comphelper::getBOOL(aHidden
))
908 if (!--nExecutionResult
)
910 xCurCol
->setPropertyValue(FM_PROP_HIDDEN
, makeAny((sal_Bool
)sal_False
));
918 if ( !aFieldType
.isEmpty() )
922 Reference
< XGridColumnFactory
> xFactory( xCols
, UNO_QUERY_THROW
);
923 Reference
< XPropertySet
> xNewCol( xFactory
->createColumn( aFieldType
), UNO_SET_THROW
);
927 // ein paar Properties hinueberretten
928 Reference
< XPropertySet
> xReplaced( xCols
->getByIndex( nPos
), UNO_QUERY
);
930 OStaticDataAccessTools().TransferFormComponentProperties(
931 xReplaced
, xNewCol
, Application::GetSettings().GetUILanguageTag().getLocale() );
933 xCols
->replaceByIndex( nPos
, makeAny( xNewCol
) );
934 ::comphelper::disposeComponent( xReplaced
);
936 eInspectorAction
= eUpdateInspector
;
937 xColumnToInspect
= xNewCol
;
941 FormControlFactory
factory( ::comphelper::getProcessServiceFactory() );
943 OUString sLabel
= factory
.getDefaultUniqueName_ByComponentType(
944 Reference
< XNameAccess
>( xCols
, UNO_QUERY_THROW
), xNewCol
);
945 xNewCol
->setPropertyValue( FM_PROP_LABEL
, makeAny( sLabel
) );
946 xNewCol
->setPropertyValue( FM_PROP_NAME
, makeAny( sLabel
) );
948 factory
.initializeControlModel( DocumentClassification::classifyHostDocument( xCols
), xNewCol
);
950 xCols
->insertByIndex( nPos
, makeAny( xNewCol
) );
953 catch( const Exception
& )
955 DBG_UNHANDLED_EXCEPTION();
959 SfxViewFrame
* pCurrentFrame
= SfxViewFrame::Current();
960 OSL_ENSURE( pCurrentFrame
, "FmGridHeader::PostExecuteColumnContextMenu: no view frame -> no bindings -> no property browser!" );
963 if ( eInspectorAction
== eUpdateInspector
)
965 if ( !pCurrentFrame
->HasChildWindow( SID_FM_SHOW_PROPERTIES
) )
966 eInspectorAction
= eNone
;
969 if ( eInspectorAction
!= eNone
)
971 FmInterfaceItem
aIFaceItem( SID_FM_SHOW_PROPERTY_BROWSER
, xColumnToInspect
);
972 SfxBoolItem
aShowItem( SID_FM_SHOW_PROPERTIES
, eInspectorAction
== eCloseInspector
? sal_False
: sal_True
);
974 pCurrentFrame
->GetBindings().GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER
, SFX_CALLMODE_ASYNCHRON
,
975 &aIFaceItem
, &aShowItem
, 0L );
980 //------------------------------------------------------------------------------
981 void FmGridHeader::triggerColumnContextMenu( const ::Point
& _rPreferredPos
)
984 sal_uInt16 nColId
= GetItemId( _rPreferredPos
);
987 PopupMenu
aContextMenu( SVX_RES( RID_SVXMNU_COLS
) );
989 // let derivees modify the menu
990 PreExecuteColumnContextMenu( nColId
, aContextMenu
);
991 aContextMenu
.RemoveDisabledEntries( sal_True
, sal_True
);
994 sal_uInt16 nResult
= aContextMenu
.Execute( this, _rPreferredPos
);
996 // let derivees handle the result
997 PostExecuteColumnContextMenu( nColId
, aContextMenu
, nResult
);
1000 //------------------------------------------------------------------------------
1001 void FmGridHeader::Command(const CommandEvent
& rEvt
)
1003 switch (rEvt
.GetCommand())
1005 case COMMAND_CONTEXTMENU
:
1007 if (!rEvt
.IsMouseEvent())
1010 triggerColumnContextMenu( rEvt
.GetMousePosPixel() );
1014 EditBrowserHeader::Command(rEvt
);
1018 //------------------------------------------------------------------------------
1019 FmGridControl::FmGridControl(
1020 const Reference
< ::com::sun::star::uno::XComponentContext
>& _rxContext
,
1022 FmXGridPeer
* _pPeer
,
1024 :DbGridControl(_rxContext
, pParent
, nBits
)
1026 ,m_nCurrentSelectedColumn(-1)
1027 ,m_nMarkedColumnId(BROWSER_INVALIDID
)
1028 ,m_bSelecting(sal_False
)
1029 ,m_bInColumnMove(sal_False
)
1031 EnableInteractiveRowHeight( );
1034 //------------------------------------------------------------------------------
1035 void FmGridControl::Command(const CommandEvent
& _rEvt
)
1037 if ( COMMAND_CONTEXTMENU
== _rEvt
.GetCommand() )
1039 FmGridHeader
* pMyHeader
= static_cast< FmGridHeader
* >( GetHeaderBar() );
1040 if ( pMyHeader
&& !_rEvt
.IsMouseEvent() )
1041 { // context menu requested by keyboard
1042 if ( 1 == GetSelectColumnCount() || IsDesignMode() )
1044 sal_uInt16 nSelId
= GetColumnId(
1045 sal::static_int_cast
< sal_uInt16
>( FirstSelectedColumn() ) );
1046 ::Rectangle
aColRect( GetFieldRectPixel( 0, nSelId
, sal_False
) );
1048 Point
aRelativePos( pMyHeader
->ScreenToOutputPixel( OutputToScreenPixel( aColRect
.TopCenter() ) ) );
1049 pMyHeader
->triggerColumnContextMenu( aRelativePos
, FmGridHeader::AccessControl() );
1057 DbGridControl::Command( _rEvt
);
1060 // ::com::sun::star::beans::XPropertyChangeListener
1061 //------------------------------------------------------------------------------
1062 void FmGridControl::propertyChange(const ::com::sun::star::beans::PropertyChangeEvent
& evt
)
1064 if (evt
.PropertyName
== FM_PROP_ROWCOUNT
)
1066 // if we're not in the main thread call AdjustRows asynchronously
1067 implAdjustInSolarThread(sal_True
);
1071 const DbGridRowRef
& xRow
= GetCurrentRow();
1072 // waehrend Positionierung wird kein abgleich der Properties vorgenommen
1073 Reference
<XPropertySet
> xSet(evt
.Source
,UNO_QUERY
);
1074 if (xRow
.Is() && (::cppu::any2bool(xSet
->getPropertyValue(FM_PROP_ISNEW
))|| CompareBookmark(getDataSource()->getBookmark(), xRow
->GetBookmark())))
1076 if (evt
.PropertyName
== FM_PROP_ISMODIFIED
)
1078 // modified or clean ?
1079 GridRowStatus eStatus
= ::comphelper::getBOOL(evt
.NewValue
) ? GRS_MODIFIED
: GRS_CLEAN
;
1080 if (eStatus
!= xRow
->GetStatus())
1082 xRow
->SetStatus(eStatus
);
1083 SolarMutexGuard aGuard
;
1084 RowModified(GetCurrentPos());
1090 //------------------------------------------------------------------------------
1091 void FmGridControl::SetDesignMode(sal_Bool bMode
)
1093 sal_Bool bOldMode
= IsDesignMode();
1094 DbGridControl::SetDesignMode(bMode
);
1095 if (bOldMode
!= bMode
)
1099 // selection aufheben
1100 markColumn(USHRT_MAX
);
1104 Reference
< ::com::sun::star::container::XIndexContainer
> xColumns(GetPeer()->getColumns());
1105 Reference
< ::com::sun::star::view::XSelectionSupplier
> xSelSupplier(xColumns
, UNO_QUERY
);
1106 if (xSelSupplier
.is())
1108 Any aSelection
= xSelSupplier
->getSelection();
1109 Reference
< ::com::sun::star::beans::XPropertySet
> xColumn
;
1110 if (aSelection
.getValueType().getTypeClass() == TypeClass_INTERFACE
)
1111 ::cppu::extractInterface(xColumn
, aSelection
);
1112 Reference
< XInterface
> xCurrent
;
1113 for (sal_uInt16 i
=0; i
<xColumns
->getCount(); ++i
)
1115 ::cppu::extractInterface(xCurrent
, xColumns
->getByIndex(i
));
1116 if (xCurrent
== xColumn
)
1118 markColumn(GetColumnIdFromModelPos(i
));
1127 //------------------------------------------------------------------------------
1128 void FmGridControl::DeleteSelectedRows()
1133 // how many rows are selected?
1134 sal_Int32 nSelectedRows
= GetSelectRowCount();
1136 // the current line should be deleted but it is currently in edit mode
1137 if ( IsCurrentAppending() )
1139 // is the insert row selected
1140 if (GetEmptyRow().Is() && IsRowSelected(GetRowCount() - 1))
1144 if (nSelectedRows
<= 0)
1147 // try to confirm the delete
1148 Reference
< ::com::sun::star::frame::XDispatchProvider
> xDispatcher
= (::com::sun::star::frame::XDispatchProvider
*)GetPeer();
1149 if (xDispatcher
.is())
1151 ::com::sun::star::util::URL aUrl
;
1152 aUrl
.Complete
= FMURL_CONFIRM_DELETION
;
1153 // #100312# ------------
1154 Reference
< ::com::sun::star::util::XURLTransformer
> xTransformer(
1155 ::com::sun::star::util::URLTransformer::create(::comphelper::getProcessComponentContext()) );
1156 xTransformer
->parseStrict( aUrl
);
1158 Reference
< ::com::sun::star::frame::XDispatch
> xDispatch
= xDispatcher
->queryDispatch(aUrl
, OUString(), 0);
1159 Reference
< ::com::sun::star::form::XConfirmDeleteListener
> xConfirm(xDispatch
, UNO_QUERY
);
1162 ::com::sun::star::sdb::RowChangeEvent aEvent
;
1163 aEvent
.Source
= (Reference
< XInterface
> )(*getDataSource());
1164 aEvent
.Rows
= nSelectedRows
;
1165 aEvent
.Action
= ::com::sun::star::sdb::RowChangeAction::DELETE
;
1166 if (!xConfirm
->confirmDelete(aEvent
))
1171 const MultiSelection
* pRowSelection
= GetSelection();
1172 if ( pRowSelection
&& pRowSelection
->IsAllSelected() )
1174 BeginCursorAction();
1175 CursorWrapper
* pCursor
= getDataSource();
1176 Reference
< XResultSetUpdate
> xUpdateCursor((Reference
< XInterface
>)*pCursor
, UNO_QUERY
);
1179 pCursor
->beforeFirst();
1180 while( pCursor
->next() )
1181 xUpdateCursor
->deleteRow();
1183 SetUpdateMode(sal_False
);
1186 xUpdateCursor
->moveToInsertRow();
1188 catch(const Exception
&)
1190 OSL_FAIL("Exception caught while deleting rows!");
1192 // An den DatenCursor anpassen
1193 AdjustDataSource(sal_True
);
1195 SetUpdateMode(sal_True
);
1199 Reference
< ::com::sun::star::sdbcx::XDeleteRows
> xDeleteThem((Reference
< XInterface
>)*getDataSource(), UNO_QUERY
);
1201 // colect the bookmarks of the selected rows
1202 Sequence
< Any
> aBookmarks
= getSelectionBookmarks();
1204 // determine the next row to position after deletion
1206 sal_Bool bNewPos
= sal_False
;
1207 // if the current row isn't selected we take the row as row after deletion
1208 OSL_ENSURE( GetCurrentRow().Is(), "FmGridControl::DeleteSelectedRows: no current row here?" );
1209 // crash reports suggest it can happen we don't have a current row - how?
1210 // #154303# / 2008-04-23 / frank.schoenheit@sun.com
1211 if ( !IsRowSelected( GetCurrentPos() ) && !IsCurrentAppending() && GetCurrentRow().Is() )
1213 aBookmark
= GetCurrentRow()->GetBookmark();
1218 // we look for the first row after the selected block for selection
1219 long nIdx
= LastSelectedRow() + 1;
1220 if (nIdx
< GetRowCount() - 1)
1222 // there is a next row to position on
1223 if (SeekCursor(nIdx
))
1225 GetSeekRow()->SetState(m_pSeekCursor
, sal_True
);
1228 // if it's not the row for inserting we keep the bookmark
1229 if (!IsInsertionRow(nIdx
))
1230 aBookmark
= m_pSeekCursor
->getBookmark();
1235 // we look for the first row before the selected block for selection after deletion
1236 nIdx
= FirstSelectedRow() - 1;
1237 if (nIdx
>= 0 && SeekCursor(nIdx
))
1239 GetSeekRow()->SetState(m_pSeekCursor
, sal_True
);
1242 aBookmark
= m_pSeekCursor
->getBookmark();
1247 // Sind alle Zeilen Selectiert
1248 // Zweite bedingung falls keine einguegeZeile existiert
1249 sal_Bool bAllSelected
= GetTotalCount() == nSelectedRows
|| GetRowCount() == nSelectedRows
;
1251 BeginCursorAction();
1253 // now delete the row
1254 Sequence
<sal_Int32
> aDeletedRows
;
1255 SetUpdateMode( sal_False
);
1258 aDeletedRows
= xDeleteThem
->deleteRows(aBookmarks
);
1260 catch(SQLException
&)
1263 SetUpdateMode( sal_True
);
1265 // how many rows are deleted?
1266 sal_Int32 nDeletedRows
= 0;
1267 const sal_Int32
* pSuccess
= aDeletedRows
.getConstArray();
1268 for (sal_Int32 i
= 0; i
< aDeletedRows
.getLength(); i
++)
1274 // sind Zeilen geloescht worden?
1277 SetUpdateMode(sal_False
);
1281 // did we delete all the rows than try to move to the next possible row
1282 if (nDeletedRows
== aDeletedRows
.getLength())
1284 // there exists a new position to move on
1287 if (aBookmark
.hasValue())
1288 getDataSource()->moveToBookmark(aBookmark
);
1289 // no valid bookmark so move to the insert row
1292 Reference
< XResultSetUpdate
> xUpdateCursor((Reference
< XInterface
>)*m_pDataCursor
, UNO_QUERY
);
1293 xUpdateCursor
->moveToInsertRow();
1298 Reference
< ::com::sun::star::beans::XPropertySet
> xSet((Reference
< XInterface
>)*m_pDataCursor
, UNO_QUERY
);
1300 sal_Int32
nRecordCount(0);
1301 xSet
->getPropertyValue(FM_PROP_ROWCOUNT
) >>= nRecordCount
;
1302 if ( m_pDataCursor
->rowDeleted() )
1305 // there are no rows left and we have an insert row
1306 if (!nRecordCount
&& GetEmptyRow().Is())
1308 Reference
< XResultSetUpdate
> xUpdateCursor((Reference
< XInterface
>)*m_pDataCursor
, UNO_QUERY
);
1309 xUpdateCursor
->moveToInsertRow();
1311 else if (nRecordCount
)
1312 // move to the first row
1313 getDataSource()->first();
1316 // not all the rows where deleted, so move to the first row which remained in the resultset
1319 for (sal_Int32 i
= 0; i
< aDeletedRows
.getLength(); i
++)
1323 getDataSource()->moveToBookmark(aBookmarks
.getConstArray()[i
]);
1329 catch(const Exception
&)
1333 // positioning went wrong so try to move to the first row
1334 getDataSource()->first();
1336 catch(const Exception
&)
1341 // An den DatenCursor anpassen
1342 AdjustDataSource(sal_True
);
1344 // es konnten nicht alle Zeilen geloescht werden
1345 // da nie nicht geloeschten wieder selektieren
1346 if (nDeletedRows
< nSelectedRows
)
1348 // waren alle selektiert
1352 if (IsInsertionRow(GetRowCount() - 1)) // einfuegeZeile nicht
1353 SelectRow(GetRowCount() - 1, sal_False
);
1357 // select the remaining rows
1358 for (sal_Int32 i
= 0; i
< aDeletedRows
.getLength(); i
++)
1364 m_pSeekCursor
->moveToBookmark(m_pDataCursor
->getBookmark());
1365 SetSeekPos(m_pSeekCursor
->getRow() - 1);
1366 SelectRow(GetSeekPos());
1369 catch(const Exception
&)
1371 // keep the seekpos in all cases
1372 SetSeekPos(m_pSeekCursor
->getRow() - 1);
1379 SetUpdateMode(sal_True
);
1381 else // Zeile konnte nicht geloescht werden
1386 // currentrow is the insert row?
1387 if (!IsCurrentAppending())
1388 getDataSource()->refreshRow();
1390 catch(const Exception
&)
1396 // if there is no selection anymore we can start editing
1397 if (!GetSelectRowCount())
1402 // XCurrentRecordListener
1403 //------------------------------------------------------------------------------
1404 void FmGridControl::positioned(const ::com::sun::star::lang::EventObject
& /*rEvent*/)
1406 SAL_INFO("svx.fmcmop", "FmGridControl::positioned");
1407 // position on the data source (force it to be done in the main thread)
1408 implAdjustInSolarThread(sal_False
);
1411 //------------------------------------------------------------------------------
1412 sal_Bool
FmGridControl::commit()
1414 // Commit nur ausfuehren, wenn nicht bereits ein Update vom ::com::sun::star::form::component::GridControl ausgefuehrt
1418 if (Controller().Is() && Controller()->IsModified())
1420 if (!SaveModified())
1427 //------------------------------------------------------------------------------
1428 void FmGridControl::inserted(const ::com::sun::star::lang::EventObject
& /*rEvent*/)
1430 const DbGridRowRef
& xRow
= GetCurrentRow();
1434 // Zeile ist eingefuegt worden, dann den status und mode zuruecksetzen
1435 xRow
->SetState(m_pDataCursor
, sal_False
);
1436 xRow
->SetNew(sal_False
);
1440 //------------------------------------------------------------------------------
1441 BrowserHeader
* FmGridControl::imp_CreateHeaderBar(BrowseBox
* pParent
)
1443 DBG_ASSERT( pParent
== this, "FmGridControl::imp_CreateHeaderBar: parent?" );
1444 return new FmGridHeader( pParent
);
1447 //------------------------------------------------------------------------------
1448 void FmGridControl::markColumn(sal_uInt16 nId
)
1450 if (GetHeaderBar() && m_nMarkedColumnId
!= nId
)
1453 if (m_nMarkedColumnId
!= BROWSER_INVALIDID
)
1455 HeaderBarItemBits aBits
= GetHeaderBar()->GetItemBits(m_nMarkedColumnId
) & ~HIB_FLAT
;
1456 GetHeaderBar()->SetItemBits(m_nMarkedColumnId
, aBits
);
1460 if (nId
!= BROWSER_INVALIDID
)
1462 HeaderBarItemBits aBits
= GetHeaderBar()->GetItemBits(nId
) | HIB_FLAT
;
1463 GetHeaderBar()->SetItemBits(nId
, aBits
);
1465 m_nMarkedColumnId
= nId
;
1469 //------------------------------------------------------------------------------
1470 sal_Bool
FmGridControl::isColumnMarked(sal_uInt16 nId
) const
1472 return m_nMarkedColumnId
== nId
;
1475 //------------------------------------------------------------------------------
1476 long FmGridControl::QueryMinimumRowHeight()
1478 long nMinimalLogicHeight
= 20; // 0.2 cm
1479 long nMinimalPixelHeight
= LogicToPixel( Point( 0, nMinimalLogicHeight
), MAP_10TH_MM
).Y();
1480 return CalcZoom( nMinimalPixelHeight
);
1483 //------------------------------------------------------------------------------
1484 void FmGridControl::RowHeightChanged()
1486 DbGridControl::RowHeightChanged();
1488 Reference
< XPropertySet
> xModel( GetPeer()->getColumns(), UNO_QUERY
);
1489 DBG_ASSERT( xModel
.is(), "FmGridControl::RowHeightChanged: no model!" );
1494 sal_Int32 nUnzoomedPixelHeight
= CalcReverseZoom( GetDataRowHeight() );
1495 Any aProperty
= makeAny( (sal_Int32
)PixelToLogic( Point( 0, nUnzoomedPixelHeight
), MAP_10TH_MM
).Y() );
1496 xModel
->setPropertyValue( FM_PROP_ROWHEIGHT
, aProperty
);
1498 catch( const Exception
& )
1500 OSL_FAIL( "FmGridControl::RowHeightChanged: caught an exception!" );
1505 //------------------------------------------------------------------------------
1506 void FmGridControl::ColumnResized(sal_uInt16 nId
)
1508 DbGridControl::ColumnResized(nId
);
1510 // Wert ans model uebergeben
1511 DbGridColumn
* pCol
= DbGridControl::GetColumns().at( GetModelColumnPos(nId
) );
1512 Reference
< ::com::sun::star::beans::XPropertySet
> xColModel(pCol
->getModel());
1516 sal_Int32 nColumnWidth
= GetColumnWidth(nId
);
1517 nColumnWidth
= CalcReverseZoom(nColumnWidth
);
1518 // Umrechnen in 10THMM
1519 aWidth
<<= (sal_Int32
)PixelToLogic(Point(nColumnWidth
,0),MAP_10TH_MM
).X();
1520 xColModel
->setPropertyValue(FM_PROP_WIDTH
, aWidth
);
1524 //------------------------------------------------------------------------------
1525 void FmGridControl::CellModified()
1527 DbGridControl::CellModified();
1528 GetPeer()->CellModified();
1531 //------------------------------------------------------------------------------
1532 void FmGridControl::BeginCursorAction()
1534 DbGridControl::BeginCursorAction();
1535 m_pPeer
->stopCursorListening();
1538 //------------------------------------------------------------------------------
1539 void FmGridControl::EndCursorAction()
1541 m_pPeer
->startCursorListening();
1542 DbGridControl::EndCursorAction();
1545 //------------------------------------------------------------------------------
1546 void FmGridControl::ColumnMoved(sal_uInt16 nId
)
1548 m_bInColumnMove
= sal_True
;
1550 DbGridControl::ColumnMoved(nId
);
1551 Reference
< ::com::sun::star::container::XIndexContainer
> xColumns(GetPeer()->getColumns());
1555 // suchen der Spalte und verschieben im Model
1557 DbGridColumn
* pCol
= DbGridControl::GetColumns().at( GetModelColumnPos(nId
) );
1558 Reference
< ::com::sun::star::beans::XPropertySet
> xCol
;
1560 // Einfuegen muß sich an den Column Positionen orientieren
1562 Reference
< XInterface
> xCurrent
;
1563 for (i
= 0; !xCol
.is() && i
< xColumns
->getCount(); i
++)
1565 ::cppu::extractInterface(xCurrent
, xColumns
->getByIndex(i
));
1566 if (xCurrent
== pCol
->getModel())
1568 xCol
= pCol
->getModel();
1573 DBG_ASSERT(i
< xColumns
->getCount(), "Falscher ::com::sun::star::sdbcx::Index");
1574 xColumns
->removeByIndex(i
);
1577 xColumns
->insertByIndex(GetModelColumnPos(nId
), aElement
);
1578 pCol
->setModel(xCol
);
1579 // if the column which is shown here is selected ...
1580 if ( isColumnSelected(nId
,pCol
) )
1581 markColumn(nId
); // ... -> mark it
1584 m_bInColumnMove
= sal_False
;
1587 //------------------------------------------------------------------------------
1588 void FmGridControl::InitColumnsByModels(const Reference
< ::com::sun::star::container::XIndexContainer
>& xColumns
)
1590 // Spalten wieder neu setzen
1591 // wenn es nur eine HandleColumn gibt, dann nicht
1592 if (GetModelColCount())
1595 InsertHandleColumn();
1601 SetUpdateMode(sal_False
);
1603 // Einfuegen mu� sich an den Column Positionen orientieren
1606 for (i
= 0; i
< xColumns
->getCount(); ++i
)
1608 Reference
< ::com::sun::star::beans::XPropertySet
> xCol
;
1609 ::cppu::extractInterface(xCol
, xColumns
->getByIndex(i
));
1612 comphelper::getString(xCol
->getPropertyValue(FM_PROP_LABEL
)));
1614 aWidth
= xCol
->getPropertyValue(FM_PROP_WIDTH
);
1615 sal_Int32 nWidth
= 0;
1616 if (aWidth
>>= nWidth
)
1617 nWidth
= LogicToPixel(Point(nWidth
,0),MAP_10TH_MM
).X();
1619 AppendColumn(aName
, (sal_uInt16
)nWidth
);
1620 DbGridColumn
* pCol
= DbGridControl::GetColumns().at( i
);
1621 pCol
->setModel(xCol
);
1624 // und jetzt noch die hidden columns rausnehmen
1625 // (wir haben das nicht gleich in der oberen Schleife gemacht, da wir dann Probleme mit den
1626 // IDs der Spalten bekommen haetten : AppendColumn vergibt die automatisch, die Spalte _nach_
1627 // einer versteckten braucht aber eine um eine erhoehte ID ....
1629 for (i
= 0; i
< xColumns
->getCount(); ++i
)
1631 Reference
< ::com::sun::star::beans::XPropertySet
> xCol
;
1632 ::cppu::extractInterface(xCol
, xColumns
->getByIndex(i
));
1633 aHidden
= xCol
->getPropertyValue(FM_PROP_HIDDEN
);
1634 if (::comphelper::getBOOL(aHidden
))
1635 HideColumn(GetColumnIdFromModelPos((sal_uInt16
)i
));
1638 SetUpdateMode(sal_True
);
1641 //------------------------------------------------------------------------------
1642 void FmGridControl::InitColumnByField(
1643 DbGridColumn
* _pColumn
, const Reference
< XPropertySet
>& _rxColumnModel
,
1644 const Reference
< XNameAccess
>& _rxFieldsByNames
, const Reference
< XIndexAccess
>& _rxFieldsByIndex
)
1646 DBG_ASSERT( _rxFieldsByNames
== _rxFieldsByIndex
, "FmGridControl::InitColumnByField: invalid container interfaces!" );
1648 // lookup the column which belongs to the control source
1649 OUString sFieldName
;
1650 _rxColumnModel
->getPropertyValue( FM_PROP_CONTROLSOURCE
) >>= sFieldName
;
1651 Reference
< XPropertySet
> xField
;
1652 _rxColumnModel
->getPropertyValue( FM_PROP_BOUNDFIELD
) >>= xField
;
1655 if ( !xField
.is() && /*sFieldName.getLength() && */_rxFieldsByNames
->hasByName( sFieldName
) ) // #i93452# do not check for name length
1656 _rxFieldsByNames
->getByName( sFieldName
) >>= xField
;
1658 // determine the position of this column
1659 sal_Int32 nFieldPos
= -1;
1662 Reference
< XPropertySet
> xCheck
;
1663 sal_Int32 nFieldCount
= _rxFieldsByIndex
->getCount();
1664 for ( sal_Int32 i
= 0; i
< nFieldCount
; ++i
)
1666 _rxFieldsByIndex
->getByIndex( i
) >>= xCheck
;
1667 if ( xField
.get() == xCheck
.get() )
1675 if ( xField
.is() && ( nFieldPos
>= 0 ) )
1677 // some data types are not allowed
1678 sal_Int32 nDataType
= DataType::OTHER
;
1679 xField
->getPropertyValue( FM_PROP_FIELDTYPE
) >>= nDataType
;
1681 sal_Bool bIllegalType
= sal_False
;
1682 switch ( nDataType
)
1684 case DataType::BLOB
:
1685 case DataType::LONGVARBINARY
:
1686 case DataType::BINARY
:
1687 case DataType::VARBINARY
:
1688 case DataType::OTHER
:
1689 bIllegalType
= sal_True
;
1695 _pColumn
->SetObject( (sal_Int16
)nFieldPos
);
1700 // the control type is determined by the ColumnServiceName
1701 static OUString
s_sPropColumnServiceName( "ColumnServiceName" );
1702 if ( !::comphelper::hasProperty( s_sPropColumnServiceName
, _rxColumnModel
) )
1705 _pColumn
->setModel( _rxColumnModel
);
1707 OUString sColumnServiceName
;
1708 _rxColumnModel
->getPropertyValue( s_sPropColumnServiceName
) >>= sColumnServiceName
;
1710 sal_Int32 nTypeId
= getColumnTypeByModelName( sColumnServiceName
);
1711 _pColumn
->CreateControl( nFieldPos
, xField
, nTypeId
);
1714 //------------------------------------------------------------------------------
1715 void FmGridControl::InitColumnsByFields(const Reference
< ::com::sun::star::container::XIndexAccess
>& _rxFields
)
1717 if ( !_rxFields
.is() )
1720 // Spalten initialisieren
1721 Reference
< XIndexContainer
> xColumns( GetPeer()->getColumns() );
1722 Reference
< XNameAccess
> xFieldsAsNames( _rxFields
, UNO_QUERY
);
1724 // Einfuegen muss sich an den Column Positionen orientieren
1725 for (sal_Int32 i
= 0; i
< xColumns
->getCount(); i
++)
1727 DbGridColumn
* pCol
= GetColumns().at( i
);
1728 OSL_ENSURE(pCol
,"No grid column!");
1731 Reference
< XPropertySet
> xColumnModel
;
1732 ::cppu::extractInterface( xColumnModel
, xColumns
->getByIndex( i
) );
1734 InitColumnByField( pCol
, xColumnModel
, xFieldsAsNames
, _rxFields
);
1739 //------------------------------------------------------------------------------
1740 void FmGridControl::HideColumn(sal_uInt16 nId
)
1742 DbGridControl::HideColumn(nId
);
1744 sal_uInt16 nPos
= GetModelColumnPos(nId
);
1745 if (nPos
== (sal_uInt16
)-1)
1748 DbGridColumn
* pColumn
= GetColumns().at( nPos
);
1749 if (pColumn
->IsHidden())
1750 GetPeer()->columnHidden(pColumn
);
1752 if (nId
== m_nMarkedColumnId
)
1753 m_nMarkedColumnId
= (sal_uInt16
)-1;
1755 // -----------------------------------------------------------------------------
1756 sal_Bool
FmGridControl::isColumnSelected(sal_uInt16
/*nId*/,DbGridColumn
* _pColumn
)
1758 OSL_ENSURE(_pColumn
,"Column can not be null!");
1759 sal_Bool bSelected
= sal_False
;
1760 // if the column which is shown here is selected ...
1761 Reference
< ::com::sun::star::view::XSelectionSupplier
> xSelSupplier(GetPeer()->getColumns(), UNO_QUERY
);
1762 if ( xSelSupplier
.is() )
1764 Reference
< ::com::sun::star::beans::XPropertySet
> xColumn
;
1765 xSelSupplier
->getSelection() >>= xColumn
;
1766 bSelected
= (xColumn
.get() == _pColumn
->getModel().get());
1771 //------------------------------------------------------------------------------
1772 void FmGridControl::ShowColumn(sal_uInt16 nId
)
1774 DbGridControl::ShowColumn(nId
);
1776 sal_uInt16 nPos
= GetModelColumnPos(nId
);
1777 if (nPos
== (sal_uInt16
)-1)
1780 DbGridColumn
* pColumn
= GetColumns().at( nPos
);
1781 if (!pColumn
->IsHidden())
1782 GetPeer()->columnVisible(pColumn
);
1784 // if the column which is shown here is selected ...
1785 if ( isColumnSelected(nId
,pColumn
) )
1786 markColumn(nId
); // ... -> mark it
1789 //------------------------------------------------------------------------------
1790 sal_Bool
FmGridControl::selectBookmarks(const Sequence
< Any
>& _rBookmarks
)
1792 SolarMutexGuard aGuard
;
1793 // need to lock the SolarMutex so that no paint call disturbs us ...
1795 if ( !m_pSeekCursor
)
1797 OSL_FAIL( "FmGridControl::selectBookmarks: no seek cursor!" );
1801 const Any
* pBookmark
= _rBookmarks
.getConstArray();
1802 const Any
* pBookmarkEnd
= pBookmark
+ _rBookmarks
.getLength();
1806 sal_Bool bAllSuccessfull
= sal_True
;
1809 for (; pBookmark
!= pBookmarkEnd
; ++pBookmark
)
1811 // move the seek cursor to the row given
1812 if (m_pSeekCursor
->moveToBookmark(*pBookmark
))
1813 SelectRow( m_pSeekCursor
->getRow() - 1);
1815 bAllSuccessfull
= sal_False
;
1820 OSL_FAIL("FmGridControl::selectBookmarks: could not move to one of the bookmarks!");
1824 return bAllSuccessfull
;
1827 //------------------------------------------------------------------------------
1828 Sequence
< Any
> FmGridControl::getSelectionBookmarks()
1830 // lock our update so no paint-triggered seeks interfere ...
1831 SetUpdateMode(sal_False
);
1833 sal_Int32 nSelectedRows
= GetSelectRowCount(), i
= 0;
1834 Sequence
< Any
> aBookmarks(nSelectedRows
);
1835 if ( nSelectedRows
)
1837 Any
* pBookmarks
= (Any
*)aBookmarks
.getArray();
1839 // (I'm not sure if the problem isn't deeper : The szenario : a large table displayed by a grid with a
1840 // thread-safe cursor (dBase). On loading the sdb-cursor started a counting thread. While this counting progress
1841 // was running, I tried do delete 3 records from within the grid. Deletion caused a SeekCursor, which did a
1842 // m_pSeekCursor->moveRelative and a m_pSeekCursor->getPosition.
1843 // Unfortunally the first call caused a propertyChanged(RECORDCOUNT) which resulted in a repaint of the
1844 // navigation bar and the grid. The latter itself will result in SeekRow calls. So after (successfully) returning
1845 // from the moveRelative the getPosition returns an invalid value. And so the SeekCursor fails.
1846 // In the consequence ALL parts of code where two calls to the seek cursor are done, while the second call _relys_ on
1847 // the first one, should be secured against recursion, with a broad-minded interpretion of "recursion" : if any of these
1848 // code parts is executed, no other should be accessible. But this sounds very difficult to achieve ....
1851 // The next problem caused by the same behaviuor (SeekCursor causes a propertyChanged) : when adjusting rows we implicitly
1852 // change our selection. So a "FirstSelected(); SeekCursor(); NextSelected();" may produce unpredictable results.
1853 // That's why we _first_ collect the indicies of the selected rows and _then_ their bookmarks.
1854 long nIdx
= FirstSelectedRow();
1857 // (we misuse the bookmarks array for this ...)
1858 pBookmarks
[i
++] <<= (sal_Int32
)nIdx
;
1859 nIdx
= NextSelectedRow();
1861 DBG_ASSERT(i
== nSelectedRows
, "FmGridControl::DeleteSelectedRows : could not collect the row indicies !");
1863 for (i
=0; i
<nSelectedRows
; ++i
)
1865 nIdx
= ::comphelper::getINT32(pBookmarks
[i
]);
1866 if (IsInsertionRow(nIdx
))
1868 // leerzeile nicht loeschen
1869 aBookmarks
.realloc(--nSelectedRows
);
1870 SelectRow(nIdx
,sal_False
); // selection aufheben fuer leerzeile
1874 // Zunaechst den DatenCursor auf den selektierten Satz pos.
1875 if (SeekCursor(nIdx
))
1877 GetSeekRow()->SetState(m_pSeekCursor
, sal_True
);
1879 pBookmarks
[i
] = m_pSeekCursor
->getBookmark();
1883 OSL_FAIL("FmGridControl::DeleteSelectedRows : a bookmark could not be determined !");
1887 SetUpdateMode(sal_True
);
1889 // if one of the SeekCursor-calls failed ....
1890 aBookmarks
.realloc(i
);
1892 // (the alternative : while collecting the bookmarks lock our propertyChanged, this should resolve both our problems.
1893 // but this would be incompatible as we need a locking flag, then ...)
1897 // -----------------------------------------------------------------------------
1900 OUString
getColumnPropertyFromPeer(FmXGridPeer
* _pPeer
,sal_Int32 _nPosition
,const OUString
& _sPropName
)
1903 if ( _pPeer
&& _nPosition
!= -1)
1905 Reference
<XIndexContainer
> xIndex
= _pPeer
->getColumns();
1906 if ( xIndex
.is() && xIndex
->getCount() > _nPosition
)
1908 Reference
<XPropertySet
> xProp
;
1909 xIndex
->getByIndex( _nPosition
) >>= xProp
;
1913 xProp
->getPropertyValue( _sPropName
) >>= sRetText
;
1914 } catch (UnknownPropertyException
const& e
) {
1915 SAL_WARN("svx.form",
1916 "exception caught: " << e
.Message
);
1924 // Object data and state ------------------------------------------------------
1925 OUString
FmGridControl::GetAccessibleObjectName( ::svt::AccessibleBrowseBoxObjType _eObjType
,sal_Int32 _nPosition
) const
1930 case ::svt::BBTYPE_BROWSEBOX
:
1933 Reference
<XPropertySet
> xProp(GetPeer()->getColumns(),UNO_QUERY
);
1935 xProp
->getPropertyValue(FM_PROP_NAME
) >>= sRetText
;
1938 case ::svt::BBTYPE_COLUMNHEADERCELL
:
1939 sRetText
= getColumnPropertyFromPeer(
1942 sal::static_int_cast
< sal_uInt16
>(_nPosition
)),
1946 sRetText
= DbGridControl::GetAccessibleObjectName(_eObjType
,_nPosition
);
1950 // -----------------------------------------------------------------------------
1952 OUString
FmGridControl::GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eObjType
,sal_Int32 _nPosition
) const
1957 case ::svt::BBTYPE_BROWSEBOX
:
1960 Reference
<XPropertySet
> xProp(GetPeer()->getColumns(),UNO_QUERY
);
1963 xProp
->getPropertyValue(FM_PROP_HELPTEXT
) >>= sRetText
;
1964 if ( sRetText
.isEmpty() )
1965 xProp
->getPropertyValue(FM_PROP_DESCRIPTION
) >>= sRetText
;
1969 case ::svt::BBTYPE_COLUMNHEADERCELL
:
1970 sRetText
= getColumnPropertyFromPeer(
1973 sal::static_int_cast
< sal_uInt16
>(_nPosition
)),
1975 if ( sRetText
.isEmpty() )
1976 sRetText
= getColumnPropertyFromPeer(
1979 sal::static_int_cast
< sal_uInt16
>(_nPosition
)),
1980 FM_PROP_DESCRIPTION
);
1984 sRetText
= DbGridControl::GetAccessibleObjectDescription(_eObjType
,_nPosition
);
1988 // -----------------------------------------------------------------------------
1989 void FmGridControl::Select()
1991 DbGridControl::Select();
1992 // ... betrifft das unsere Spalten ?
1993 const MultiSelection
* pColumnSelection
= GetColumnSelection();
1995 sal_uInt16 nSelectedColumn
=
1996 pColumnSelection
&& pColumnSelection
->GetSelectCount()
1997 ? sal::static_int_cast
< sal_uInt16
>(
1998 ((MultiSelection
*)pColumnSelection
)->FirstSelected())
2000 // die HandleColumn wird nicht selektiert
2001 switch (nSelectedColumn
)
2003 case SAL_MAX_UINT16
: break; // no selection
2004 case 0 : nSelectedColumn
= SAL_MAX_UINT16
; break;
2005 // handle col can't be seledted
2007 // get the model col pos instead of the view col pos
2008 nSelectedColumn
= GetModelColumnPos(GetColumnIdFromViewPos(nSelectedColumn
- 1));
2012 if (nSelectedColumn
!= m_nCurrentSelectedColumn
)
2014 // VOR dem Aufruf des select am SelectionSupplier !
2015 m_nCurrentSelectedColumn
= nSelectedColumn
;
2019 m_bSelecting
= sal_True
;
2023 Reference
< XIndexAccess
> xColumns(GetPeer()->getColumns(), UNO_QUERY
);
2024 Reference
< XSelectionSupplier
> xSelSupplier(xColumns
, UNO_QUERY
);
2025 if (xSelSupplier
.is())
2027 if (nSelectedColumn
!= SAL_MAX_UINT16
)
2029 Reference
< XPropertySet
> xColumn
;
2030 ::cppu::extractInterface(xColumn
,xColumns
->getByIndex(nSelectedColumn
));
2031 xSelSupplier
->select(makeAny(xColumn
));
2035 xSelSupplier
->select(Any());
2044 m_bSelecting
= sal_False
;
2048 // -----------------------------------------------------------------------------
2049 sal_Int32
FmGridControl::GetSelectedColumn() const
2051 return m_nCurrentSelectedColumn
;
2053 // -----------------------------------------------------------------------------
2054 void FmGridControl::KeyInput( const KeyEvent
& rKEvt
)
2056 sal_Bool bDone
= sal_False
;
2057 const KeyCode
& rKeyCode
= rKEvt
.GetKeyCode();
2059 && !rKeyCode
.IsShift()
2060 && !rKeyCode
.IsMod1()
2061 && !rKeyCode
.IsMod2()
2064 switch ( rKeyCode
.GetCode() )
2067 GetParent()->GrabFocus();
2071 if ( GetSelectColumnCount() && GetPeer() && m_nCurrentSelectedColumn
>= 0 )
2073 Reference
< ::com::sun::star::container::XIndexContainer
> xCols(GetPeer()->getColumns());
2078 if ( m_nCurrentSelectedColumn
< xCols
->getCount() )
2080 Reference
< XInterface
> xCol
;
2081 xCols
->getByIndex(m_nCurrentSelectedColumn
) >>= xCol
;
2082 xCols
->removeByIndex(m_nCurrentSelectedColumn
);
2083 ::comphelper::disposeComponent(xCol
);
2086 catch(const Exception
&)
2088 OSL_FAIL("exception occurred while deleting a column");
2097 DbGridControl::KeyInput( rKEvt
);
2099 // -----------------------------------------------------------------------------
2103 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */