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