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