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