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/settings.hxx>
70 #include <sal/log.hxx>
72 #include <memory>
73 #include <string_view>
74 
75 using namespace ::com::sun::star::uno;
76 using namespace ::com::sun::star::view;
77 using namespace ::com::sun::star::beans;
78 using namespace ::com::sun::star::lang;
79 using namespace ::com::sun::star::sdbcx;
80 using namespace ::com::sun::star::sdbc;
81 using namespace ::com::sun::star::sdb;
82 using namespace ::com::sun::star::form;
83 using namespace ::com::sun::star::util;
84 using namespace ::com::sun::star::container;
85 using namespace ::cppu;
86 using namespace ::svxform;
87 using namespace ::svx;
88 using namespace ::dbtools;
89 
91 {
92  ODataAccessDescriptor aDropData;
95  Reference< XInterface > xDroppedStatement;
96  Reference< XInterface > xDroppedResultSet;
97 };
98 
99 static 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();
121 }
122 
123 sal_uInt16 FmGridHeader::GetModelColumnPos(sal_uInt16 nId) const
124 {
125  return static_cast<FmGridControl*>(GetParent())->GetModelColumnPos(nId);
126 }
127 
128 void 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  {
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;
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 
352 IMPL_LINK_NOARG( FmGridHeader, OnAsyncExecuteDrop, void*, void )
353 {
354  OUString sCommand, sFieldName,sURL;
355  sal_Int32 nCommandType = CommandType::COMMAND;
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  {
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 
812 namespace {
813 
814 enum InspectorAction { eOpenInspector, eCloseInspector, eUpdateInspector, eNone };
815 
816 }
817 
818 void 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 
1005 void 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
1097 void 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);
1216  SetNoSelection();
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);
1226  EndCursorAction();
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);
1305  SetNoSelection();
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);
1391  SelectRow(GetSeekPos());
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 
1403  EndCursorAction();
1404  SetUpdateMode(true);
1405  }
1406  else // row could not be deleted
1407  {
1408  EndCursorAction();
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)
1431  implAdjustInSolarThread(false);
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 
1467 void FmGridControl::markColumn(sal_uInt16 nId)
1468 {
1469  if (!(GetHeaderBar() && m_nMarkedColumnId != nId))
1470  return;
1471 
1472  // deselect
1474  {
1475  HeaderBarItemBits aBits = GetHeaderBar()->GetItemBits(m_nMarkedColumnId) & ~HeaderBarItemBits::FLAT;
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  }
1485  m_nMarkedColumnId = nId;
1486 }
1487 
1488 bool 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 
1521 void FmGridControl::ColumnResized(sal_uInt16 nId)
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 
1557 void 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 
1598 void 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;
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  {
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 
1722 void 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 
1746 void 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 
1762 bool FmGridControl::isColumnSelected(DbGridColumn const * _pColumn) const
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 
1777 void 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 
1794 bool 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 
1805  SetNoSelection();
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.
1854  tools::Long nIdx = FirstSelectedRow();
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 
1898 namespace
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  {
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
1925 OUString 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)),
1943  FM_PROP_LABEL);
1944  break;
1945  default:
1946  sRetText = DbGridControl::GetAccessibleObjectName(_eObjType,_nPosition);
1947  }
1948  return sRetText;
1949 }
1950 
1951 OUString FmGridControl::GetAccessibleObjectDescription( AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition ) const
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())
1998  : SAL_MAX_UINT16;
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  {
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 
2050 void FmGridControl::KeyInput( const KeyEvent& rKEvt )
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: */
OString stripEnd(const OString &rIn, char c)
bool is() const
const css::uno::Reference< css::beans::XPropertySet > & getModel() const
Definition: gridcell.hxx:112
virtual bool SaveModified() override
Definition: gridctrl.cxx:2829
virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent &rEvt) override
Definition: fmgridcl.cxx:206
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 OUString GetAccessibleObjectName(AccessibleBrowseBoxObjType eObjType, sal_Int32 _nPosition=-1) const override
return the name of the specified object.
Definition: fmgridcl.cxx:1925
constexpr OUStringLiteral FM_PROP_ROWCOUNT
Definition: fmprop.hxx:34
virtual void HideColumn(sal_uInt16 nId) override
hide a column
Definition: fmgridcl.cxx:1746
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:655
virtual void set_sensitive(const OString &rIdent, bool bSensitive)=0
bool m_bSelecting
Definition: fmgridcl.hxx:101
void inserted()
Definition: fmgridcl.cxx:1449
GridRowStatus GetStatus() const
Definition: gridctrl.hxx:83
Reference< XRow > xRow
bool next()
Definition: fmtools.hxx:119
virtual void Command(const CommandEvent &rCEvt) override
Definition: fmgridcl.cxx:1039
void columnVisible(DbGridColumn const *pColumn)
Definition: fmgridif.cxx:2381
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
const DbGridRowRef & GetEmptyRow() const
Definition: gridctrl.hxx:577
signed char sal_Int8
virtual void ShowColumn(sal_uInt16 nId) override
show a column
Definition: fmgridcl.cxx:1777
const css::uno::Any & GetBookmark() const
Definition: gridctrl.hxx:87
static SvxAbstractDialogFactory * Create()
Definition: svxdlg.cxx:22
::std::vector< DataFlavorEx > DataFlavorExVector
long Long
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
constexpr OUStringLiteral SRV_SDB_CONNECTION
Definition: fmservs.hxx:53
void CreateControl(sal_Int32 _nFieldPos, const css::uno::Reference< css::beans::XPropertySet > &xField, sal_Int32 nTypeId)
Definition: gridcell.cxx:137
constexpr OUStringLiteral FM_PROP_HELPTEXT
Definition: fmprop.hxx:100
virtual void dispose() override
Definition: fmgridcl.cxx:116
std::unique_ptr< FmGridHeaderData > m_pImpl
Definition: fmgridcl.hxx:40
sal_Int32 GetSelectRowCount() const
bool IsAllSelected() const
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:93
constexpr OUStringLiteral FM_PROP_BOUNDFIELD
Definition: fmprop.hxx:103
#define FM_COL_COMBOBOX
Definition: gridcols.hxx:26
constexpr sal_Int32 BROWSER_ENDOFSELECTION
virtual void Select() override
Definition: fmgridcl.cxx:1988
Reference< XNumberFormatsSupplier > getNumberFormats(const Reference< XConnection > &_rxConn, bool _bAlloweDefault, const Reference< XComponentContext > &_rxContext)
virtual void KeyInput(const KeyEvent &rKEvt) override
Definition: fmgridcl.cxx:2050
virtual void ColumnMoved(sal_uInt16 nId) override
Definition: fmgridcl.cxx:1557
constexpr OUStringLiteral FM_PROP_ESCAPE_PROCESSING
Definition: fmprop.hxx:124
HelpEventMode GetMode() const
sal_uInt16 GetModelColumnPos(sal_uInt16 nId) const
Definition: gridctrl.cxx:3154
sal_uInt16 GetModelColCount() const
Definition: gridctrl.hxx:422
#define TYPE_CHECKBOX
Definition: gridcols.hxx:37
constexpr OUStringLiteral FM_PROP_WIDTH
Definition: fmprop.hxx:51
bool IsDesignMode() const
Definition: gridctrl.hxx:428
virtual sal_Int8 AcceptDrop(const AcceptDropEvent &rEvt) override
Definition: fmgridcl.cxx:192
sal_uInt16 GetSelectColumnCount() const
constexpr OUStringLiteral FM_PROP_ROWHEIGHT
Definition: fmprop.hxx:99
virtual void Command(const CommandEvent &rEvt) override
Definition: gridctrl.cxx:2541
#define TYPE_PATTERNFIELD
Definition: gridcols.hxx:44
sal_Int32 getColumnTypeByModelName(const OUString &aModelName)
Definition: gridcols.cxx:77
constexpr OUStringLiteral FM_PROP_ISMODIFIED
Definition: fmprop.hxx:116
constexpr OUStringLiteral FM_PROP_ISNEW
Definition: fmprop.hxx:117
sal_Int64 WinBits
virtual void BeginCursorAction() override
Definition: fmgridcl.cxx:1545
virtual void BeginCursorAction()
Definition: gridctrl.cxx:3206
sal_Int8 nDropAction
Definition: fmgridcl.cxx:94
virtual void ColumnMoved(sal_uInt16 nId) override
Definition: gridctrl.cxx:1441
constexpr OUStringLiteral FM_PROP_LABEL
Definition: fmprop.hxx:42
#define SAL_MAX_UINT16
bool IsUpdating() const
Definition: gridctrl.hxx:466
constexpr OUStringLiteral FM_PROP_FORMATSSUPPLIER
Definition: fmprop.hxx:68
CursorWrapper * getDataSource() const
Definition: gridctrl.hxx:405
bool IsMouseEvent() const
bool IsCurrentAppending() const
Definition: gridctrl.cxx:2819
const DataFlavorExVector & GetDataFlavorExVector() const
int nCount
OUString SvxResId(TranslateId aId)
Definition: dialmgr.cxx:24
#define DND_ACTION_NONE
constexpr Point TopCenter() const
virtual ~FmGridHeader() override
Definition: fmgridcl.cxx:111
#define TYPE_NUMERICFIELD
Definition: gridcols.hxx:43
Reference< XInterface > xDroppedStatement
Definition: fmgridcl.cxx:95
virtual void SetDesignMode(bool bMode)
Definition: gridctrl.cxx:2316
virtual void SetNoSelection() override
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
bool moveToBookmark(const css::uno::Any &bookmark)
Definition: fmtools.hxx:105
constexpr OUStringLiteral FM_PROP_FIELDTYPE
Definition: fmprop.hxx:77
virtual void Select() override
Definition: fmgridcl.cxx:144
sal_uInt16 GetColumnIdFromViewPos(sal_uInt16 nPos) const
Definition: gridctrl.hxx:424
constexpr OUStringLiteral FM_PROP_ISCURRENCY
Definition: fmprop.hxx:128
virtual OUString GetAccessibleObjectName(AccessibleBrowseBoxObjType eObjType, sal_Int32 _nPosition=-1) const override
constexpr void SetLeft(tools::Long v)
const Point & GetMousePosPixel() const
virtual void Select() override
Definition: gridctrl.cxx:831
bool IsInsertionRow(sal_Int32 nRow) const
Definition: gridctrl.cxx:2824
virtual tools::Long QueryMinimumRowHeight() override
Definition: fmgridcl.cxx:1493
constexpr OUStringLiteral FM_PROP_DESCRIPTION
Definition: fmprop.hxx:149
virtual void CellModified() override
Definition: fmgridcl.cxx:1539
void SetNew(bool _bNew)
Definition: gridctrl.hxx:84
void startCursorListening()
Definition: fmgridif.cxx:2110
#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:573
#define DBG_ASSERT(sCon, aError)
constexpr OUStringLiteral FM_PROP_DATASOURCE
Definition: fmprop.hxx:80
bool selectBookmarks(const css::uno::Sequence< css::uno::Any > &_rBookmarks)
Definition: fmgridcl.cxx:1794
bool CompareBookmark(const Any &aLeft, const Any &aRight)
Definition: gridctrl.cxx:237
int i
void CellModified()
Definition: fmgridif.cxx:1315
void InitColumnsByModels(const css::uno::Reference< css::container::XIndexContainer > &xColumns)
Definition: fmgridcl.cxx:1598
void markColumn(sal_uInt16 nId)
Definition: fmgridcl.cxx:1467
sal_Int32 FirstSelectedColumn() const
void propertyChange(const css::beans::PropertyChangeEvent &evt)
Definition: fmgridcl.cxx:1097
bool isColumnSelected(DbGridColumn const *_pColumn) const
returns if a column is selected
Definition: fmgridcl.cxx:1762
FmXGridPeer * m_pPeer
Definition: fmgridcl.hxx:98
weld::Window * GetPopupParent(vcl::Window &rOutWin, tools::Rectangle &rRect)
css::uno::Sequence< css::uno::Any > getSelectionBookmarks()
Definition: fmgridcl.cxx:1828
virtual bool get_active(const OString &rIdent) const =0
SfxBindings & GetBindings()
virtual void DeleteSelectedRows() override
Definition: fmgridcl.cxx:1161
void triggerColumnContextMenu(const ::Point &_rPreferredPos)
Definition: fmgridcl.cxx:1005
void AdjustDataSource(bool bFull=false)
Definition: gridctrl.cxx:1925
constexpr OUStringLiteral FM_PROP_COMMANDTYPE
Definition: fmprop.hxx:120
static void InsertMenuItem(weld::Menu &rMenu, int nMenuPos, std::string_view id, const OUString &rText, const OUString &rImgId)
Definition: fmgridcl.cxx:99
virtual void ShowColumn(sal_uInt16 nId)
show a column
Definition: gridctrl.cxx:3062
std::unique_ptr< CursorWrapper > m_pSeekCursor
Definition: gridctrl.hxx:267
virtual void RowHeightChanged() override
Definition: fmgridcl.cxx:1500
virtual void set_active(const OString &rIdent, bool bActive)=0
CommandEventId GetCommand() const
virtual void CellModified() override
Definition: gridctrl.cxx:2642
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:1125
virtual void EndCursorAction()
Definition: gridctrl.cxx:3223
sal_uInt16 m_nMarkedColumnId
Definition: fmgridcl.hxx:100
const DbGridRowRef & GetCurrentRow() const
Definition: gridctrl.hxx:481
void columnHidden(DbGridColumn const *pColumn)
Definition: fmgridif.cxx:2396
SfxItemState QueryState(sal_uInt16 nSID, std::unique_ptr< SfxPoolItem > &rpState)
constexpr void SetRight(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
constexpr void SetBottom(tools::Long v)
sal_uInt16 GetColumnIdFromModelPos(sal_uInt16 nPos) const
Definition: gridctrl.cxx:3127
#define TYPE_COMBOBOX
Definition: gridcols.hxx:38
ODataAccessDescriptor aDropData
Definition: fmgridcl.cxx:92
#define DND_ACTION_LINK
virtual void RequestHelp(const HelpEvent &rHEvt) override
Definition: fmgridcl.cxx:150
virtual OUString GetAccessibleObjectDescription(AccessibleBrowseBoxObjType eObjType, sal_Int32 _nPosition=-1) const override
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
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
constexpr OUStringLiteral FM_PROP_URL
Definition: fmprop.hxx:129
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
constexpr void SetTop(tools::Long v)
FmGridControl(const css::uno::Reference< css::uno::XComponentContext > &, vcl::Window *pParent, FmXGridPeer *_pPeer, WinBits nBits)
Definition: fmgridcl.cxx:1056
#define Y
#define TYPE_DATEFIELD
Definition: gridcols.hxx:40
#define TYPE_LISTBOX
Definition: gridcols.hxx:42
constexpr Point Center() const
constexpr Point TopLeft() const
const Point & GetMousePosPixel() const
void implAdjustInSolarThread(bool _bRows)
Definition: gridctrl.cxx:3163
const LanguageTag & getLocale()
void SetSeekPos(sal_Int32 nPos, GrantControlAccess)
Definition: gridctrl.hxx:527
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
void setModel(const css::uno::Reference< css::beans::XPropertySet > &_xModel)
Definition: gridcell.cxx:294
virtual void Command(const CommandEvent &rEvt) override
Definition: fmgridcl.cxx:1071
const vcl::KeyCode & GetKeyCode() const
void refreshRow()
Definition: fmtools.hxx:120
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:1551
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:2046
#define FM_COL_CURRENCYFIELD
Definition: gridcols.hxx:31
sal_Int32 nDataType
constexpr sal_uInt16 KEY_ESCAPE
void RemoveColumns()
Definition: gridctrl.cxx:1380
sal_Int32 GetTotalCount() const
Definition: gridctrl.hxx:575
const CellControllerRef & Controller() const
#define SAL_INFO(area, stream)
OUString aName
tools::Long CalcReverseZoom(tools::Long nVal) const
void InsertHandleColumn()
Definition: gridctrl.cxx:726
bool IsMod1() const
static VclPtr< reference_type > Create(Arg &&...arg)
sal_Int32 FirstSelectedRow()
virtual VclPtr< BrowserHeader > imp_CreateHeaderBar(BrowseBox *pParent) override
Definition: fmgridcl.cxx:1461
Reference< XInterface > xDroppedResultSet
Definition: fmgridcl.cxx:96
constexpr OUStringLiteral FMURL_CONFIRM_DELETION
Definition: fmurl.hxx:44
constexpr OUStringLiteral FM_PROP_NAME
Definition: fmprop.hxx:31
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:123
OString stripStart(const OString &rIn, char c)
void SetStatus(GridRowStatus _eStat)
Definition: gridctrl.hxx:82
void set(reference_type *pBody)
constexpr OUStringLiteral FM_PROP_COMMAND
Definition: fmprop.hxx:119
AccessibleBrowseBoxObjType
void stopCursorListening()
Definition: fmgridif.cxx:2133
Reference< XColumn > xColumn
sal_Int32 GetSeekPos() const
Definition: gridctrl.hxx:574
constexpr Point BottomRight() const
virtual void HideColumn(sal_uInt16 nId)
hide a column
Definition: gridctrl.cxx:3033
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:3016
const DbGridRowRef & GetSeekRow() const
Definition: gridctrl.hxx:578
Reference< XSingleServiceFactory > xFactory
Reference< XModel > xModel
class FmSearchEngine - Impl class for FmSearchDialog
bool isColumnMarked(sal_uInt16 nId) const
Definition: fmgridcl.cxx:1488
constexpr OUStringLiteral FM_PROP_CONTROLSOURCE
Definition: fmprop.hxx:45
void RowModified(sal_Int32 nRow)
Definition: gridctrl.cxx:2803
bool IsHidden() const
Definition: gridcell.hxx:122
constexpr sal_uInt16 KEY_DELETE
FmGridHeader(BrowseBox *pParent, WinBits nWinBits=WB_STDHEADERBAR|WB_DRAG)
Definition: fmgridcl.cxx:104
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:1521
void SetObject(sal_Int16 nPos)
Definition: gridcell.hxx:159
virtual void SelectAll() override
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
OUString getString(const Any &_rAny)
void positioned()
Definition: fmgridcl.cxx:1427
sal_Int8 mnAction
InspectorAction
Definition: fmgridcl.cxx:814
virtual bool IsRowSelected(sal_Int32 nRow) const override
virtual void RowHeightChanged() override
css::uno::Any getBookmark()
Definition: fmtools.hxx:101
virtual void InitColumnsByFields(const css::uno::Reference< css::container::XIndexAccess > &xFields) override
Definition: fmgridcl.cxx:1722
#define BROWSER_INVALIDID
void TransferFormComponentProperties(const Reference< XPropertySet > &xOldProps, const Reference< XPropertySet > &xNewProps, const Locale &_rLocale)
void beforeFirst()
Definition: fmtools.hxx:112
weld::Window * GetFrameWeld(const SfxFrame *pFrame)
virtual OUString GetAccessibleObjectDescription(AccessibleBrowseBoxObjType eObjType, sal_Int32 _nPosition=-1) const override
return the description of the specified object.
Definition: fmgridcl.cxx:1951
sal_uLong GetColumnWidth(sal_uInt16 nColumnId) const
void notifyColumnSelect(sal_uInt16 nColumnId)
selects the column at the selection supplier.
Definition: fmgridcl.cxx:128
BrowserHeader * GetHeaderBar() const
constexpr OUStringLiteral FM_PROP_HIDDEN
Definition: fmprop.hxx:108
AnyEventRef aEvent
HeaderBarItemBits
sal_Int32 GetSelectCount() const
const MultiSelection * GetSelection() const
sal_uInt16 nPos
#define TYPE_FORMATTEDFIELD
Definition: gridcols.hxx:41
static std::unique_ptr< weld::Builder > CreateBuilder(weld::Widget *pParent, const OUString &rUIFile, bool bMobile=false, sal_uInt64 nLOKWindowId=0)
void EnableInteractiveRowHeight()
static void ShowBalloon(vcl::Window *pParent, const Point &rScreenPos, const tools::Rectangle &, const OUString &rHelpText)
bool first()
Definition: fmtools.hxx:113
bool m_bDetectedRangeSegmentation false
IMPL_LINK_NOARG(FmGridHeader, OnAsyncExecuteDrop, void *, void)
Definition: fmgridcl.cxx:352
bool IsMod2() const
const DataFlavorExVector & GetDataFlavorExVector() const