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 "svx/fmgridif.hxx"
21 : #include "fmitems.hxx"
22 : #include "fmprop.hrc"
23 : #include "svx/fmtools.hxx"
24 : #include "svx/fmresids.hrc"
25 : #include "fmservs.hxx"
26 : #include "fmurl.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"
36 :
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/numbers.hxx>
56 : #include <comphelper/processfactory.hxx>
57 : #include <comphelper/property.hxx>
58 : #include <comphelper/string.hxx>
59 : #include <connectivity/dbtools.hxx>
60 : #include <sfx2/dispatch.hxx>
61 : #include <sfx2/viewfrm.hxx>
62 : #include <svl/eitem.hxx>
63 : #include <svtools/fmtfield.hxx>
64 : #include <svl/numuno.hxx>
65 : #include <tools/multisel.hxx>
66 : #include <tools/shl.hxx>
67 : #include <tools/diagnose_ex.h>
68 : #include <vcl/help.hxx>
69 : #include <vcl/image.hxx>
70 : #include <vcl/longcurr.hxx>
71 : #include <vcl/menu.hxx>
72 : #include <vcl/settings.hxx>
73 :
74 : #include <math.h>
75 :
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;
89 :
90 0 : OUString FieldServiceFromId(sal_Int32 nID)
91 : {
92 0 : switch (nID)
93 : {
94 0 : case SID_FM_EDIT : return FM_COL_TEXTFIELD;
95 0 : case SID_FM_COMBOBOX : return FM_COL_COMBOBOX;
96 0 : case SID_FM_LISTBOX : return FM_COL_LISTBOX;
97 0 : case SID_FM_CHECKBOX : return FM_COL_CHECKBOX;
98 0 : case SID_FM_DATEFIELD : return FM_COL_DATEFIELD;
99 0 : case SID_FM_TIMEFIELD : return FM_COL_TIMEFIELD;
100 0 : case SID_FM_NUMERICFIELD : return FM_COL_NUMERICFIELD;
101 0 : case SID_FM_CURRENCYFIELD : return FM_COL_CURRENCYFIELD;
102 0 : case SID_FM_PATTERNFIELD : return FM_COL_PATTERNFIELD;
103 0 : case SID_FM_FORMATTEDFIELD : return FM_COL_FORMATTEDFIELD;
104 : }
105 0 : return OUString();
106 : }
107 :
108 0 : struct FmGridHeaderData
109 : {
110 : ODataAccessDescriptor aDropData;
111 : Point aDropPosPixel;
112 : sal_Int8 nDropAction;
113 : Reference< XInterface > xDroppedStatement;
114 : Reference< XInterface > xDroppedResultSet;
115 : };
116 :
117 : const sal_Int16 nChangeTypeOffset = 1000;
118 0 : void SetMenuItem(const ImageList& rList, sal_uInt16 nID, Menu* pMenu, Menu& rNewMenu, sal_Bool bDesignMode = sal_True, sal_Int16 nOffset = nChangeTypeOffset)
119 : {
120 0 : pMenu->SetItemImage(nID, rList.GetImage(nID));
121 0 : pMenu->EnableItem(nID, bDesignMode);
122 0 : rNewMenu.InsertItem(nID + nOffset, pMenu->GetItemText(nID));
123 0 : rNewMenu.SetItemImage(nID + nOffset, rList.GetImage(nID));
124 0 : rNewMenu.SetHelpId(nID + nOffset, pMenu->GetHelpId(nID));
125 0 : rNewMenu.EnableItem(nID + nOffset, bDesignMode);
126 0 : }
127 :
128 0 : FmGridHeader::FmGridHeader( BrowseBox* pParent, WinBits nWinBits)
129 : :EditBrowserHeader(pParent, nWinBits)
130 : ,DropTargetHelper(this)
131 0 : ,m_pImpl(new FmGridHeaderData)
132 : {
133 0 : }
134 :
135 0 : FmGridHeader::~FmGridHeader()
136 : {
137 0 : delete m_pImpl;
138 0 : }
139 :
140 0 : sal_uInt16 FmGridHeader::GetModelColumnPos(sal_uInt16 nId) const
141 : {
142 0 : return static_cast<FmGridControl*>(GetParent())->GetModelColumnPos(nId);
143 : }
144 :
145 0 : void FmGridHeader::notifyColumnSelect(sal_uInt16 nColumnId)
146 : {
147 0 : sal_uInt16 nPos = GetModelColumnPos(nColumnId);
148 0 : Reference< XIndexAccess > xColumns(((FmGridControl*)GetParent())->GetPeer()->getColumns(), UNO_QUERY);
149 0 : if ( nPos < xColumns->getCount() )
150 : {
151 0 : Reference< XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY);
152 0 : if ( xSelSupplier.is() )
153 : {
154 0 : Reference< XPropertySet > xColumn;
155 0 : xColumns->getByIndex(nPos) >>= xColumn;
156 0 : xSelSupplier->select(makeAny(xColumn));
157 0 : }
158 0 : }
159 0 : }
160 :
161 0 : void FmGridHeader::Select()
162 : {
163 0 : EditBrowserHeader::Select();
164 0 : notifyColumnSelect(GetCurItemId());
165 0 : }
166 :
167 0 : void FmGridHeader::RequestHelp( const HelpEvent& rHEvt )
168 : {
169 0 : sal_uInt16 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
170 0 : if ( nItemId )
171 : {
172 0 : if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
173 : {
174 0 : Rectangle aItemRect = GetItemRect( nItemId );
175 0 : Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
176 0 : aItemRect.Left() = aPt.X();
177 0 : aItemRect.Top() = aPt.Y();
178 0 : aPt = OutputToScreenPixel( aItemRect.BottomRight() );
179 0 : aItemRect.Right() = aPt.X();
180 0 : aItemRect.Bottom() = aPt.Y();
181 :
182 0 : sal_uInt16 nPos = GetModelColumnPos(nItemId);
183 0 : Reference< ::com::sun::star::container::XIndexContainer > xColumns(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
184 : try
185 : {
186 0 : Reference< ::com::sun::star::beans::XPropertySet > xColumn(xColumns->getByIndex(nPos),UNO_QUERY);
187 0 : OUString aHelpText;
188 0 : xColumn->getPropertyValue(FM_PROP_HELPTEXT) >>= aHelpText;
189 0 : if ( aHelpText.isEmpty() )
190 0 : xColumn->getPropertyValue(FM_PROP_DESCRIPTION) >>= aHelpText;
191 0 : if ( !aHelpText.isEmpty() )
192 : {
193 0 : if ( rHEvt.GetMode() & HELPMODE_BALLOON )
194 0 : Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aHelpText );
195 : else
196 0 : Help::ShowQuickHelp( this, aItemRect, aHelpText );
197 0 : return;
198 0 : }
199 : }
200 0 : catch(Exception&)
201 : {
202 0 : return;
203 0 : }
204 : }
205 : }
206 0 : EditBrowserHeader::RequestHelp( rHEvt );
207 : }
208 :
209 0 : sal_Int8 FmGridHeader::AcceptDrop( const AcceptDropEvent& rEvt )
210 : {
211 : // drop allowed in design mode only
212 0 : if (!static_cast<FmGridControl*>(GetParent())->IsDesignMode())
213 0 : return DND_ACTION_NONE;
214 :
215 : // search for recognized formats
216 0 : const DataFlavorExVector& rFlavors = GetDataFlavorExVector();
217 0 : if (OColumnTransferable::canExtractColumnDescriptor(rFlavors, CTF_COLUMN_DESCRIPTOR | CTF_FIELD_DESCRIPTOR))
218 0 : return rEvt.mnAction;
219 :
220 0 : return DND_ACTION_NONE;
221 : }
222 :
223 0 : sal_Int8 FmGridHeader::ExecuteDrop( const ExecuteDropEvent& _rEvt )
224 : {
225 0 : if (!static_cast<FmGridControl*>(GetParent())->IsDesignMode())
226 0 : return DND_ACTION_NONE;
227 :
228 0 : TransferableDataHelper aDroppedData(_rEvt.maDropEvent.Transferable);
229 :
230 : // check the formats
231 0 : sal_Bool bColumnDescriptor = OColumnTransferable::canExtractColumnDescriptor(aDroppedData.GetDataFlavorExVector(), CTF_COLUMN_DESCRIPTOR);
232 0 : sal_Bool bFieldDescriptor = OColumnTransferable::canExtractColumnDescriptor(aDroppedData.GetDataFlavorExVector(), CTF_FIELD_DESCRIPTOR);
233 0 : if (!bColumnDescriptor && !bFieldDescriptor)
234 : {
235 : OSL_FAIL("FmGridHeader::ExecuteDrop: should never have reached this (no extractable format)!");
236 0 : return DND_ACTION_NONE;
237 : }
238 :
239 : // extract the descriptor
240 0 : OUString sDatasouce, sCommand, sFieldName,sDatabaseLocation,sConnnectionResource;
241 0 : sal_Int32 nCommandType = CommandType::COMMAND;
242 0 : Reference< XPreparedStatement > xStatement;
243 0 : Reference< XResultSet > xResultSet;
244 0 : Reference< XPropertySet > xField;
245 0 : Reference< XConnection > xConnection;
246 :
247 0 : ODataAccessDescriptor aColumn = OColumnTransferable::extractColumnDescriptor(aDroppedData);
248 0 : if (aColumn.has(daDataSource)) aColumn[daDataSource] >>= sDatasouce;
249 0 : if (aColumn.has(daDatabaseLocation)) aColumn[daDatabaseLocation] >>= sDatabaseLocation;
250 0 : if (aColumn.has(daConnectionResource)) aColumn[daConnectionResource] >>= sConnnectionResource;
251 0 : if (aColumn.has(daCommand)) aColumn[daCommand] >>= sCommand;
252 0 : if (aColumn.has(daCommandType)) aColumn[daCommandType] >>= nCommandType;
253 0 : if (aColumn.has(daColumnName)) aColumn[daColumnName] >>= sFieldName;
254 0 : if (aColumn.has(daColumnObject))aColumn[daColumnObject] >>= xField;
255 0 : if (aColumn.has(daConnection)) aColumn[daConnection] >>= xConnection;
256 :
257 0 : if ( sFieldName.isEmpty()
258 0 : || sCommand.isEmpty()
259 0 : || ( sDatasouce.isEmpty()
260 0 : && sDatabaseLocation.isEmpty()
261 0 : && !xConnection.is()
262 : )
263 : )
264 : {
265 : OSL_FAIL( "FmGridHeader::ExecuteDrop: somebody started a nonsense drag operation!!" );
266 0 : return DND_ACTION_NONE;
267 : }
268 :
269 : try
270 : {
271 : // need a connection
272 0 : if (!xConnection.is())
273 : { // the transferable did not contain the connection -> build an own one
274 : try
275 : {
276 0 : OUString sSignificantSource( sDatasouce.isEmpty() ? sDatabaseLocation : sDatasouce );
277 0 : xConnection = OStaticDataAccessTools().getConnection_withFeedback(sSignificantSource, OUString(), OUString(),
278 0 : static_cast<FmGridControl*>(GetParent())->getContext() );
279 : }
280 0 : catch(NoSuchElementException&)
281 : { // allowed, means sDatasouce isn't a valid data source name ....
282 : }
283 0 : catch(Exception&)
284 : {
285 : OSL_FAIL("FmGridHeader::ExecuteDrop: could not retrieve the database access object !");
286 : }
287 :
288 0 : if (!xConnection.is())
289 : {
290 : OSL_FAIL("FmGridHeader::ExecuteDrop: could not retrieve the database access object !");
291 0 : return DND_ACTION_NONE;
292 : }
293 : }
294 :
295 : // try to obtain the column object
296 0 : if (!xField.is())
297 : {
298 : #ifdef DBG_UTIL
299 : Reference< XServiceInfo > xServiceInfo(xConnection, UNO_QUERY);
300 : DBG_ASSERT(xServiceInfo.is() && xServiceInfo->supportsService(SRV_SDB_CONNECTION), "FmGridHeader::ExecuteDrop: invalid connection (no database access connection !)");
301 : #endif
302 :
303 0 : Reference< XNameAccess > xFields;
304 0 : switch (nCommandType)
305 : {
306 : case CommandType::TABLE:
307 : {
308 0 : Reference< XTablesSupplier > xSupplyTables(xConnection, UNO_QUERY);
309 0 : Reference< XColumnsSupplier > xSupplyColumns;
310 0 : xSupplyTables->getTables()->getByName(sCommand) >>= xSupplyColumns;
311 0 : xFields = xSupplyColumns->getColumns();
312 : }
313 0 : break;
314 : case CommandType::QUERY:
315 : {
316 0 : Reference< XQueriesSupplier > xSupplyQueries(xConnection, UNO_QUERY);
317 0 : Reference< XColumnsSupplier > xSupplyColumns;
318 0 : xSupplyQueries->getQueries()->getByName(sCommand) >>= xSupplyColumns;
319 0 : xFields = xSupplyColumns->getColumns();
320 : }
321 0 : break;
322 : default:
323 : {
324 0 : xStatement = xConnection->prepareStatement(sCommand);
325 : // not interested in any results
326 :
327 0 : Reference< XPropertySet > xStatProps(xStatement,UNO_QUERY);
328 0 : xStatProps->setPropertyValue("MaxRows", makeAny(sal_Int32(0)));
329 :
330 0 : xResultSet = xStatement->executeQuery();
331 0 : Reference< XColumnsSupplier > xSupplyCols(xResultSet, UNO_QUERY);
332 0 : if (xSupplyCols.is())
333 0 : xFields = xSupplyCols->getColumns();
334 : }
335 : }
336 :
337 0 : if (xFields.is() && xFields->hasByName(sFieldName))
338 0 : xFields->getByName(sFieldName) >>= xField;
339 :
340 0 : if (!xField.is())
341 : {
342 0 : ::comphelper::disposeComponent(xStatement);
343 0 : return DND_ACTION_NONE;
344 0 : }
345 : }
346 :
347 : // do the drop asynchronously
348 : // (85957 - UI actions within the drop are not allowed, but we want to open a popup menu)
349 0 : m_pImpl->aDropData = aColumn;
350 0 : m_pImpl->aDropData[daConnection] <<= xConnection;
351 0 : m_pImpl->aDropData[daColumnObject] <<= xField;
352 :
353 0 : m_pImpl->nDropAction = _rEvt.mnAction;
354 0 : m_pImpl->aDropPosPixel = _rEvt.maPosPixel;
355 0 : m_pImpl->xDroppedStatement = xStatement;
356 0 : m_pImpl->xDroppedResultSet = xResultSet;
357 :
358 0 : PostUserEvent(LINK(this, FmGridHeader, OnAsyncExecuteDrop));
359 : }
360 0 : catch (Exception&)
361 : {
362 : OSL_FAIL("FmGridHeader::ExecuteDrop: caught an exception while creatin' the column !");
363 0 : ::comphelper::disposeComponent(xStatement);
364 0 : return sal_False;
365 : }
366 :
367 0 : return DND_ACTION_LINK;
368 : }
369 :
370 0 : IMPL_LINK( FmGridHeader, OnAsyncExecuteDrop, void*, /*NOTINTERESTEDIN*/ )
371 : {
372 0 : OUString sCommand, sFieldName,sURL;
373 0 : sal_Int32 nCommandType = CommandType::COMMAND;
374 0 : Reference< XPropertySet > xField;
375 0 : Reference< XConnection > xConnection;
376 :
377 0 : OUString sDatasouce = m_pImpl->aDropData.getDataSource();
378 0 : if ( sDatasouce.isEmpty() && m_pImpl->aDropData.has(daConnectionResource) )
379 0 : m_pImpl->aDropData[daConnectionResource] >>= sURL;
380 0 : m_pImpl->aDropData[daCommand] >>= sCommand;
381 0 : m_pImpl->aDropData[daCommandType] >>= nCommandType;
382 0 : m_pImpl->aDropData[daColumnName] >>= sFieldName;
383 0 : m_pImpl->aDropData[daConnection] >>= xConnection;
384 0 : m_pImpl->aDropData[daColumnObject] >>= xField;
385 :
386 : try
387 : {
388 : // need number formats
389 0 : Reference< XNumberFormatsSupplier > xSupplier = OStaticDataAccessTools().getNumberFormats(xConnection, sal_True);
390 0 : Reference< XNumberFormats > xNumberFormats;
391 0 : if (xSupplier.is())
392 0 : xNumberFormats = xSupplier->getNumberFormats();
393 0 : if (!xNumberFormats.is())
394 : {
395 0 : ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
396 0 : ::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
397 0 : return 0L;
398 : }
399 :
400 : // Vom Feld werden nun zwei Informationen benoetigt:
401 : // a.) Name des Feldes fuer Label und ControlSource
402 : // b.) FormatKey, um festzustellen, welches Feld erzeugt werden soll
403 0 : sal_Int32 nDataType = 0;
404 0 : xField->getPropertyValue(FM_PROP_FIELDTYPE) >>= nDataType;
405 : // diese Datentypen koennen im Gridcontrol nicht verarbeitet werden
406 0 : switch (nDataType)
407 : {
408 : case DataType::BLOB:
409 : case DataType::LONGVARBINARY:
410 : case DataType::BINARY:
411 : case DataType::VARBINARY:
412 : case DataType::OTHER:
413 0 : ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
414 0 : ::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
415 0 : return 0L;
416 : }
417 :
418 : // Erstellen der Column
419 0 : Reference< XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
420 0 : Reference< XGridColumnFactory > xFactory(xCols, UNO_QUERY);
421 :
422 0 : sal_uInt16 nColId = GetItemId(m_pImpl->aDropPosPixel);
423 : // EinfuegePosition, immer vor der aktuellen Spalte
424 0 : sal_uInt16 nPos = GetModelColumnPos(nColId);
425 0 : Reference< XPropertySet > xCol, xSecondCol;
426 :
427 : // Create Column based on type, default textfield
428 0 : std::vector<sal_uInt16> aPossibleTypes;
429 0 : switch (nDataType)
430 : {
431 : case DataType::BIT:
432 : case DataType::BOOLEAN:
433 0 : aPossibleTypes.push_back(SID_FM_CHECKBOX);
434 0 : break;
435 : case DataType::TINYINT:
436 : case DataType::SMALLINT:
437 : case DataType::INTEGER:
438 0 : aPossibleTypes.push_back(SID_FM_NUMERICFIELD);
439 0 : aPossibleTypes.push_back(SID_FM_FORMATTEDFIELD);
440 0 : break;
441 : case DataType::REAL:
442 : case DataType::DOUBLE:
443 : case DataType::NUMERIC:
444 : case DataType::DECIMAL:
445 0 : aPossibleTypes.push_back(SID_FM_FORMATTEDFIELD);
446 0 : aPossibleTypes.push_back(SID_FM_NUMERICFIELD);
447 0 : break;
448 : case DataType::TIMESTAMP:
449 0 : aPossibleTypes.push_back(SID_FM_TWOFIELDS_DATE_N_TIME);
450 0 : aPossibleTypes.push_back(SID_FM_DATEFIELD);
451 0 : aPossibleTypes.push_back(SID_FM_TIMEFIELD);
452 0 : aPossibleTypes.push_back(SID_FM_FORMATTEDFIELD);
453 0 : break;
454 : case DataType::DATE:
455 0 : aPossibleTypes.push_back(SID_FM_DATEFIELD);
456 0 : aPossibleTypes.push_back(SID_FM_FORMATTEDFIELD);
457 0 : break;
458 : case DataType::TIME:
459 0 : aPossibleTypes.push_back(SID_FM_TIMEFIELD);
460 0 : aPossibleTypes.push_back(SID_FM_FORMATTEDFIELD);
461 0 : break;
462 : case DataType::CHAR:
463 : case DataType::VARCHAR:
464 : case DataType::LONGVARCHAR:
465 : default:
466 0 : aPossibleTypes.push_back(SID_FM_EDIT);
467 0 : aPossibleTypes.push_back(SID_FM_FORMATTEDFIELD);
468 0 : break;
469 : }
470 : // if it's a currency field, a a "currency field" option
471 : try
472 : {
473 0 : if ( ::comphelper::hasProperty(FM_PROP_ISCURRENCY, xField)
474 0 : && ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_ISCURRENCY)))
475 0 : aPossibleTypes.insert(aPossibleTypes.begin(), SID_FM_CURRENCYFIELD);
476 : }
477 0 : catch(Exception&)
478 : {
479 : OSL_FAIL("FmGridHeader::ExecuteDrop: Exception occurred!");
480 : }
481 :
482 0 : sal_Bool bDateNTimeCol = sal_False;
483 0 : if (!aPossibleTypes.empty())
484 : {
485 0 : sal_Int32 nPreferredType = aPossibleTypes[0];
486 0 : if ((m_pImpl->nDropAction == DND_ACTION_LINK) && (aPossibleTypes.size() > 1))
487 : {
488 0 : ImageList aImageList( SVX_RES(RID_SVXIMGLIST_FMEXPL) );
489 :
490 0 : PopupMenu aInsertMenu(SVX_RES(RID_SVXMNU_COLS));
491 0 : PopupMenu aTypeMenu;
492 0 : PopupMenu* pMenu = aInsertMenu.GetPopupMenu(SID_FM_INSERTCOL);
493 0 : for (std::vector<sal_uInt16>::const_iterator iter = aPossibleTypes.begin(); iter != aPossibleTypes.end(); ++iter)
494 0 : SetMenuItem(aImageList, *iter, pMenu, aTypeMenu, sal_True, 0);
495 0 : nPreferredType = aTypeMenu.Execute(this, m_pImpl->aDropPosPixel);
496 : }
497 :
498 0 : bDateNTimeCol = nPreferredType == SID_FM_TWOFIELDS_DATE_N_TIME;
499 0 : sal_uInt16 nColCount = bDateNTimeCol ? 2 : 1;
500 0 : OUString sFieldService;
501 0 : while (nColCount--)
502 : {
503 0 : if (bDateNTimeCol)
504 0 : nPreferredType = nColCount ? SID_FM_DATEFIELD : SID_FM_TIMEFIELD;
505 :
506 0 : sFieldService = FieldServiceFromId(nPreferredType);
507 0 : Reference< XPropertySet > xThisRoundCol;
508 0 : if ( !sFieldService.isEmpty() )
509 0 : xThisRoundCol = xFactory->createColumn(sFieldService);
510 0 : if (nColCount)
511 0 : xSecondCol = xThisRoundCol;
512 : else
513 0 : xCol = xThisRoundCol;
514 0 : }
515 : }
516 :
517 0 : if (!xCol.is() || (bDateNTimeCol && !xSecondCol.is()))
518 : {
519 0 : ::comphelper::disposeComponent(xCol); // in case only the creation of the second column failed
520 0 : ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
521 0 : ::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
522 0 : return 0L;
523 : }
524 :
525 0 : if (bDateNTimeCol)
526 : {
527 0 : OUString sTimePostfix(SVX_RESSTR(RID_STR_POSTFIX_TIME));
528 0 : xCol->setPropertyValue(FM_PROP_LABEL, makeAny( OUString( sFieldName + sTimePostfix ) ) );
529 :
530 0 : OUString sDatePostfix(SVX_RESSTR( RID_STR_POSTFIX_DATE));
531 0 : xSecondCol->setPropertyValue(FM_PROP_LABEL, makeAny( OUString( sFieldName + sDatePostfix ) ) );
532 : }
533 : else
534 0 : xCol->setPropertyValue(FM_PROP_LABEL, makeAny(sFieldName));
535 :
536 0 : FormControlFactory aControlFactory;
537 0 : aControlFactory.initializeControlModel( DocumentClassification::classifyHostDocument( xCols ), xCol );
538 0 : aControlFactory.initializeFieldDependentProperties( xField, xCol, xNumberFormats );
539 :
540 0 : xCol->setPropertyValue(FM_PROP_CONTROLSOURCE, makeAny(sFieldName));
541 0 : if ( xSecondCol.is() )
542 0 : xSecondCol->setPropertyValue(FM_PROP_CONTROLSOURCE, makeAny(sFieldName));
543 :
544 0 : if (bDateNTimeCol)
545 : {
546 0 : OUString sRealName,sPurePostfix;
547 :
548 : OUString aPostfix[] = {
549 0 : SVX_RESSTR(RID_STR_POSTFIX_DATE),
550 0 : SVX_RESSTR(RID_STR_POSTFIX_TIME)
551 0 : };
552 :
553 0 : for ( size_t i=0; i<2; ++i )
554 : {
555 0 : sPurePostfix = comphelper::string::stripStart(aPostfix[i], ' ');
556 0 : sPurePostfix = comphelper::string::stripStart(sPurePostfix, '(');
557 0 : sPurePostfix = comphelper::string::stripEnd(sPurePostfix, ')');
558 0 : sRealName = sFieldName;
559 0 : sRealName += "_";
560 0 : sRealName += sPurePostfix;
561 0 : if (i)
562 0 : xSecondCol->setPropertyValue(FM_PROP_NAME, makeAny(OUString(sRealName)));
563 : else
564 0 : xCol->setPropertyValue(FM_PROP_NAME, makeAny(OUString(sRealName)));
565 0 : }
566 : }
567 : else
568 0 : xCol->setPropertyValue(FM_PROP_NAME, makeAny(sFieldName));
569 :
570 : // jetzt einfuegen
571 0 : Any aElement;
572 0 : aElement <<= xCol;
573 0 : xCols->insertByIndex(nPos, aElement);
574 :
575 0 : if (bDateNTimeCol)
576 : {
577 0 : aElement <<= xSecondCol;
578 0 : xCols->insertByIndex(nPos == (sal_uInt16)-1 ? nPos : ++nPos, aElement);
579 : }
580 :
581 : // ist die component::Form an die Datenbankangebunden?
582 0 : Reference< XFormComponent > xFormCp(xCols, UNO_QUERY);
583 0 : Reference< XPropertySet > xForm(xFormCp->getParent(), UNO_QUERY);
584 0 : if (xForm.is())
585 : {
586 0 : if (::comphelper::getString(xForm->getPropertyValue(FM_PROP_DATASOURCE)).isEmpty())
587 : {
588 0 : if ( !sDatasouce.isEmpty() )
589 0 : xForm->setPropertyValue(FM_PROP_DATASOURCE, makeAny(sDatasouce));
590 : else
591 0 : xForm->setPropertyValue(FM_PROP_URL, makeAny(sURL));
592 : }
593 :
594 0 : if (::comphelper::getString(xForm->getPropertyValue(FM_PROP_COMMAND)).isEmpty())
595 : {
596 0 : xForm->setPropertyValue(FM_PROP_COMMAND, makeAny(sCommand));
597 0 : Any aCommandType;
598 0 : switch (nCommandType)
599 : {
600 : case CommandType::TABLE:
601 0 : aCommandType <<= (sal_Int32)CommandType::TABLE;
602 0 : break;
603 : case CommandType::QUERY:
604 0 : aCommandType <<= (sal_Int32)CommandType::QUERY;
605 0 : break;
606 : default:
607 0 : aCommandType <<= (sal_Int32)CommandType::COMMAND;
608 0 : xForm->setPropertyValue(FM_PROP_ESCAPE_PROCESSING, css::uno::Any(2 == nCommandType));
609 0 : break;
610 : }
611 0 : xForm->setPropertyValue(FM_PROP_COMMANDTYPE, aCommandType);
612 : }
613 0 : }
614 : }
615 0 : catch (Exception&)
616 : {
617 : OSL_FAIL("FmGridHeader::OnAsyncExecuteDrop: caught an exception while creatin' the column !");
618 0 : ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
619 0 : ::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
620 0 : return 0L;
621 : }
622 :
623 0 : ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
624 0 : ::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
625 0 : return 1L;
626 : }
627 :
628 0 : void FmGridHeader::PreExecuteColumnContextMenu(sal_uInt16 nColId, PopupMenu& rMenu)
629 : {
630 0 : sal_Bool bDesignMode = static_cast<FmGridControl*>(GetParent())->IsDesignMode();
631 :
632 0 : Reference< ::com::sun::star::container::XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
633 : // Aufbau des Insert Menues
634 : // mark the column if nColId != HEADERBAR_ITEM_NOTFOUND
635 0 : if(nColId > 0)
636 : {
637 0 : sal_uInt16 nPos2 = GetModelColumnPos(nColId);
638 :
639 0 : Reference< ::com::sun::star::container::XIndexContainer > xColumns(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
640 : Reference< ::com::sun::star::beans::XPropertySet> xColumn(
641 0 : xColumns->getByIndex(nPos2), css::uno::UNO_QUERY);
642 0 : Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY);
643 0 : if (xSelSupplier.is())
644 0 : xSelSupplier->select(makeAny(xColumn));
645 : }
646 :
647 : // EinfuegePosition, immer vor der aktuellen Spalte
648 0 : sal_uInt16 nPos = GetModelColumnPos(nColId);
649 0 : sal_Bool bMarked = nColId && static_cast<FmGridControl*>(GetParent())->isColumnMarked(nColId);
650 :
651 0 : ImageList aImageList( SVX_RES(RID_SVXIMGLIST_FMEXPL) );
652 0 : PopupMenu* pControlMenu = new PopupMenu;
653 :
654 0 : PopupMenu* pMenu = rMenu.GetPopupMenu(SID_FM_INSERTCOL);
655 0 : if (pMenu)
656 : {
657 0 : SetMenuItem(aImageList, SID_FM_EDIT, pMenu, *pControlMenu, bDesignMode);
658 0 : SetMenuItem(aImageList, SID_FM_CHECKBOX, pMenu, *pControlMenu, bDesignMode);
659 0 : SetMenuItem(aImageList, SID_FM_COMBOBOX, pMenu, *pControlMenu, bDesignMode);
660 0 : SetMenuItem(aImageList, SID_FM_LISTBOX, pMenu, *pControlMenu, bDesignMode);
661 0 : SetMenuItem(aImageList, SID_FM_DATEFIELD, pMenu, *pControlMenu, bDesignMode);
662 0 : SetMenuItem(aImageList, SID_FM_TIMEFIELD, pMenu, *pControlMenu, bDesignMode);
663 0 : SetMenuItem(aImageList, SID_FM_NUMERICFIELD, pMenu, *pControlMenu, bDesignMode);
664 0 : SetMenuItem(aImageList, SID_FM_CURRENCYFIELD, pMenu, *pControlMenu, bDesignMode);
665 0 : SetMenuItem(aImageList, SID_FM_PATTERNFIELD, pMenu, *pControlMenu, bDesignMode);
666 0 : SetMenuItem(aImageList, SID_FM_FORMATTEDFIELD, pMenu, *pControlMenu, bDesignMode);
667 : }
668 :
669 0 : if (pMenu && xCols.is() && nColId)
670 : {
671 : Reference< ::com::sun::star::beans::XPropertySet > xSet(
672 0 : xCols->getByIndex(nPos), css::uno::UNO_QUERY);
673 : sal_Int16 nClassId;
674 0 : xSet->getPropertyValue(FM_PROP_CLASSID) >>= nClassId;
675 :
676 0 : Reference< ::com::sun::star::io::XPersistObject > xServiceQuestion(xSet, UNO_QUERY);
677 0 : sal_Int32 nColType = xServiceQuestion.is() ? getColumnTypeByModelName(xServiceQuestion->getServiceName()) : 0;
678 0 : if (nColType == TYPE_TEXTFIELD)
679 : { // edit fields and formatted fields have the same service name, thus getColumnTypeByModelName returns TYPE_TEXTFIELD
680 : // in both cases. And as columns don't have an ::com::sun::star::lang::XServiceInfo interface, we have to distinguish both
681 : // types via the existence of special properties
682 0 : Reference< ::com::sun::star::beans::XPropertySet > xProps(xSet, UNO_QUERY);
683 0 : if (xProps.is())
684 : {
685 0 : Reference< ::com::sun::star::beans::XPropertySetInfo > xPropsInfo = xProps->getPropertySetInfo();
686 0 : if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(FM_PROP_FORMATSSUPPLIER))
687 0 : nColType = TYPE_FORMATTEDFIELD;
688 0 : }
689 : }
690 :
691 0 : pControlMenu->EnableItem(SID_FM_EDIT + nChangeTypeOffset, bDesignMode && (nColType != TYPE_TEXTFIELD));
692 0 : pControlMenu->EnableItem(SID_FM_COMBOBOX + nChangeTypeOffset, bDesignMode && (nColType != TYPE_COMBOBOX));
693 0 : pControlMenu->EnableItem(SID_FM_LISTBOX + nChangeTypeOffset, bDesignMode && (nColType != TYPE_LISTBOX));
694 0 : pControlMenu->EnableItem(SID_FM_CHECKBOX + nChangeTypeOffset, bDesignMode && (nColType != TYPE_CHECKBOX));
695 0 : pControlMenu->EnableItem(SID_FM_DATEFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_DATEFIELD));
696 0 : pControlMenu->EnableItem(SID_FM_NUMERICFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_NUMERICFIELD));
697 0 : pControlMenu->EnableItem(SID_FM_TIMEFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_TIMEFIELD));
698 0 : pControlMenu->EnableItem(SID_FM_CURRENCYFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_CURRENCYFIELD));
699 0 : pControlMenu->EnableItem(SID_FM_PATTERNFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_PATTERNFIELD));
700 0 : pControlMenu->EnableItem(SID_FM_FORMATTEDFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_FORMATTEDFIELD));
701 0 : rMenu.SetPopupMenu(SID_FM_CHANGECOL, pControlMenu);
702 : }
703 :
704 0 : rMenu.EnableItem(SID_FM_INSERTCOL, bDesignMode && xCols.is());
705 0 : rMenu.EnableItem(SID_FM_DELETECOL, bDesignMode && bMarked && xCols.is());
706 0 : rMenu.EnableItem(SID_FM_CHANGECOL, bDesignMode && bMarked && xCols.is());
707 0 : rMenu.EnableItem(SID_FM_SHOW_PROPERTY_BROWSER, bDesignMode && bMarked && xCols.is());
708 :
709 0 : PopupMenu* pShowColsMenu = rMenu.GetPopupMenu(SID_FM_SHOWCOLS);
710 0 : sal_uInt16 nHiddenCols = 0;
711 0 : if (pShowColsMenu)
712 : {
713 0 : if (xCols.is())
714 : {
715 : // check for hidden cols
716 0 : Reference< ::com::sun::star::beans::XPropertySet > xCurCol;
717 0 : Any aHidden,aName;
718 0 : for (sal_uInt16 i=0; i<xCols->getCount(); ++i)
719 : {
720 0 : xCurCol.set(xCols->getByIndex(i), css::uno::UNO_QUERY);
721 : DBG_ASSERT(xCurCol.is(), "FmGridHeader::PreExecuteColumnContextMenu : the Peer has invalid columns !");
722 0 : aHidden = xCurCol->getPropertyValue(FM_PROP_HIDDEN);
723 : DBG_ASSERT(aHidden.getValueType().getTypeClass() == TypeClass_BOOLEAN,
724 : "FmGridHeader::PreExecuteColumnContextMenu : the property 'hidden' should be boolean !");
725 0 : if (::comphelper::getBOOL(aHidden))
726 : {
727 : // put the column name into the 'show col' menu
728 0 : if (nHiddenCols < 16)
729 : { // (only the first 16 items to keep the menu rather small)
730 0 : aName = xCurCol->getPropertyValue(FM_PROP_LABEL);
731 : pShowColsMenu->InsertItem(nHiddenCols + 1, ::comphelper::getString(aName),
732 0 : 0, OString(), nHiddenCols);
733 : // the ID is arbitrary, but should be unique within the whole menu
734 : }
735 0 : ++nHiddenCols;
736 : }
737 0 : }
738 : }
739 0 : pShowColsMenu->EnableItem(SID_FM_SHOWCOLS_MORE, xCols.is() && (nHiddenCols > 16));
740 0 : pShowColsMenu->EnableItem(SID_FM_SHOWALLCOLS, xCols.is() && (nHiddenCols > 0));
741 : }
742 :
743 : // allow the 'hide column' item ?
744 0 : sal_Bool bAllowHide = bMarked; // a column is marked
745 0 : bAllowHide = bAllowHide || (!bDesignMode && (nPos != (sal_uInt16)-1)); // OR we are in alive mode and have hit a column
746 0 : bAllowHide = bAllowHide && xCols.is(); // AND we have a column container
747 0 : bAllowHide = bAllowHide && (xCols->getCount()-nHiddenCols > 1); // AND there are at least two visible columns
748 0 : rMenu.EnableItem(SID_FM_HIDECOL, bAllowHide);
749 :
750 0 : sal_Bool bChecked = sal_False;
751 0 : if (bMarked)
752 : {
753 :
754 0 : SfxViewFrame* pCurrentFrame = SfxViewFrame::Current();
755 0 : SfxItemState eState = SFX_ITEM_UNKNOWN;
756 : // ask the bindings of the current view frame (which should be the one we're residing in) for the state
757 0 : if (pCurrentFrame)
758 : {
759 0 : SfxPoolItem* pItem = NULL;
760 0 : eState = pCurrentFrame->GetBindings().QueryState(SID_FM_CTL_PROPERTIES, pItem);
761 :
762 0 : if (eState >= SFX_ITEM_AVAILABLE && pItem )
763 : {
764 0 : bChecked = pItem->ISA(SfxBoolItem) && ((SfxBoolItem*)pItem)->GetValue();
765 0 : rMenu.CheckItem(SID_FM_SHOW_PROPERTY_BROWSER,bChecked);
766 : }
767 0 : delete pItem;
768 : }
769 0 : }
770 0 : }
771 :
772 : enum InspectorAction { eOpenInspector, eCloseInspector, eUpdateInspector, eNone };
773 :
774 0 : void FmGridHeader::PostExecuteColumnContextMenu(sal_uInt16 nColId, const PopupMenu& rMenu, sal_uInt16 nExecutionResult)
775 : {
776 0 : Reference< ::com::sun::star::container::XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
777 0 : sal_uInt16 nPos = GetModelColumnPos(nColId);
778 :
779 : // remove and delet the menu we inserted in PreExecuteColumnContextMenu
780 0 : PopupMenu* pControlMenu = rMenu.GetPopupMenu(SID_FM_CHANGECOL);
781 0 : delete pControlMenu;
782 :
783 0 : OUString aFieldType;
784 0 : sal_Bool bReplace = sal_False;
785 0 : InspectorAction eInspectorAction = eNone;
786 0 : Reference< XPropertySet > xColumnToInspect;
787 0 : switch (nExecutionResult)
788 : {
789 : case SID_FM_DELETECOL:
790 : {
791 : Reference< XInterface > xCol(
792 0 : xCols->getByIndex(nPos), css::uno::UNO_QUERY);
793 0 : xCols->removeByIndex(nPos);
794 0 : ::comphelper::disposeComponent(xCol);
795 0 : } break;
796 : case SID_FM_SHOW_PROPERTY_BROWSER:
797 0 : eInspectorAction = rMenu.IsItemChecked( SID_FM_SHOW_PROPERTY_BROWSER ) ? eOpenInspector : eCloseInspector;
798 0 : xColumnToInspect.set( xCols->getByIndex( nPos ), UNO_QUERY );
799 0 : break;
800 : case SID_FM_EDIT + nChangeTypeOffset:
801 0 : bReplace = sal_True;
802 : case SID_FM_EDIT:
803 0 : aFieldType = FM_COL_TEXTFIELD;
804 0 : break;
805 : case SID_FM_COMBOBOX + nChangeTypeOffset:
806 0 : bReplace = sal_True;
807 : case SID_FM_COMBOBOX:
808 0 : aFieldType = FM_COL_COMBOBOX;
809 0 : break;
810 : case SID_FM_LISTBOX + nChangeTypeOffset:
811 0 : bReplace = sal_True;
812 : case SID_FM_LISTBOX:
813 0 : aFieldType = FM_COL_LISTBOX;
814 0 : break;
815 : case SID_FM_CHECKBOX + nChangeTypeOffset:
816 0 : bReplace = sal_True;
817 : case SID_FM_CHECKBOX:
818 0 : aFieldType = FM_COL_CHECKBOX;
819 0 : break;
820 : case SID_FM_DATEFIELD + nChangeTypeOffset:
821 0 : bReplace = sal_True;
822 : case SID_FM_DATEFIELD:
823 0 : aFieldType = FM_COL_DATEFIELD;
824 0 : break;
825 : case SID_FM_TIMEFIELD + nChangeTypeOffset:
826 0 : bReplace = sal_True;
827 : case SID_FM_TIMEFIELD:
828 0 : aFieldType = FM_COL_TIMEFIELD;
829 0 : break;
830 : case SID_FM_NUMERICFIELD + nChangeTypeOffset:
831 0 : bReplace = sal_True;
832 : case SID_FM_NUMERICFIELD:
833 0 : aFieldType = FM_COL_NUMERICFIELD;
834 0 : break;
835 : case SID_FM_CURRENCYFIELD + nChangeTypeOffset:
836 0 : bReplace = sal_True;
837 : case SID_FM_CURRENCYFIELD:
838 0 : aFieldType = FM_COL_CURRENCYFIELD;
839 0 : break;
840 : case SID_FM_PATTERNFIELD + nChangeTypeOffset:
841 0 : bReplace = sal_True;
842 : case SID_FM_PATTERNFIELD:
843 0 : aFieldType = FM_COL_PATTERNFIELD;
844 0 : break;
845 : case SID_FM_FORMATTEDFIELD + nChangeTypeOffset:
846 0 : bReplace = sal_True;
847 : case SID_FM_FORMATTEDFIELD:
848 0 : aFieldType = FM_COL_FORMATTEDFIELD;
849 0 : break;
850 : case SID_FM_HIDECOL:
851 : {
852 : Reference< ::com::sun::star::beans::XPropertySet > xCurCol(
853 0 : xCols->getByIndex(nPos), css::uno::UNO_QUERY);
854 0 : xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny((sal_Bool)sal_True));
855 : }
856 0 : break;
857 : case SID_FM_SHOWCOLS_MORE:
858 : {
859 0 : SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
860 0 : if(pFact)
861 : {
862 0 : AbstractFmShowColsDialog* pDlg = pFact->CreateFmShowColsDialog(NULL);
863 : DBG_ASSERT(pDlg, "Dialogdiet fail!");
864 0 : pDlg->SetColumns(xCols);
865 0 : pDlg->Execute();
866 0 : delete pDlg;
867 : }
868 :
869 : }
870 0 : break;
871 : case SID_FM_SHOWALLCOLS:
872 : {
873 : // just iterate through all the cols ...
874 0 : Reference< ::com::sun::star::beans::XPropertySet > xCurCol;
875 0 : for (sal_uInt16 i=0; i<xCols->getCount(); ++i)
876 : {
877 0 : xCurCol.set(xCols->getByIndex(i), css::uno::UNO_QUERY);
878 0 : xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny((sal_Bool)sal_False));
879 0 : }
880 : // TODO : there must be a more clever way to do this ....
881 : // with the above the view is updated after every single model update ...
882 : }
883 0 : break;
884 : default:
885 0 : if (nExecutionResult>0 && nExecutionResult<=16)
886 : { // it was a "show column/<colname>" command (there are at most 16 such items)
887 : // search the nExecutionResult'th hidden col
888 0 : Reference< ::com::sun::star::beans::XPropertySet > xCurCol;
889 0 : for (sal_uInt16 i=0; i<xCols->getCount() && nExecutionResult; ++i)
890 : {
891 0 : xCurCol.set(xCols->getByIndex(i), css::uno::UNO_QUERY);
892 0 : Any aHidden = xCurCol->getPropertyValue(FM_PROP_HIDDEN);
893 0 : if (::comphelper::getBOOL(aHidden))
894 0 : if (!--nExecutionResult)
895 : {
896 0 : xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny((sal_Bool)sal_False));
897 0 : break;
898 : }
899 0 : }
900 : }
901 0 : break;
902 : }
903 :
904 0 : if ( !aFieldType.isEmpty() )
905 : {
906 : try
907 : {
908 0 : Reference< XGridColumnFactory > xFactory( xCols, UNO_QUERY_THROW );
909 0 : Reference< XPropertySet > xNewCol( xFactory->createColumn( aFieldType ), UNO_SET_THROW );
910 :
911 0 : if ( bReplace )
912 : {
913 : // ein paar Properties hinueberretten
914 0 : Reference< XPropertySet > xReplaced( xCols->getByIndex( nPos ), UNO_QUERY );
915 :
916 : OStaticDataAccessTools().TransferFormComponentProperties(
917 0 : xReplaced, xNewCol, Application::GetSettings().GetUILanguageTag().getLocale() );
918 :
919 0 : xCols->replaceByIndex( nPos, makeAny( xNewCol ) );
920 0 : ::comphelper::disposeComponent( xReplaced );
921 :
922 0 : eInspectorAction = eUpdateInspector;
923 0 : xColumnToInspect = xNewCol;
924 : }
925 : else
926 : {
927 0 : FormControlFactory factory;
928 :
929 : OUString sLabel = factory.getDefaultUniqueName_ByComponentType(
930 0 : Reference< XNameAccess >( xCols, UNO_QUERY_THROW ), xNewCol );
931 0 : xNewCol->setPropertyValue( FM_PROP_LABEL, makeAny( sLabel ) );
932 0 : xNewCol->setPropertyValue( FM_PROP_NAME, makeAny( sLabel ) );
933 :
934 0 : factory.initializeControlModel( DocumentClassification::classifyHostDocument( xCols ), xNewCol );
935 :
936 0 : xCols->insertByIndex( nPos, makeAny( xNewCol ) );
937 0 : }
938 : }
939 0 : catch( const Exception& )
940 : {
941 : DBG_UNHANDLED_EXCEPTION();
942 : }
943 : }
944 :
945 0 : SfxViewFrame* pCurrentFrame = SfxViewFrame::Current();
946 : OSL_ENSURE( pCurrentFrame, "FmGridHeader::PostExecuteColumnContextMenu: no view frame -> no bindings -> no property browser!" );
947 0 : if ( pCurrentFrame )
948 : {
949 0 : if ( eInspectorAction == eUpdateInspector )
950 : {
951 0 : if ( !pCurrentFrame->HasChildWindow( SID_FM_SHOW_PROPERTIES ) )
952 0 : eInspectorAction = eNone;
953 : }
954 :
955 0 : if ( eInspectorAction != eNone )
956 : {
957 0 : FmInterfaceItem aIFaceItem( SID_FM_SHOW_PROPERTY_BROWSER, xColumnToInspect );
958 0 : SfxBoolItem aShowItem( SID_FM_SHOW_PROPERTIES, eInspectorAction == eCloseInspector ? sal_False : sal_True );
959 :
960 0 : pCurrentFrame->GetBindings().GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER, SFX_CALLMODE_ASYNCHRON,
961 0 : &aIFaceItem, &aShowItem, 0L );
962 : }
963 0 : }
964 0 : }
965 :
966 0 : void FmGridHeader::triggerColumnContextMenu( const ::Point& _rPreferredPos )
967 : {
968 : // the affected col
969 0 : sal_uInt16 nColId = GetItemId( _rPreferredPos );
970 :
971 : // the menu
972 0 : PopupMenu aContextMenu( SVX_RES( RID_SVXMNU_COLS ) );
973 :
974 : // let derivees modify the menu
975 0 : PreExecuteColumnContextMenu( nColId, aContextMenu );
976 0 : aContextMenu.RemoveDisabledEntries( true, true );
977 :
978 : // execute the menu
979 0 : sal_uInt16 nResult = aContextMenu.Execute( this, _rPreferredPos );
980 :
981 : // let derivees handle the result
982 0 : PostExecuteColumnContextMenu( nColId, aContextMenu, nResult );
983 0 : }
984 :
985 0 : void FmGridHeader::Command(const CommandEvent& rEvt)
986 : {
987 0 : switch (rEvt.GetCommand())
988 : {
989 : case COMMAND_CONTEXTMENU:
990 : {
991 0 : if (!rEvt.IsMouseEvent())
992 0 : return;
993 :
994 0 : triggerColumnContextMenu( rEvt.GetMousePosPixel() );
995 : }
996 0 : break;
997 : default:
998 0 : EditBrowserHeader::Command(rEvt);
999 : }
1000 : }
1001 :
1002 0 : FmGridControl::FmGridControl(
1003 : const Reference< ::com::sun::star::uno::XComponentContext >& _rxContext,
1004 : Window* pParent,
1005 : FmXGridPeer* _pPeer,
1006 : WinBits nBits)
1007 : :DbGridControl(_rxContext, pParent, nBits)
1008 : ,m_pPeer(_pPeer)
1009 : ,m_nCurrentSelectedColumn(-1)
1010 : ,m_nMarkedColumnId(BROWSER_INVALIDID)
1011 : ,m_bSelecting(false)
1012 0 : ,m_bInColumnMove(false)
1013 : {
1014 0 : EnableInteractiveRowHeight( );
1015 0 : }
1016 :
1017 0 : void FmGridControl::Command(const CommandEvent& _rEvt)
1018 : {
1019 0 : if ( COMMAND_CONTEXTMENU == _rEvt.GetCommand() )
1020 : {
1021 0 : FmGridHeader* pMyHeader = static_cast< FmGridHeader* >( GetHeaderBar() );
1022 0 : if ( pMyHeader && !_rEvt.IsMouseEvent() )
1023 : { // context menu requested by keyboard
1024 0 : if ( 1 == GetSelectColumnCount() || IsDesignMode() )
1025 : {
1026 : sal_uInt16 nSelId = GetColumnId(
1027 0 : sal::static_int_cast< sal_uInt16 >( FirstSelectedColumn() ) );
1028 0 : ::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, false ) );
1029 :
1030 0 : Point aRelativePos( pMyHeader->ScreenToOutputPixel( OutputToScreenPixel( aColRect.TopCenter() ) ) );
1031 0 : pMyHeader->triggerColumnContextMenu( aRelativePos, FmGridHeader::AccessControl() );
1032 :
1033 : // handled
1034 0 : return;
1035 : }
1036 : }
1037 : }
1038 :
1039 0 : DbGridControl::Command( _rEvt );
1040 : }
1041 :
1042 : // ::com::sun::star::beans::XPropertyChangeListener
1043 0 : void FmGridControl::propertyChange(const ::com::sun::star::beans::PropertyChangeEvent& evt)
1044 : {
1045 0 : if (evt.PropertyName == FM_PROP_ROWCOUNT)
1046 : {
1047 : // if we're not in the main thread call AdjustRows asynchronously
1048 0 : implAdjustInSolarThread(true);
1049 0 : return;
1050 : }
1051 :
1052 0 : const DbGridRowRef& xRow = GetCurrentRow();
1053 : // waehrend Positionierung wird kein abgleich der Properties vorgenommen
1054 0 : Reference<XPropertySet> xSet(evt.Source,UNO_QUERY);
1055 0 : if (xRow.Is() && (::cppu::any2bool(xSet->getPropertyValue(FM_PROP_ISNEW))|| CompareBookmark(getDataSource()->getBookmark(), xRow->GetBookmark())))
1056 : {
1057 0 : if (evt.PropertyName == FM_PROP_ISMODIFIED)
1058 : {
1059 : // modified or clean ?
1060 0 : GridRowStatus eStatus = ::comphelper::getBOOL(evt.NewValue) ? GRS_MODIFIED : GRS_CLEAN;
1061 0 : if (eStatus != xRow->GetStatus())
1062 : {
1063 0 : xRow->SetStatus(eStatus);
1064 0 : SolarMutexGuard aGuard;
1065 0 : RowModified(GetCurrentPos());
1066 : }
1067 : }
1068 0 : }
1069 : }
1070 :
1071 0 : void FmGridControl::SetDesignMode(bool bMode)
1072 : {
1073 0 : bool bOldMode = IsDesignMode();
1074 0 : DbGridControl::SetDesignMode(bMode);
1075 0 : if (bOldMode != bMode)
1076 : {
1077 0 : if (!bMode)
1078 : {
1079 : // selection aufheben
1080 0 : markColumn(USHRT_MAX);
1081 : }
1082 : else
1083 : {
1084 0 : Reference< ::com::sun::star::container::XIndexContainer > xColumns(GetPeer()->getColumns());
1085 0 : Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY);
1086 0 : if (xSelSupplier.is())
1087 : {
1088 0 : Any aSelection = xSelSupplier->getSelection();
1089 0 : Reference< ::com::sun::star::beans::XPropertySet > xColumn;
1090 0 : if (aSelection.getValueType().getTypeClass() == TypeClass_INTERFACE)
1091 0 : xColumn.set(aSelection, css::uno::UNO_QUERY);
1092 0 : Reference< XInterface > xCurrent;
1093 0 : for (sal_uInt16 i=0; i<xColumns->getCount(); ++i)
1094 : {
1095 0 : xCurrent.set(xColumns->getByIndex(i), css::uno::UNO_QUERY);
1096 0 : if (xCurrent == xColumn)
1097 : {
1098 0 : markColumn(GetColumnIdFromModelPos(i));
1099 0 : break;
1100 : }
1101 0 : }
1102 0 : }
1103 : }
1104 : }
1105 0 : }
1106 :
1107 0 : void FmGridControl::DeleteSelectedRows()
1108 : {
1109 0 : if (!m_pSeekCursor)
1110 0 : return;
1111 :
1112 : // how many rows are selected?
1113 0 : sal_Int32 nSelectedRows = GetSelectRowCount();
1114 :
1115 : // the current line should be deleted but it is currently in edit mode
1116 0 : if ( IsCurrentAppending() )
1117 0 : return;
1118 : // is the insert row selected
1119 0 : if (GetEmptyRow().Is() && IsRowSelected(GetRowCount() - 1))
1120 0 : nSelectedRows -= 1;
1121 :
1122 : // nothing to do
1123 0 : if (nSelectedRows <= 0)
1124 0 : return;
1125 :
1126 : // try to confirm the delete
1127 0 : Reference< ::com::sun::star::frame::XDispatchProvider > xDispatcher = (::com::sun::star::frame::XDispatchProvider*)GetPeer();
1128 0 : if (xDispatcher.is())
1129 : {
1130 0 : ::com::sun::star::util::URL aUrl;
1131 0 : aUrl.Complete = FMURL_CONFIRM_DELETION;
1132 : // #100312# ------------
1133 : Reference< ::com::sun::star::util::XURLTransformer > xTransformer(
1134 0 : ::com::sun::star::util::URLTransformer::create(::comphelper::getProcessComponentContext()) );
1135 0 : xTransformer->parseStrict( aUrl );
1136 :
1137 0 : Reference< ::com::sun::star::frame::XDispatch > xDispatch = xDispatcher->queryDispatch(aUrl, OUString(), 0);
1138 0 : Reference< ::com::sun::star::form::XConfirmDeleteListener > xConfirm(xDispatch, UNO_QUERY);
1139 0 : if (xConfirm.is())
1140 : {
1141 0 : ::com::sun::star::sdb::RowChangeEvent aEvent;
1142 0 : aEvent.Source = (Reference< XInterface > )(*getDataSource());
1143 0 : aEvent.Rows = nSelectedRows;
1144 0 : aEvent.Action = ::com::sun::star::sdb::RowChangeAction::DELETE;
1145 0 : if (!xConfirm->confirmDelete(aEvent))
1146 0 : return;
1147 0 : }
1148 : }
1149 :
1150 0 : const MultiSelection* pRowSelection = GetSelection();
1151 0 : if ( pRowSelection && pRowSelection->IsAllSelected() )
1152 : {
1153 0 : BeginCursorAction();
1154 0 : CursorWrapper* pCursor = getDataSource();
1155 0 : Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*pCursor, UNO_QUERY);
1156 : try
1157 : {
1158 0 : pCursor->beforeFirst();
1159 0 : while( pCursor->next() )
1160 0 : xUpdateCursor->deleteRow();
1161 :
1162 0 : SetUpdateMode(false);
1163 0 : SetNoSelection();
1164 :
1165 0 : xUpdateCursor->moveToInsertRow();
1166 : }
1167 0 : catch(const Exception&)
1168 : {
1169 : OSL_FAIL("Exception caught while deleting rows!");
1170 : }
1171 : // An den DatenCursor anpassen
1172 0 : AdjustDataSource(true);
1173 0 : EndCursorAction();
1174 0 : SetUpdateMode(true);
1175 : }
1176 : else
1177 : {
1178 0 : Reference< ::com::sun::star::sdbcx::XDeleteRows > xDeleteThem((Reference< XInterface >)*getDataSource(), UNO_QUERY);
1179 :
1180 : // colect the bookmarks of the selected rows
1181 0 : Sequence < Any> aBookmarks = getSelectionBookmarks();
1182 :
1183 : // determine the next row to position after deletion
1184 0 : Any aBookmark;
1185 0 : sal_Bool bNewPos = sal_False;
1186 : // if the current row isn't selected we take the row as row after deletion
1187 : OSL_ENSURE( GetCurrentRow().Is(), "FmGridControl::DeleteSelectedRows: no current row here?" );
1188 : // crash reports suggest it can happen we don't have a current row - how?
1189 : // #154303# / 2008-04-23 / frank.schoenheit@sun.com
1190 0 : if ( !IsRowSelected( GetCurrentPos() ) && !IsCurrentAppending() && GetCurrentRow().Is() )
1191 : {
1192 0 : aBookmark = GetCurrentRow()->GetBookmark();
1193 0 : bNewPos = sal_True;
1194 : }
1195 : else
1196 : {
1197 : // we look for the first row after the selected block for selection
1198 0 : long nIdx = LastSelectedRow() + 1;
1199 0 : if (nIdx < GetRowCount() - 1)
1200 : {
1201 : // there is a next row to position on
1202 0 : if (SeekCursor(nIdx))
1203 : {
1204 0 : GetSeekRow()->SetState(m_pSeekCursor, true);
1205 :
1206 0 : bNewPos = sal_True;
1207 : // if it's not the row for inserting we keep the bookmark
1208 0 : if (!IsInsertionRow(nIdx))
1209 0 : aBookmark = m_pSeekCursor->getBookmark();
1210 : }
1211 : }
1212 : else
1213 : {
1214 : // we look for the first row before the selected block for selection after deletion
1215 0 : nIdx = FirstSelectedRow() - 1;
1216 0 : if (nIdx >= 0 && SeekCursor(nIdx))
1217 : {
1218 0 : GetSeekRow()->SetState(m_pSeekCursor, true);
1219 :
1220 0 : bNewPos = sal_True;
1221 0 : aBookmark = m_pSeekCursor->getBookmark();
1222 : }
1223 : }
1224 : }
1225 :
1226 : // Sind alle Zeilen Selectiert
1227 : // Zweite bedingung falls keine einguegeZeile existiert
1228 0 : sal_Bool bAllSelected = GetTotalCount() == nSelectedRows || GetRowCount() == nSelectedRows;
1229 :
1230 0 : BeginCursorAction();
1231 :
1232 : // now delete the row
1233 0 : Sequence<sal_Int32> aDeletedRows;
1234 0 : SetUpdateMode( false );
1235 : try
1236 : {
1237 0 : aDeletedRows = xDeleteThem->deleteRows(aBookmarks);
1238 : }
1239 0 : catch(SQLException&)
1240 : {
1241 : }
1242 0 : SetUpdateMode( true );
1243 :
1244 : // how many rows are deleted?
1245 0 : sal_Int32 nDeletedRows = 0;
1246 0 : const sal_Int32* pSuccess = aDeletedRows.getConstArray();
1247 0 : for (sal_Int32 i = 0; i < aDeletedRows.getLength(); i++)
1248 : {
1249 0 : if (pSuccess[i])
1250 0 : ++nDeletedRows;
1251 : }
1252 :
1253 : // sind Zeilen geloescht worden?
1254 0 : if (nDeletedRows)
1255 : {
1256 0 : SetUpdateMode(false);
1257 0 : SetNoSelection();
1258 : try
1259 : {
1260 : // did we delete all the rows than try to move to the next possible row
1261 0 : if (nDeletedRows == aDeletedRows.getLength())
1262 : {
1263 : // there exists a new position to move on
1264 0 : if (bNewPos)
1265 : {
1266 0 : if (aBookmark.hasValue())
1267 0 : getDataSource()->moveToBookmark(aBookmark);
1268 : // no valid bookmark so move to the insert row
1269 : else
1270 : {
1271 0 : Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY);
1272 0 : xUpdateCursor->moveToInsertRow();
1273 : }
1274 : }
1275 : else
1276 : {
1277 0 : Reference< ::com::sun::star::beans::XPropertySet > xSet((Reference< XInterface >)*m_pDataCursor, UNO_QUERY);
1278 :
1279 0 : sal_Int32 nRecordCount(0);
1280 0 : xSet->getPropertyValue(FM_PROP_ROWCOUNT) >>= nRecordCount;
1281 0 : if ( m_pDataCursor->rowDeleted() )
1282 0 : --nRecordCount;
1283 :
1284 : // there are no rows left and we have an insert row
1285 0 : if (!nRecordCount && GetEmptyRow().Is())
1286 : {
1287 0 : Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY);
1288 0 : xUpdateCursor->moveToInsertRow();
1289 : }
1290 0 : else if (nRecordCount)
1291 : // move to the first row
1292 0 : getDataSource()->first();
1293 : }
1294 : }
1295 : // not all the rows where deleted, so move to the first row which remained in the resultset
1296 : else
1297 : {
1298 0 : for (sal_Int32 i = 0; i < aDeletedRows.getLength(); i++)
1299 : {
1300 0 : if (!pSuccess[i])
1301 : {
1302 0 : getDataSource()->moveToBookmark(aBookmarks.getConstArray()[i]);
1303 0 : break;
1304 : }
1305 : }
1306 : }
1307 : }
1308 0 : catch(const Exception&)
1309 : {
1310 : try
1311 : {
1312 : // positioning went wrong so try to move to the first row
1313 0 : getDataSource()->first();
1314 : }
1315 0 : catch(const Exception&)
1316 : {
1317 : }
1318 : }
1319 :
1320 : // An den DatenCursor anpassen
1321 0 : AdjustDataSource(true);
1322 :
1323 : // es konnten nicht alle Zeilen geloescht werden
1324 : // da nie nicht geloeschten wieder selektieren
1325 0 : if (nDeletedRows < nSelectedRows)
1326 : {
1327 : // waren alle selektiert
1328 0 : if (bAllSelected)
1329 : {
1330 0 : SelectAll();
1331 0 : if (IsInsertionRow(GetRowCount() - 1)) // einfuegeZeile nicht
1332 0 : SelectRow(GetRowCount() - 1, false);
1333 : }
1334 : else
1335 : {
1336 : // select the remaining rows
1337 0 : for (sal_Int32 i = 0; i < aDeletedRows.getLength(); i++)
1338 : {
1339 : try
1340 : {
1341 0 : if (!pSuccess[i])
1342 : {
1343 0 : m_pSeekCursor->moveToBookmark(m_pDataCursor->getBookmark());
1344 0 : SetSeekPos(m_pSeekCursor->getRow() - 1);
1345 0 : SelectRow(GetSeekPos());
1346 : }
1347 : }
1348 0 : catch(const Exception&)
1349 : {
1350 : // keep the seekpos in all cases
1351 0 : SetSeekPos(m_pSeekCursor->getRow() - 1);
1352 : }
1353 : }
1354 : }
1355 : }
1356 :
1357 0 : EndCursorAction();
1358 0 : SetUpdateMode(true);
1359 : }
1360 : else // Zeile konnte nicht geloescht werden
1361 : {
1362 0 : EndCursorAction();
1363 : try
1364 : {
1365 : // currentrow is the insert row?
1366 0 : if (!IsCurrentAppending())
1367 0 : getDataSource()->refreshRow();
1368 : }
1369 0 : catch(const Exception&)
1370 : {
1371 : }
1372 0 : }
1373 : }
1374 :
1375 : // if there is no selection anymore we can start editing
1376 0 : if (!GetSelectRowCount())
1377 0 : ActivateCell();
1378 : }
1379 :
1380 : // XCurrentRecordListener
1381 0 : void FmGridControl::positioned(const ::com::sun::star::lang::EventObject& /*rEvent*/)
1382 : {
1383 : SAL_INFO("svx.fmcomp", "FmGridControl::positioned");
1384 : // position on the data source (force it to be done in the main thread)
1385 0 : implAdjustInSolarThread(false);
1386 0 : }
1387 :
1388 0 : bool FmGridControl::commit()
1389 : {
1390 : // Commit nur ausfuehren, wenn nicht bereits ein Update vom ::com::sun::star::form::component::GridControl ausgefuehrt
1391 : // wird
1392 0 : if (!IsUpdating())
1393 : {
1394 0 : if (Controller().Is() && Controller()->IsModified())
1395 : {
1396 0 : if (!SaveModified())
1397 0 : return false;
1398 : }
1399 : }
1400 0 : return true;
1401 : }
1402 :
1403 0 : void FmGridControl::inserted(const ::com::sun::star::lang::EventObject& /*rEvent*/)
1404 : {
1405 0 : const DbGridRowRef& xRow = GetCurrentRow();
1406 0 : if (!xRow.Is())
1407 0 : return;
1408 :
1409 : // Zeile ist eingefuegt worden, dann den status und mode zuruecksetzen
1410 0 : xRow->SetState(m_pDataCursor, false);
1411 0 : xRow->SetNew(false);
1412 :
1413 : }
1414 :
1415 0 : BrowserHeader* FmGridControl::imp_CreateHeaderBar(BrowseBox* pParent)
1416 : {
1417 : DBG_ASSERT( pParent == this, "FmGridControl::imp_CreateHeaderBar: parent?" );
1418 0 : return new FmGridHeader( pParent );
1419 : }
1420 :
1421 0 : void FmGridControl::markColumn(sal_uInt16 nId)
1422 : {
1423 0 : if (GetHeaderBar() && m_nMarkedColumnId != nId)
1424 : {
1425 : // deselektieren
1426 0 : if (m_nMarkedColumnId != BROWSER_INVALIDID)
1427 : {
1428 0 : HeaderBarItemBits aBits = GetHeaderBar()->GetItemBits(m_nMarkedColumnId) & ~HIB_FLAT;
1429 0 : GetHeaderBar()->SetItemBits(m_nMarkedColumnId, aBits);
1430 : }
1431 :
1432 :
1433 0 : if (nId != BROWSER_INVALIDID)
1434 : {
1435 0 : HeaderBarItemBits aBits = GetHeaderBar()->GetItemBits(nId) | HIB_FLAT;
1436 0 : GetHeaderBar()->SetItemBits(nId, aBits);
1437 : }
1438 0 : m_nMarkedColumnId = nId;
1439 : }
1440 0 : }
1441 :
1442 0 : bool FmGridControl::isColumnMarked(sal_uInt16 nId) const
1443 : {
1444 0 : return m_nMarkedColumnId == nId;
1445 : }
1446 :
1447 0 : long FmGridControl::QueryMinimumRowHeight()
1448 : {
1449 0 : long nMinimalLogicHeight = 20; // 0.2 cm
1450 0 : long nMinimalPixelHeight = LogicToPixel( Point( 0, nMinimalLogicHeight ), MAP_10TH_MM ).Y();
1451 0 : return CalcZoom( nMinimalPixelHeight );
1452 : }
1453 :
1454 0 : void FmGridControl::RowHeightChanged()
1455 : {
1456 0 : DbGridControl::RowHeightChanged();
1457 :
1458 0 : Reference< XPropertySet > xModel( GetPeer()->getColumns(), UNO_QUERY );
1459 : DBG_ASSERT( xModel.is(), "FmGridControl::RowHeightChanged: no model!" );
1460 0 : if ( xModel.is() )
1461 : {
1462 : try
1463 : {
1464 0 : sal_Int32 nUnzoomedPixelHeight = CalcReverseZoom( GetDataRowHeight() );
1465 0 : Any aProperty = makeAny( (sal_Int32)PixelToLogic( Point( 0, nUnzoomedPixelHeight ), MAP_10TH_MM ).Y() );
1466 0 : xModel->setPropertyValue( FM_PROP_ROWHEIGHT, aProperty );
1467 : }
1468 0 : catch( const Exception& )
1469 : {
1470 : OSL_FAIL( "FmGridControl::RowHeightChanged: caught an exception!" );
1471 : }
1472 0 : }
1473 0 : }
1474 :
1475 0 : void FmGridControl::ColumnResized(sal_uInt16 nId)
1476 : {
1477 0 : DbGridControl::ColumnResized(nId);
1478 :
1479 : // Wert ans model uebergeben
1480 0 : DbGridColumn* pCol = DbGridControl::GetColumns().at( GetModelColumnPos(nId) );
1481 0 : Reference< ::com::sun::star::beans::XPropertySet > xColModel(pCol->getModel());
1482 0 : if (xColModel.is())
1483 : {
1484 0 : Any aWidth;
1485 0 : sal_Int32 nColumnWidth = GetColumnWidth(nId);
1486 0 : nColumnWidth = CalcReverseZoom(nColumnWidth);
1487 : // Umrechnen in 10THMM
1488 0 : aWidth <<= (sal_Int32)PixelToLogic(Point(nColumnWidth,0),MAP_10TH_MM).X();
1489 0 : xColModel->setPropertyValue(FM_PROP_WIDTH, aWidth);
1490 0 : }
1491 0 : }
1492 :
1493 0 : void FmGridControl::CellModified()
1494 : {
1495 0 : DbGridControl::CellModified();
1496 0 : GetPeer()->CellModified();
1497 0 : }
1498 :
1499 0 : void FmGridControl::BeginCursorAction()
1500 : {
1501 0 : DbGridControl::BeginCursorAction();
1502 0 : m_pPeer->stopCursorListening();
1503 0 : }
1504 :
1505 0 : void FmGridControl::EndCursorAction()
1506 : {
1507 0 : m_pPeer->startCursorListening();
1508 0 : DbGridControl::EndCursorAction();
1509 0 : }
1510 :
1511 0 : void FmGridControl::ColumnMoved(sal_uInt16 nId)
1512 : {
1513 0 : m_bInColumnMove = true;
1514 :
1515 0 : DbGridControl::ColumnMoved(nId);
1516 0 : Reference< ::com::sun::star::container::XIndexContainer > xColumns(GetPeer()->getColumns());
1517 :
1518 0 : if (xColumns.is())
1519 : {
1520 : // suchen der Spalte und verschieben im Model
1521 : // ColumnPos holen
1522 0 : DbGridColumn* pCol = DbGridControl::GetColumns().at( GetModelColumnPos(nId) );
1523 0 : Reference< ::com::sun::star::beans::XPropertySet > xCol;
1524 :
1525 : // Einfuegen muss sich an den Column Positionen orientieren
1526 : sal_Int32 i;
1527 0 : Reference< XInterface > xCurrent;
1528 0 : for (i = 0; !xCol.is() && i < xColumns->getCount(); i++)
1529 : {
1530 0 : xCurrent.set(xColumns->getByIndex(i), css::uno::UNO_QUERY);
1531 0 : if (xCurrent == pCol->getModel())
1532 : {
1533 0 : xCol = pCol->getModel();
1534 0 : break;
1535 : }
1536 : }
1537 :
1538 : DBG_ASSERT(i < xColumns->getCount(), "Falscher ::com::sun::star::sdbcx::Index");
1539 0 : xColumns->removeByIndex(i);
1540 0 : Any aElement;
1541 0 : aElement <<= xCol;
1542 0 : xColumns->insertByIndex(GetModelColumnPos(nId), aElement);
1543 0 : pCol->setModel(xCol);
1544 : // if the column which is shown here is selected ...
1545 0 : if ( isColumnSelected(nId,pCol) )
1546 0 : markColumn(nId); // ... -> mark it
1547 : }
1548 :
1549 0 : m_bInColumnMove = false;
1550 0 : }
1551 :
1552 0 : void FmGridControl::InitColumnsByModels(const Reference< ::com::sun::star::container::XIndexContainer >& xColumns)
1553 : {
1554 : // Spalten wieder neu setzen
1555 : // wenn es nur eine HandleColumn gibt, dann nicht
1556 0 : if (GetModelColCount())
1557 : {
1558 0 : RemoveColumns();
1559 0 : InsertHandleColumn();
1560 : }
1561 :
1562 0 : if (!xColumns.is())
1563 0 : return;
1564 :
1565 0 : SetUpdateMode(false);
1566 :
1567 : // Einfuegen muss sich an den Column Positionen orientieren
1568 : sal_Int32 i;
1569 0 : Any aWidth;
1570 0 : for (i = 0; i < xColumns->getCount(); ++i)
1571 : {
1572 : Reference< ::com::sun::star::beans::XPropertySet > xCol(
1573 0 : xColumns->getByIndex(i), css::uno::UNO_QUERY);
1574 :
1575 : OUString aName(
1576 0 : comphelper::getString(xCol->getPropertyValue(FM_PROP_LABEL)));
1577 :
1578 0 : aWidth = xCol->getPropertyValue(FM_PROP_WIDTH);
1579 0 : sal_Int32 nWidth = 0;
1580 0 : if (aWidth >>= nWidth)
1581 0 : nWidth = LogicToPixel(Point(nWidth,0),MAP_10TH_MM).X();
1582 :
1583 0 : AppendColumn(aName, (sal_uInt16)nWidth);
1584 0 : DbGridColumn* pCol = DbGridControl::GetColumns().at( i );
1585 0 : pCol->setModel(xCol);
1586 0 : }
1587 :
1588 : // und jetzt noch die hidden columns rausnehmen
1589 : // (wir haben das nicht gleich in der oberen Schleife gemacht, da wir dann Probleme mit den
1590 : // IDs der Spalten bekommen haetten : AppendColumn vergibt die automatisch, die Spalte _nach_
1591 : // einer versteckten braucht aber eine um eine erhoehte ID ....
1592 0 : Any aHidden;
1593 0 : for (i = 0; i < xColumns->getCount(); ++i)
1594 : {
1595 : Reference< ::com::sun::star::beans::XPropertySet > xCol(
1596 0 : xColumns->getByIndex(i), css::uno::UNO_QUERY);
1597 0 : aHidden = xCol->getPropertyValue(FM_PROP_HIDDEN);
1598 0 : if (::comphelper::getBOOL(aHidden))
1599 0 : HideColumn(GetColumnIdFromModelPos((sal_uInt16)i));
1600 0 : }
1601 :
1602 0 : SetUpdateMode(true);
1603 : }
1604 :
1605 0 : void FmGridControl::InitColumnByField(
1606 : DbGridColumn* _pColumn, const Reference< XPropertySet >& _rxColumnModel,
1607 : const Reference< XNameAccess >& _rxFieldsByNames, const Reference< XIndexAccess >& _rxFieldsByIndex )
1608 : {
1609 : DBG_ASSERT( _rxFieldsByNames == _rxFieldsByIndex, "FmGridControl::InitColumnByField: invalid container interfaces!" );
1610 :
1611 : // lookup the column which belongs to the control source
1612 0 : OUString sFieldName;
1613 0 : _rxColumnModel->getPropertyValue( FM_PROP_CONTROLSOURCE ) >>= sFieldName;
1614 0 : Reference< XPropertySet > xField;
1615 0 : _rxColumnModel->getPropertyValue( FM_PROP_BOUNDFIELD ) >>= xField;
1616 :
1617 :
1618 0 : if ( !xField.is() && /*sFieldName.getLength() && */_rxFieldsByNames->hasByName( sFieldName ) ) // #i93452# do not check for name length
1619 0 : _rxFieldsByNames->getByName( sFieldName ) >>= xField;
1620 :
1621 : // determine the position of this column
1622 0 : sal_Int32 nFieldPos = -1;
1623 0 : if ( xField.is() )
1624 : {
1625 0 : Reference< XPropertySet > xCheck;
1626 0 : sal_Int32 nFieldCount = _rxFieldsByIndex->getCount();
1627 0 : for ( sal_Int32 i = 0; i < nFieldCount; ++i)
1628 : {
1629 0 : _rxFieldsByIndex->getByIndex( i ) >>= xCheck;
1630 0 : if ( xField.get() == xCheck.get() )
1631 : {
1632 0 : nFieldPos = i;
1633 0 : break;
1634 : }
1635 0 : }
1636 : }
1637 :
1638 0 : if ( xField.is() && ( nFieldPos >= 0 ) )
1639 : {
1640 : // some data types are not allowed
1641 0 : sal_Int32 nDataType = DataType::OTHER;
1642 0 : xField->getPropertyValue( FM_PROP_FIELDTYPE ) >>= nDataType;
1643 :
1644 0 : sal_Bool bIllegalType = sal_False;
1645 0 : switch ( nDataType )
1646 : {
1647 : case DataType::BLOB:
1648 : case DataType::LONGVARBINARY:
1649 : case DataType::BINARY:
1650 : case DataType::VARBINARY:
1651 : case DataType::OTHER:
1652 0 : bIllegalType = sal_True;
1653 0 : break;
1654 : }
1655 :
1656 0 : if ( bIllegalType )
1657 : {
1658 0 : _pColumn->SetObject( (sal_Int16)nFieldPos );
1659 0 : return;
1660 : }
1661 : }
1662 :
1663 : // the control type is determined by the ColumnServiceName
1664 0 : static OUString s_sPropColumnServiceName( "ColumnServiceName" );
1665 0 : if ( !::comphelper::hasProperty( s_sPropColumnServiceName, _rxColumnModel ) )
1666 0 : return;
1667 :
1668 0 : _pColumn->setModel( _rxColumnModel );
1669 :
1670 0 : OUString sColumnServiceName;
1671 0 : _rxColumnModel->getPropertyValue( s_sPropColumnServiceName ) >>= sColumnServiceName;
1672 :
1673 0 : sal_Int32 nTypeId = getColumnTypeByModelName( sColumnServiceName );
1674 0 : _pColumn->CreateControl( nFieldPos, xField, nTypeId );
1675 : }
1676 :
1677 0 : void FmGridControl::InitColumnsByFields(const Reference< ::com::sun::star::container::XIndexAccess >& _rxFields)
1678 : {
1679 0 : if ( !_rxFields.is() )
1680 0 : return;
1681 :
1682 : // Spalten initialisieren
1683 0 : Reference< XIndexContainer > xColumns( GetPeer()->getColumns() );
1684 0 : Reference< XNameAccess > xFieldsAsNames( _rxFields, UNO_QUERY );
1685 :
1686 : // Einfuegen muss sich an den Column Positionen orientieren
1687 0 : for (sal_Int32 i = 0; i < xColumns->getCount(); i++)
1688 : {
1689 0 : DbGridColumn* pCol = GetColumns().at( i );
1690 : OSL_ENSURE(pCol,"No grid column!");
1691 0 : if ( pCol )
1692 : {
1693 : Reference< XPropertySet > xColumnModel(
1694 0 : xColumns->getByIndex( i ), css::uno::UNO_QUERY);
1695 :
1696 0 : InitColumnByField( pCol, xColumnModel, xFieldsAsNames, _rxFields );
1697 : }
1698 0 : }
1699 : }
1700 :
1701 0 : void FmGridControl::HideColumn(sal_uInt16 nId)
1702 : {
1703 0 : DbGridControl::HideColumn(nId);
1704 :
1705 0 : sal_uInt16 nPos = GetModelColumnPos(nId);
1706 0 : if (nPos == (sal_uInt16)-1)
1707 0 : return;
1708 :
1709 0 : DbGridColumn* pColumn = GetColumns().at( nPos );
1710 0 : if (pColumn->IsHidden())
1711 0 : GetPeer()->columnHidden(pColumn);
1712 :
1713 0 : if (nId == m_nMarkedColumnId)
1714 0 : m_nMarkedColumnId = (sal_uInt16)-1;
1715 : }
1716 :
1717 0 : bool FmGridControl::isColumnSelected(sal_uInt16 /*nId*/,DbGridColumn* _pColumn)
1718 : {
1719 : OSL_ENSURE(_pColumn,"Column can not be null!");
1720 0 : bool bSelected = false;
1721 : // if the column which is shown here is selected ...
1722 0 : Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(GetPeer()->getColumns(), UNO_QUERY);
1723 0 : if ( xSelSupplier.is() )
1724 : {
1725 0 : Reference< ::com::sun::star::beans::XPropertySet > xColumn;
1726 0 : xSelSupplier->getSelection() >>= xColumn;
1727 0 : bSelected = (xColumn.get() == _pColumn->getModel().get());
1728 : }
1729 0 : return bSelected;
1730 : }
1731 :
1732 0 : void FmGridControl::ShowColumn(sal_uInt16 nId)
1733 : {
1734 0 : DbGridControl::ShowColumn(nId);
1735 :
1736 0 : sal_uInt16 nPos = GetModelColumnPos(nId);
1737 0 : if (nPos == (sal_uInt16)-1)
1738 0 : return;
1739 :
1740 0 : DbGridColumn* pColumn = GetColumns().at( nPos );
1741 0 : if (!pColumn->IsHidden())
1742 0 : GetPeer()->columnVisible(pColumn);
1743 :
1744 : // if the column which is shown here is selected ...
1745 0 : if ( isColumnSelected(nId,pColumn) )
1746 0 : markColumn(nId); // ... -> mark it
1747 : }
1748 :
1749 0 : bool FmGridControl::selectBookmarks(const Sequence< Any >& _rBookmarks)
1750 : {
1751 0 : SolarMutexGuard aGuard;
1752 : // need to lock the SolarMutex so that no paint call disturbs us ...
1753 :
1754 0 : if ( !m_pSeekCursor )
1755 : {
1756 : OSL_FAIL( "FmGridControl::selectBookmarks: no seek cursor!" );
1757 0 : return false;
1758 : }
1759 :
1760 0 : const Any* pBookmark = _rBookmarks.getConstArray();
1761 0 : const Any* pBookmarkEnd = pBookmark + _rBookmarks.getLength();
1762 :
1763 0 : SetNoSelection();
1764 :
1765 0 : bool bAllSuccessfull = true;
1766 : try
1767 : {
1768 0 : for (; pBookmark != pBookmarkEnd; ++pBookmark)
1769 : {
1770 : // move the seek cursor to the row given
1771 0 : if (m_pSeekCursor->moveToBookmark(*pBookmark))
1772 0 : SelectRow( m_pSeekCursor->getRow() - 1);
1773 : else
1774 0 : bAllSuccessfull = false;
1775 : }
1776 : }
1777 0 : catch(Exception&)
1778 : {
1779 : OSL_FAIL("FmGridControl::selectBookmarks: could not move to one of the bookmarks!");
1780 0 : return false;
1781 : }
1782 :
1783 0 : return bAllSuccessfull;
1784 : }
1785 :
1786 0 : Sequence< Any> FmGridControl::getSelectionBookmarks()
1787 : {
1788 : // lock our update so no paint-triggered seeks interfere ...
1789 0 : SetUpdateMode(false);
1790 :
1791 0 : sal_Int32 nSelectedRows = GetSelectRowCount(), i = 0;
1792 0 : Sequence< Any> aBookmarks(nSelectedRows);
1793 0 : if ( nSelectedRows )
1794 : {
1795 0 : Any* pBookmarks = (Any*)aBookmarks.getArray();
1796 :
1797 : // (I'm not sure if the problem isn't deeper : The szenario : a large table displayed by a grid with a
1798 : // thread-safe cursor (dBase). On loading the sdb-cursor started a counting thread. While this counting progress
1799 : // was running, I tried do delete 3 records from within the grid. Deletion caused a SeekCursor, which did a
1800 : // m_pSeekCursor->moveRelative and a m_pSeekCursor->getPosition.
1801 : // Unfortunally the first call caused a propertyChanged(RECORDCOUNT) which resulted in a repaint of the
1802 : // navigation bar and the grid. The latter itself will result in SeekRow calls. So after (successfully) returning
1803 : // from the moveRelative the getPosition returns an invalid value. And so the SeekCursor fails.
1804 : // In the consequence ALL parts of code where two calls to the seek cursor are done, while the second call _relys_ on
1805 : // the first one, should be secured against recursion, with a broad-minded interpretion of "recursion" : if any of these
1806 : // code parts is executed, no other should be accessible. But this sounds very difficult to achieve ....
1807 : // )
1808 :
1809 : // The next problem caused by the same behaviuor (SeekCursor causes a propertyChanged) : when adjusting rows we implicitly
1810 : // change our selection. So a "FirstSelected(); SeekCursor(); NextSelected();" may produce unpredictable results.
1811 : // That's why we _first_ collect the indicies of the selected rows and _then_ their bookmarks.
1812 0 : long nIdx = FirstSelectedRow();
1813 0 : while (nIdx >= 0)
1814 : {
1815 : // (we misuse the bookmarks array for this ...)
1816 0 : pBookmarks[i++] <<= (sal_Int32)nIdx;
1817 0 : nIdx = NextSelectedRow();
1818 : }
1819 : DBG_ASSERT(i == nSelectedRows, "FmGridControl::DeleteSelectedRows : could not collect the row indicies !");
1820 :
1821 0 : for (i=0; i<nSelectedRows; ++i)
1822 : {
1823 0 : nIdx = ::comphelper::getINT32(pBookmarks[i]);
1824 0 : if (IsInsertionRow(nIdx))
1825 : {
1826 : // leerzeile nicht loeschen
1827 0 : aBookmarks.realloc(--nSelectedRows);
1828 0 : SelectRow(nIdx, false); // selection aufheben fuer leerzeile
1829 0 : break;
1830 : }
1831 :
1832 : // Zunaechst den DatenCursor auf den selektierten Satz pos.
1833 0 : if (SeekCursor(nIdx))
1834 : {
1835 0 : GetSeekRow()->SetState(m_pSeekCursor, true);
1836 :
1837 0 : pBookmarks[i] = m_pSeekCursor->getBookmark();
1838 : }
1839 : #ifdef DBG_UTIL
1840 : else
1841 : OSL_FAIL("FmGridControl::DeleteSelectedRows : a bookmark could not be determined !");
1842 : #endif
1843 : }
1844 : }
1845 0 : SetUpdateMode(true);
1846 :
1847 : // if one of the SeekCursor-calls failed ....
1848 0 : aBookmarks.realloc(i);
1849 :
1850 : // (the alternative : while collecting the bookmarks lock our propertyChanged, this should resolve both our problems.
1851 : // but this would be incompatible as we need a locking flag, then ...)
1852 :
1853 0 : return aBookmarks;
1854 : }
1855 :
1856 : namespace
1857 : {
1858 0 : OUString getColumnPropertyFromPeer(FmXGridPeer* _pPeer,sal_Int32 _nPosition,const OUString& _sPropName)
1859 : {
1860 0 : OUString sRetText;
1861 0 : if ( _pPeer && _nPosition != -1)
1862 : {
1863 0 : Reference<XIndexContainer> xIndex = _pPeer->getColumns();
1864 0 : if ( xIndex.is() && xIndex->getCount() > _nPosition )
1865 : {
1866 0 : Reference<XPropertySet> xProp;
1867 0 : xIndex->getByIndex( _nPosition ) >>= xProp;
1868 0 : if ( xProp.is() )
1869 : {
1870 : try {
1871 0 : xProp->getPropertyValue( _sPropName ) >>= sRetText;
1872 0 : } catch (UnknownPropertyException const& e) {
1873 : SAL_WARN("svx.form",
1874 : "exception caught: " << e.Message);
1875 : }
1876 0 : }
1877 0 : }
1878 : }
1879 0 : return sRetText;
1880 : }
1881 : }
1882 :
1883 : // Object data and state ------------------------------------------------------
1884 0 : OUString FmGridControl::GetAccessibleObjectName( ::svt::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition ) const
1885 : {
1886 0 : OUString sRetText;
1887 0 : switch( _eObjType )
1888 : {
1889 : case ::svt::BBTYPE_BROWSEBOX:
1890 0 : if ( GetPeer() )
1891 : {
1892 0 : Reference<XPropertySet> xProp(GetPeer()->getColumns(),UNO_QUERY);
1893 0 : if ( xProp.is() )
1894 0 : xProp->getPropertyValue(FM_PROP_NAME) >>= sRetText;
1895 : }
1896 0 : break;
1897 : case ::svt::BBTYPE_COLUMNHEADERCELL:
1898 0 : sRetText = getColumnPropertyFromPeer(
1899 : GetPeer(),
1900 : GetModelColumnPos(
1901 0 : sal::static_int_cast< sal_uInt16 >(_nPosition)),
1902 0 : FM_PROP_LABEL);
1903 0 : break;
1904 : default:
1905 0 : sRetText = DbGridControl::GetAccessibleObjectName(_eObjType,_nPosition);
1906 : }
1907 0 : return sRetText;
1908 : }
1909 :
1910 0 : OUString FmGridControl::GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition ) const
1911 : {
1912 0 : OUString sRetText;
1913 0 : switch( _eObjType )
1914 : {
1915 : case ::svt::BBTYPE_BROWSEBOX:
1916 0 : if ( GetPeer() )
1917 : {
1918 0 : Reference<XPropertySet> xProp(GetPeer()->getColumns(),UNO_QUERY);
1919 0 : if ( xProp.is() )
1920 : {
1921 0 : xProp->getPropertyValue(FM_PROP_HELPTEXT) >>= sRetText;
1922 0 : if ( sRetText.isEmpty() )
1923 0 : xProp->getPropertyValue(FM_PROP_DESCRIPTION) >>= sRetText;
1924 0 : }
1925 : }
1926 0 : break;
1927 : case ::svt::BBTYPE_COLUMNHEADERCELL:
1928 0 : sRetText = getColumnPropertyFromPeer(
1929 : GetPeer(),
1930 : GetModelColumnPos(
1931 0 : sal::static_int_cast< sal_uInt16 >(_nPosition)),
1932 0 : FM_PROP_HELPTEXT);
1933 0 : if ( sRetText.isEmpty() )
1934 0 : sRetText = getColumnPropertyFromPeer(
1935 : GetPeer(),
1936 : GetModelColumnPos(
1937 0 : sal::static_int_cast< sal_uInt16 >(_nPosition)),
1938 0 : FM_PROP_DESCRIPTION);
1939 :
1940 0 : break;
1941 : default:
1942 0 : sRetText = DbGridControl::GetAccessibleObjectDescription(_eObjType,_nPosition);
1943 : }
1944 0 : return sRetText;
1945 : }
1946 :
1947 0 : void FmGridControl::Select()
1948 : {
1949 0 : DbGridControl::Select();
1950 : // ... betrifft das unsere Spalten ?
1951 0 : const MultiSelection* pColumnSelection = GetColumnSelection();
1952 :
1953 : sal_uInt16 nSelectedColumn =
1954 0 : pColumnSelection && pColumnSelection->GetSelectCount()
1955 : ? sal::static_int_cast< sal_uInt16 >(
1956 0 : ((MultiSelection*)pColumnSelection)->FirstSelected())
1957 0 : : SAL_MAX_UINT16;
1958 : // die HandleColumn wird nicht selektiert
1959 0 : switch (nSelectedColumn)
1960 : {
1961 0 : case SAL_MAX_UINT16: break; // no selection
1962 0 : case 0 : nSelectedColumn = SAL_MAX_UINT16; break;
1963 : // handle col can't be seledted
1964 : default :
1965 : // get the model col pos instead of the view col pos
1966 0 : nSelectedColumn = GetModelColumnPos(GetColumnIdFromViewPos(nSelectedColumn - 1));
1967 0 : break;
1968 : }
1969 :
1970 0 : if (nSelectedColumn != m_nCurrentSelectedColumn)
1971 : {
1972 : // VOR dem Aufruf des select am SelectionSupplier !
1973 0 : m_nCurrentSelectedColumn = nSelectedColumn;
1974 :
1975 0 : if (!m_bSelecting)
1976 : {
1977 0 : m_bSelecting = true;
1978 :
1979 : try
1980 : {
1981 0 : Reference< XIndexAccess > xColumns(GetPeer()->getColumns(), UNO_QUERY);
1982 0 : Reference< XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY);
1983 0 : if (xSelSupplier.is())
1984 : {
1985 0 : if (nSelectedColumn != SAL_MAX_UINT16)
1986 : {
1987 : Reference< XPropertySet > xColumn(
1988 0 : xColumns->getByIndex(nSelectedColumn),
1989 0 : css::uno::UNO_QUERY);
1990 0 : xSelSupplier->select(makeAny(xColumn));
1991 : }
1992 : else
1993 : {
1994 0 : xSelSupplier->select(Any());
1995 : }
1996 0 : }
1997 : }
1998 0 : catch(Exception&)
1999 : {
2000 : }
2001 :
2002 :
2003 0 : m_bSelecting = false;
2004 : }
2005 : }
2006 0 : }
2007 :
2008 0 : sal_Int32 FmGridControl::GetSelectedColumn() const
2009 : {
2010 0 : return m_nCurrentSelectedColumn;
2011 : }
2012 :
2013 0 : void FmGridControl::KeyInput( const KeyEvent& rKEvt )
2014 : {
2015 0 : sal_Bool bDone = sal_False;
2016 0 : const KeyCode& rKeyCode = rKEvt.GetKeyCode();
2017 0 : if ( IsDesignMode()
2018 0 : && !rKeyCode.IsShift()
2019 0 : && !rKeyCode.IsMod1()
2020 0 : && !rKeyCode.IsMod2()
2021 0 : && GetParent() )
2022 : {
2023 0 : switch ( rKeyCode.GetCode() )
2024 : {
2025 : case KEY_ESCAPE:
2026 0 : GetParent()->GrabFocus();
2027 0 : bDone = sal_True;
2028 0 : break;
2029 : case KEY_DELETE:
2030 0 : if ( GetSelectColumnCount() && GetPeer() && m_nCurrentSelectedColumn >= 0 )
2031 : {
2032 0 : Reference< ::com::sun::star::container::XIndexContainer > xCols(GetPeer()->getColumns());
2033 0 : if ( xCols.is() )
2034 : {
2035 : try
2036 : {
2037 0 : if ( m_nCurrentSelectedColumn < xCols->getCount() )
2038 : {
2039 0 : Reference< XInterface > xCol;
2040 0 : xCols->getByIndex(m_nCurrentSelectedColumn) >>= xCol;
2041 0 : xCols->removeByIndex(m_nCurrentSelectedColumn);
2042 0 : ::comphelper::disposeComponent(xCol);
2043 : }
2044 : }
2045 0 : catch(const Exception&)
2046 : {
2047 : OSL_FAIL("exception occurred while deleting a column");
2048 : }
2049 0 : }
2050 : }
2051 0 : bDone = sal_True;
2052 0 : break;
2053 : }
2054 : }
2055 0 : if ( !bDone )
2056 0 : DbGridControl::KeyInput( rKEvt );
2057 0 : }
2058 :
2059 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|