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