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