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  {
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;
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;
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, AllSettings::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  return;
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 namespace {
776 
777 enum InspectorAction { eOpenInspector, eCloseInspector, eUpdateInspector, eNone };
778 
779 }
780 
781 void FmGridHeader::PostExecuteColumnContextMenu(sal_uInt16 nColId, const PopupMenu& rMenu, sal_uInt16 nExecutionResult)
782 {
783  Reference< css::container::XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
784  sal_uInt16 nPos = GetModelColumnPos(nColId);
785 
786  OUString aFieldType;
787  bool bReplace = false;
788  InspectorAction eInspectorAction = eNone;
789 
790  OString sExecutionResult = rMenu.GetCurItemIdent();
791  if (sExecutionResult.isEmpty())
792  {
793  PopupMenu* pMenu = rMenu.GetPopupMenu(rMenu.GetItemId("insert"));
794  if (pMenu)
795  sExecutionResult = pMenu->GetCurItemIdent();
796  }
797  if (sExecutionResult.isEmpty())
798  {
799  PopupMenu* pMenu = rMenu.GetPopupMenu(rMenu.GetItemId("change"));
800  if (pMenu)
801  sExecutionResult = pMenu->GetCurItemIdent();
802  }
803  if (sExecutionResult.isEmpty())
804  {
805  PopupMenu* pMenu = rMenu.GetPopupMenu(rMenu.GetItemId("show"));
806  if (pMenu)
807  sExecutionResult = pMenu->GetCurItemIdent();
808  }
809 
810  if (sExecutionResult == "delete")
811  {
813  xCols->getByIndex(nPos), css::uno::UNO_QUERY);
814  xCols->removeByIndex(nPos);
815  ::comphelper::disposeComponent(xCol);
816  }
817  else if (sExecutionResult == "hide")
818  {
819  Reference< css::beans::XPropertySet > xCurCol( xCols->getByIndex(nPos), css::uno::UNO_QUERY);
820  xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny(true));
821  }
822  else if (sExecutionResult == "column")
823  {
824  eInspectorAction = rMenu.IsItemChecked(rMenu.GetItemId("column")) ? eOpenInspector : eCloseInspector;
825  }
826  else if (sExecutionResult.startsWith(FM_COL_TEXTFIELD))
827  {
828  if (sExecutionResult != FM_COL_TEXTFIELD)
829  bReplace = true;
830  aFieldType = FM_COL_TEXTFIELD;
831  }
832  else if (sExecutionResult.startsWith(FM_COL_COMBOBOX))
833  {
834  if (sExecutionResult != FM_COL_COMBOBOX)
835  bReplace = true;
836  aFieldType = FM_COL_COMBOBOX;
837  }
838  else if (sExecutionResult.startsWith(FM_COL_LISTBOX))
839  {
840  if (sExecutionResult != FM_COL_LISTBOX)
841  bReplace = true;
842  aFieldType = FM_COL_LISTBOX;
843  }
844  else if (sExecutionResult.startsWith(FM_COL_CHECKBOX))
845  {
846  if (sExecutionResult != FM_COL_CHECKBOX)
847  bReplace = true;
848  aFieldType = FM_COL_CHECKBOX;
849  }
850  else if (sExecutionResult.startsWith(FM_COL_DATEFIELD))
851  {
852  if (sExecutionResult != FM_COL_DATEFIELD)
853  bReplace = true;
854  aFieldType = FM_COL_DATEFIELD;
855  }
856  else if (sExecutionResult.startsWith(FM_COL_TIMEFIELD))
857  {
858  if (sExecutionResult != FM_COL_TIMEFIELD)
859  bReplace = true;
860  aFieldType = FM_COL_TIMEFIELD;
861  }
862  else if (sExecutionResult.startsWith(FM_COL_NUMERICFIELD))
863  {
864  if (sExecutionResult != FM_COL_NUMERICFIELD)
865  bReplace = true;
866  aFieldType = FM_COL_NUMERICFIELD;
867  }
868  else if (sExecutionResult.startsWith(FM_COL_CURRENCYFIELD))
869  {
870  if (sExecutionResult != FM_COL_CURRENCYFIELD)
871  bReplace = true;
872  aFieldType = FM_COL_CURRENCYFIELD;
873  }
874  else if (sExecutionResult.startsWith(FM_COL_PATTERNFIELD))
875  {
876  if (sExecutionResult != FM_COL_PATTERNFIELD)
877  bReplace = true;
878  aFieldType = FM_COL_PATTERNFIELD;
879  }
880  else if (sExecutionResult.startsWith(FM_COL_FORMATTEDFIELD))
881  {
882  if (sExecutionResult != FM_COL_FORMATTEDFIELD)
883  bReplace = true;
884  aFieldType = FM_COL_FORMATTEDFIELD;
885  }
886  else if (sExecutionResult == "more")
887  {
890  pDlg->SetColumns(xCols);
891  pDlg->Execute();
892  }
893  else if (sExecutionResult == "all")
894  {
895  // just iterate through all the cols ...
896  Reference< css::beans::XPropertySet > xCurCol;
897  for (sal_Int32 i=0; i<xCols->getCount(); ++i)
898  {
899  xCurCol.set(xCols->getByIndex(i), css::uno::UNO_QUERY);
900  xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny(false));
901  }
902  // TODO : there must be a more clever way to do this...
903  // with the above the view is updated after every single model update ...
904  }
905  else if (nExecutionResult>0 && nExecutionResult<=16)
906  { // it was a "show column/<colname>" command (there are at most 16 such items)
907  // search the nExecutionResult'th hidden col
908  Reference< css::beans::XPropertySet > xCurCol;
909  for (sal_Int32 i=0; i<xCols->getCount() && nExecutionResult; ++i)
910  {
911  xCurCol.set(xCols->getByIndex(i), css::uno::UNO_QUERY);
912  Any aHidden = xCurCol->getPropertyValue(FM_PROP_HIDDEN);
913  if (::comphelper::getBOOL(aHidden))
914  if (!--nExecutionResult)
915  {
916  xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny(false));
917  break;
918  }
919  }
920  }
921 
922  if ( !aFieldType.isEmpty() )
923  {
924  try
925  {
926  Reference< XGridColumnFactory > xFactory( xCols, UNO_QUERY_THROW );
927  Reference< XPropertySet > xNewCol( xFactory->createColumn( aFieldType ), UNO_SET_THROW );
928 
929  if ( bReplace )
930  {
931  // rescue over a few properties
932  Reference< XPropertySet > xReplaced( xCols->getByIndex( nPos ), UNO_QUERY );
933 
935  xReplaced, xNewCol, Application::GetSettings().GetUILanguageTag().getLocale() );
936 
937  xCols->replaceByIndex( nPos, makeAny( xNewCol ) );
938  ::comphelper::disposeComponent( xReplaced );
939 
940  eInspectorAction = eUpdateInspector;
941  }
942  else
943  {
944  FormControlFactory factory;
945 
946  OUString sLabel = FormControlFactory::getDefaultUniqueName_ByComponentType(
947  Reference< XNameAccess >( xCols, UNO_QUERY_THROW ), xNewCol );
948  xNewCol->setPropertyValue( FM_PROP_LABEL, makeAny( sLabel ) );
949  xNewCol->setPropertyValue( FM_PROP_NAME, makeAny( sLabel ) );
950 
951  factory.initializeControlModel( DocumentClassification::classifyHostDocument( xCols ), xNewCol );
952 
953  xCols->insertByIndex( nPos, makeAny( xNewCol ) );
954  }
955  }
956  catch( const Exception& )
957  {
959  }
960  }
961 
962  SfxViewFrame* pCurrentFrame = SfxViewFrame::Current();
963  OSL_ENSURE( pCurrentFrame, "FmGridHeader::PostExecuteColumnContextMenu: no view frame -> no bindings -> no property browser!" );
964  if ( !pCurrentFrame )
965  return;
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 void FmGridHeader::triggerColumnContextMenu( const ::Point& _rPreferredPos )
984 {
985  // the affected col
986  sal_uInt16 nColId = GetItemId( _rPreferredPos );
987 
988  // the menu
989  VclBuilder aBuilder(nullptr, AllSettings::GetUIRootDir(), "svx/ui/colsmenu.ui", "");
990  VclPtr<PopupMenu> aContextMenu(aBuilder.get_menu("menu"));
991 
992  // let derivatives modify the menu
993  PreExecuteColumnContextMenu( nColId, *aContextMenu );
994  aContextMenu->RemoveDisabledEntries( true, true );
995 
996  // execute the menu
997  sal_uInt16 nResult = aContextMenu->Execute( this, _rPreferredPos );
998 
999  // let derivatives handle the result
1000  PostExecuteColumnContextMenu( nColId, *aContextMenu, nResult );
1001 }
1002 
1004 {
1005  switch (rEvt.GetCommand())
1006  {
1007  case CommandEventId::ContextMenu:
1008  {
1009  if (!rEvt.IsMouseEvent())
1010  return;
1011 
1013  }
1014  break;
1015  default:
1016  EditBrowserHeader::Command(rEvt);
1017  }
1018 }
1019 
1021  const Reference< css::uno::XComponentContext >& _rxContext,
1022  vcl::Window* pParent,
1023  FmXGridPeer* _pPeer,
1024  WinBits nBits)
1025  :DbGridControl(_rxContext, pParent, nBits)
1026  ,m_pPeer(_pPeer)
1027  ,m_nCurrentSelectedColumn(-1)
1028  ,m_nMarkedColumnId(BROWSER_INVALIDID)
1029  ,m_bSelecting(false)
1030  ,m_bInColumnMove(false)
1031 {
1033 }
1034 
1036 {
1037  if ( CommandEventId::ContextMenu == _rEvt.GetCommand() )
1038  {
1039  FmGridHeader* pMyHeader = static_cast< FmGridHeader* >( GetHeaderBar() );
1040  if ( pMyHeader && !_rEvt.IsMouseEvent() )
1041  { // context menu requested by keyboard
1042  if ( 1 == GetSelectColumnCount() || IsDesignMode() )
1043  {
1044  sal_uInt16 nSelId = GetColumnId(
1045  sal::static_int_cast< sal_uInt16 >( FirstSelectedColumn() ) );
1046  ::tools::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, false ) );
1047 
1048  Point aRelativePos( pMyHeader->ScreenToOutputPixel( OutputToScreenPixel( aColRect.TopCenter() ) ) );
1049  pMyHeader->triggerColumnContextMenu(aRelativePos);
1050 
1051  // handled
1052  return;
1053  }
1054  }
1055  }
1056 
1057  DbGridControl::Command( _rEvt );
1058 }
1059 
1060 // css::beans::XPropertyChangeListener
1061 void FmGridControl::propertyChange(const css::beans::PropertyChangeEvent& evt)
1062 {
1063  if (evt.PropertyName == FM_PROP_ROWCOUNT)
1064  {
1065  // if we're not in the main thread call AdjustRows asynchronously
1067  return;
1068  }
1069 
1070  const DbGridRowRef& xRow = GetCurrentRow();
1071  // no adjustment of the properties is carried out during positioning
1072  Reference<XPropertySet> xSet(evt.Source,UNO_QUERY);
1073  if (!(xRow.is() && (::cppu::any2bool(xSet->getPropertyValue(FM_PROP_ISNEW))|| CompareBookmark(getDataSource()->getBookmark(), xRow->GetBookmark()))))
1074  return;
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 
1090 {
1091  bool bOldMode = IsDesignMode();
1093  if (bOldMode == bMode)
1094  return;
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 
1126 {
1127  if (!m_pSeekCursor)
1128  return;
1129 
1130  // how many rows are selected?
1131  sal_Int32 nSelectedRows = GetSelectRowCount();
1132 
1133  // the current line should be deleted but it is currently in edit mode
1134  if ( IsCurrentAppending() )
1135  return;
1136  // is the insert row selected
1137  if (GetEmptyRow().is() && IsRowSelected(GetRowCount() - 1))
1138  nSelectedRows -= 1;
1139 
1140  // nothing to do
1141  if (nSelectedRows <= 0)
1142  return;
1143 
1144  // try to confirm the delete
1145  Reference< css::frame::XDispatchProvider > xDispatcher = static_cast<css::frame::XDispatchProvider*>(GetPeer());
1146  if (xDispatcher.is())
1147  {
1148  css::util::URL aUrl;
1149  aUrl.Complete = FMURL_CONFIRM_DELETION;
1150  Reference< css::util::XURLTransformer > xTransformer(
1151  css::util::URLTransformer::create(::comphelper::getProcessComponentContext()) );
1152  xTransformer->parseStrict( aUrl );
1153 
1154  Reference< css::frame::XDispatch > xDispatch = xDispatcher->queryDispatch(aUrl, OUString(), 0);
1155  Reference< css::form::XConfirmDeleteListener > xConfirm(xDispatch, UNO_QUERY);
1156  if (xConfirm.is())
1157  {
1158  css::sdb::RowChangeEvent aEvent;
1159  aEvent.Source = Reference< XInterface >(*getDataSource());
1160  aEvent.Rows = nSelectedRows;
1161  aEvent.Action = css::sdb::RowChangeAction::DELETE;
1162  if (!xConfirm->confirmDelete(aEvent))
1163  return;
1164  }
1165  }
1166 
1167  const MultiSelection* pRowSelection = GetSelection();
1168  if ( pRowSelection && pRowSelection->IsAllSelected() )
1169  {
1171  CursorWrapper* pCursor = getDataSource();
1172  Reference< XResultSetUpdate > xUpdateCursor(Reference< XInterface >(*pCursor), UNO_QUERY);
1173  try
1174  {
1175  pCursor->beforeFirst();
1176  while( pCursor->next() )
1177  xUpdateCursor->deleteRow();
1178 
1179  SetUpdateMode(false);
1180  SetNoSelection();
1181 
1182  xUpdateCursor->moveToInsertRow();
1183  }
1184  catch(const Exception&)
1185  {
1186  OSL_FAIL("Exception caught while deleting rows!");
1187  }
1188  // adapt to the data cursor
1189  AdjustDataSource(true);
1190  EndCursorAction();
1191  SetUpdateMode(true);
1192  }
1193  else
1194  {
1195  Reference< css::sdbcx::XDeleteRows > xDeleteThem(Reference< XInterface >(*getDataSource()), UNO_QUERY);
1196 
1197  // collect the bookmarks of the selected rows
1198  Sequence < Any> aBookmarks = getSelectionBookmarks();
1199 
1200  // determine the next row to position after deletion
1201  Any aBookmark;
1202  bool bNewPos = false;
1203  // if the current row isn't selected we take the row as row after deletion
1204  OSL_ENSURE( GetCurrentRow().is(), "FmGridControl::DeleteSelectedRows: no current row here?" );
1205  // crash reports suggest it can happen we don't have a current row - how?
1206  // #154303# / 2008-04-23 / frank.schoenheit@sun.com
1207  if ( !IsRowSelected( GetCurrentPos() ) && !IsCurrentAppending() && GetCurrentRow().is() )
1208  {
1209  aBookmark = GetCurrentRow()->GetBookmark();
1210  bNewPos = true;
1211  }
1212  else
1213  {
1214  // we look for the first row after the selected block for selection
1215  long nIdx = LastSelectedRow() + 1;
1216  if (nIdx < GetRowCount() - 1)
1217  {
1218  // there is a next row to position on
1219  if (SeekCursor(nIdx))
1220  {
1221  GetSeekRow()->SetState(m_pSeekCursor.get(), true);
1222 
1223  bNewPos = true;
1224  // if it's not the row for inserting we keep the bookmark
1225  if (!IsInsertionRow(nIdx))
1226  aBookmark = m_pSeekCursor->getBookmark();
1227  }
1228  }
1229  else
1230  {
1231  // we look for the first row before the selected block for selection after deletion
1232  nIdx = FirstSelectedRow() - 1;
1233  if (nIdx >= 0 && SeekCursor(nIdx))
1234  {
1235  GetSeekRow()->SetState(m_pSeekCursor.get(), true);
1236 
1237  bNewPos = true;
1238  aBookmark = m_pSeekCursor->getBookmark();
1239  }
1240  }
1241  }
1242 
1243  // Are all rows selected?
1244  // Second condition if no insertion line exists
1245  bool bAllSelected = GetTotalCount() == nSelectedRows || GetRowCount() == nSelectedRows;
1246 
1248 
1249  // now delete the row
1250  Sequence<sal_Int32> aDeletedRows;
1251  SetUpdateMode( false );
1252  try
1253  {
1254  aDeletedRows = xDeleteThem->deleteRows(aBookmarks);
1255  }
1256  catch(SQLException&)
1257  {
1258  }
1259  SetUpdateMode( true );
1260 
1261  // how many rows are deleted?
1262  sal_Int32 nDeletedRows = static_cast<sal_Int32>(std::count_if(aDeletedRows.begin(), aDeletedRows.end(),
1263  [](const sal_Int32 nRow) { return nRow != 0; }));
1264 
1265  // have rows been deleted?
1266  if (nDeletedRows)
1267  {
1268  SetUpdateMode(false);
1269  SetNoSelection();
1270  try
1271  {
1272  // did we delete all the rows than try to move to the next possible row
1273  if (nDeletedRows == aDeletedRows.getLength())
1274  {
1275  // there exists a new position to move on
1276  if (bNewPos)
1277  {
1278  if (aBookmark.hasValue())
1279  getDataSource()->moveToBookmark(aBookmark);
1280  // no valid bookmark so move to the insert row
1281  else
1282  {
1283  Reference< XResultSetUpdate > xUpdateCursor(Reference< XInterface >(*m_pDataCursor), UNO_QUERY);
1284  xUpdateCursor->moveToInsertRow();
1285  }
1286  }
1287  else
1288  {
1289  Reference< css::beans::XPropertySet > xSet(Reference< XInterface >(*m_pDataCursor), UNO_QUERY);
1290 
1291  sal_Int32 nRecordCount(0);
1292  xSet->getPropertyValue(FM_PROP_ROWCOUNT) >>= nRecordCount;
1293  if ( m_pDataCursor->rowDeleted() )
1294  --nRecordCount;
1295 
1296  // there are no rows left and we have an insert row
1297  if (!nRecordCount && GetEmptyRow().is())
1298  {
1299  Reference< XResultSetUpdate > xUpdateCursor(Reference< XInterface >(*m_pDataCursor), UNO_QUERY);
1300  xUpdateCursor->moveToInsertRow();
1301  }
1302  else if (nRecordCount)
1303  // move to the first row
1304  getDataSource()->first();
1305  }
1306  }
1307  // not all the rows where deleted, so move to the first row which remained in the resultset
1308  else
1309  {
1310  auto pRow = std::find(aDeletedRows.begin(), aDeletedRows.end(), 0);
1311  if (pRow != aDeletedRows.end())
1312  {
1313  auto i = static_cast<sal_Int32>(std::distance(aDeletedRows.begin(), pRow));
1314  getDataSource()->moveToBookmark(aBookmarks[i]);
1315  }
1316  }
1317  }
1318  catch(const Exception&)
1319  {
1320  try
1321  {
1322  // positioning went wrong so try to move to the first row
1323  getDataSource()->first();
1324  }
1325  catch(const Exception&)
1326  {
1327  }
1328  }
1329 
1330  // adapt to the data cursor
1331  AdjustDataSource(true);
1332 
1333  // not all rows could be deleted;
1334  // never select again there the ones that could not be deleted
1335  if (nDeletedRows < nSelectedRows)
1336  {
1337  // were all selected
1338  if (bAllSelected)
1339  {
1340  SelectAll();
1341  if (IsInsertionRow(GetRowCount() - 1)) // not the insertion row
1342  SelectRow(GetRowCount() - 1, false);
1343  }
1344  else
1345  {
1346  // select the remaining rows
1347  for (const sal_Int32 nSuccess : aDeletedRows)
1348  {
1349  try
1350  {
1351  if (!nSuccess)
1352  {
1353  m_pSeekCursor->moveToBookmark(m_pDataCursor->getBookmark());
1354  SetSeekPos(m_pSeekCursor->getRow() - 1);
1355  SelectRow(GetSeekPos());
1356  }
1357  }
1358  catch(const Exception&)
1359  {
1360  // keep the seekpos in all cases
1361  SetSeekPos(m_pSeekCursor->getRow() - 1);
1362  }
1363  }
1364  }
1365  }
1366 
1367  EndCursorAction();
1368  SetUpdateMode(true);
1369  }
1370  else // row could not be deleted
1371  {
1372  EndCursorAction();
1373  try
1374  {
1375  // currentrow is the insert row?
1376  if (!IsCurrentAppending())
1378  }
1379  catch(const Exception&)
1380  {
1381  }
1382  }
1383  }
1384 
1385  // if there is no selection anymore we can start editing
1386  if (!GetSelectRowCount())
1387  ActivateCell();
1388 }
1389 
1390 // XCurrentRecordListener
1392 {
1393  SAL_INFO("svx.fmcomp", "FmGridControl::positioned");
1394  // position on the data source (force it to be done in the main thread)
1395  implAdjustInSolarThread(false);
1396 }
1397 
1399 {
1400  // execute commit only if an update is not already executed by the
1401  // css::form::component::GridControl
1402  if (!IsUpdating())
1403  {
1404  if (Controller().is() && Controller()->IsValueChangedFromSaved())
1405  {
1406  if (!SaveModified())
1407  return false;
1408  }
1409  }
1410  return true;
1411 }
1412 
1414 {
1415  const DbGridRowRef& xRow = GetCurrentRow();
1416  if (!xRow.is())
1417  return;
1418 
1419  // line has been inserted, then reset the status and mode
1420  xRow->SetState(m_pDataCursor.get(), false);
1421  xRow->SetNew(false);
1422 
1423 }
1424 
1426 {
1427  DBG_ASSERT( pParent == this, "FmGridControl::imp_CreateHeaderBar: parent?" );
1428  return VclPtr<FmGridHeader>::Create( pParent );
1429 }
1430 
1431 void FmGridControl::markColumn(sal_uInt16 nId)
1432 {
1433  if (!(GetHeaderBar() && m_nMarkedColumnId != nId))
1434  return;
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 bool FmGridControl::isColumnMarked(sal_uInt16 nId) const
1453 {
1454  return m_nMarkedColumnId == nId;
1455 }
1456 
1458 {
1459  long const nMinimalLogicHeight = 20; // 0.2 cm
1460  long nMinimalPixelHeight = LogicToPixel(Point(0, nMinimalLogicHeight), MapMode(MapUnit::Map10thMM)).Y();
1461  return CalcZoom( nMinimalPixelHeight );
1462 }
1463 
1465 {
1467 
1468  Reference< XPropertySet > xModel( GetPeer()->getColumns(), UNO_QUERY );
1469  DBG_ASSERT( xModel.is(), "FmGridControl::RowHeightChanged: no model!" );
1470  if ( !xModel.is() )
1471  return;
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 void FmGridControl::ColumnResized(sal_uInt16 nId)
1486 {
1488 
1489  // transfer value to the model
1491  const Reference< css::beans::XPropertySet >& xColModel(pCol->getModel());
1492  if (xColModel.is())
1493  {
1494  Any aWidth;
1495  sal_Int32 nColumnWidth = GetColumnWidth(nId);
1496  nColumnWidth = CalcReverseZoom(nColumnWidth);
1497  // convert to 10THMM
1498  aWidth <<= static_cast<sal_Int32>(PixelToLogic(Point(nColumnWidth, 0), MapMode(MapUnit::Map10thMM)).X());
1499  xColModel->setPropertyValue(FM_PROP_WIDTH, aWidth);
1500  }
1501 }
1502 
1504 {
1506  GetPeer()->CellModified();
1507 }
1508 
1510 {
1513 }
1514 
1516 {
1519 }
1520 
1521 void FmGridControl::ColumnMoved(sal_uInt16 nId)
1522 {
1523  m_bInColumnMove = true;
1524 
1526  Reference< css::container::XIndexContainer > xColumns(GetPeer()->getColumns());
1527 
1528  if (xColumns.is())
1529  {
1530  // locate the column and move in the model;
1531  // get ColumnPos
1533  Reference< css::beans::XPropertySet > xCol;
1534 
1535  // inserting must be based on the column positions
1536  sal_Int32 i;
1537  Reference< XInterface > xCurrent;
1538  for (i = 0; !xCol.is() && i < xColumns->getCount(); i++)
1539  {
1540  xCurrent.set(xColumns->getByIndex(i), css::uno::UNO_QUERY);
1541  if (xCurrent == pCol->getModel())
1542  {
1543  xCol = pCol->getModel();
1544  break;
1545  }
1546  }
1547 
1548  DBG_ASSERT(i < xColumns->getCount(), "Wrong css::sdbcx::Index");
1549  xColumns->removeByIndex(i);
1550  Any aElement;
1551  aElement <<= xCol;
1552  xColumns->insertByIndex(GetModelColumnPos(nId), aElement);
1553  pCol->setModel(xCol);
1554  // if the column which is shown here is selected ...
1555  if ( isColumnSelected(pCol) )
1556  markColumn(nId); // ... -> mark it
1557  }
1558 
1559  m_bInColumnMove = false;
1560 }
1561 
1562 void FmGridControl::InitColumnsByModels(const Reference< css::container::XIndexContainer >& xColumns)
1563 {
1564  // reset columns;
1565  // if there is only one HandleColumn, then don't
1566  if (GetModelColCount())
1567  {
1568  RemoveColumns();
1570  }
1571 
1572  if (!xColumns.is())
1573  return;
1574 
1575  SetUpdateMode(false);
1576 
1577  // inserting must be based on the column positions
1578  sal_Int32 i;
1579  Any aWidth;
1580  for (i = 0; i < xColumns->getCount(); ++i)
1581  {
1582  Reference< css::beans::XPropertySet > xCol(
1583  xColumns->getByIndex(i), css::uno::UNO_QUERY);
1584 
1585  OUString aName(
1586  comphelper::getString(xCol->getPropertyValue(FM_PROP_LABEL)));
1587 
1588  aWidth = xCol->getPropertyValue(FM_PROP_WIDTH);
1589  sal_Int32 nWidth = 0;
1590  if (aWidth >>= nWidth)
1591  nWidth = LogicToPixel(Point(nWidth, 0), MapMode(MapUnit::Map10thMM)).X();
1592 
1593  AppendColumn(aName, static_cast<sal_uInt16>(nWidth));
1594  DbGridColumn* pCol = DbGridControl::GetColumns()[ i ].get();
1595  pCol->setModel(xCol);
1596  }
1597 
1598  // and now remove the hidden columns as well
1599  // (we did not already make it in the upper loop, since we would then have gotten
1600  // problems with the IDs of the columns: AppendColumn allocates them automatically,
1601  // but the column _after_ a hidden one needs an ID increased by one ...)
1602  Any aHidden;
1603  for (i = 0; i < xColumns->getCount(); ++i)
1604  {
1605  Reference< css::beans::XPropertySet > xCol( xColumns->getByIndex(i), css::uno::UNO_QUERY);
1606  aHidden = xCol->getPropertyValue(FM_PROP_HIDDEN);
1607  if (::comphelper::getBOOL(aHidden))
1608  HideColumn(GetColumnIdFromModelPos(static_cast<sal_uInt16>(i)));
1609  }
1610 
1611  SetUpdateMode(true);
1612 }
1613 
1615  DbGridColumn* _pColumn, const Reference< XPropertySet >& _rxColumnModel,
1616  const Reference< XNameAccess >& _rxFieldsByNames, const Reference< XIndexAccess >& _rxFieldsByIndex )
1617 {
1618  DBG_ASSERT( _rxFieldsByNames == _rxFieldsByIndex, "FmGridControl::InitColumnByField: invalid container interfaces!" );
1619 
1620  // lookup the column which belongs to the control source
1621  OUString sFieldName;
1622  _rxColumnModel->getPropertyValue( FM_PROP_CONTROLSOURCE ) >>= sFieldName;
1624  _rxColumnModel->getPropertyValue( FM_PROP_BOUNDFIELD ) >>= xField;
1625 
1626 
1627  if ( !xField.is() && /*sFieldName.getLength() && */_rxFieldsByNames->hasByName( sFieldName ) ) // #i93452# do not check for name length
1628  _rxFieldsByNames->getByName( sFieldName ) >>= xField;
1629 
1630  // determine the position of this column
1631  sal_Int32 nFieldPos = -1;
1632  if ( xField.is() )
1633  {
1635  sal_Int32 nFieldCount = _rxFieldsByIndex->getCount();
1636  for ( sal_Int32 i = 0; i < nFieldCount; ++i)
1637  {
1638  _rxFieldsByIndex->getByIndex( i ) >>= xCheck;
1639  if ( xField.get() == xCheck.get() )
1640  {
1641  nFieldPos = i;
1642  break;
1643  }
1644  }
1645  }
1646 
1647  if ( xField.is() && ( nFieldPos >= 0 ) )
1648  {
1649  // some data types are not allowed
1650  sal_Int32 nDataType = DataType::OTHER;
1651  xField->getPropertyValue( FM_PROP_FIELDTYPE ) >>= nDataType;
1652 
1653  bool bIllegalType = false;
1654  switch ( nDataType )
1655  {
1656  case DataType::BLOB:
1657  case DataType::LONGVARBINARY:
1658  case DataType::BINARY:
1659  case DataType::VARBINARY:
1660  case DataType::OTHER:
1661  bIllegalType = true;
1662  break;
1663  }
1664 
1665  if ( bIllegalType )
1666  {
1667  _pColumn->SetObject( static_cast<sal_Int16>(nFieldPos) );
1668  return;
1669  }
1670  }
1671 
1672  // the control type is determined by the ColumnServiceName
1673  static const char s_sPropColumnServiceName[] = "ColumnServiceName";
1674  if ( !::comphelper::hasProperty( s_sPropColumnServiceName, _rxColumnModel ) )
1675  return;
1676 
1677  _pColumn->setModel( _rxColumnModel );
1678 
1679  OUString sColumnServiceName;
1680  _rxColumnModel->getPropertyValue( s_sPropColumnServiceName ) >>= sColumnServiceName;
1681 
1682  sal_Int32 nTypeId = getColumnTypeByModelName( sColumnServiceName );
1683  _pColumn->CreateControl( nFieldPos, xField, nTypeId );
1684 }
1685 
1686 void FmGridControl::InitColumnsByFields(const Reference< css::container::XIndexAccess >& _rxFields)
1687 {
1688  if ( !_rxFields.is() )
1689  return;
1690 
1691  // initialize columns
1692  Reference< XIndexContainer > xColumns( GetPeer()->getColumns() );
1693  Reference< XNameAccess > xFieldsAsNames( _rxFields, UNO_QUERY );
1694 
1695  // inserting must be based on the column positions
1696  for (sal_Int32 i = 0; i < xColumns->getCount(); i++)
1697  {
1698  DbGridColumn* pCol = GetColumns()[ i ].get();
1699  OSL_ENSURE(pCol,"No grid column!");
1700  if ( pCol )
1701  {
1702  Reference< XPropertySet > xColumnModel(
1703  xColumns->getByIndex( i ), css::uno::UNO_QUERY);
1704 
1705  InitColumnByField( pCol, xColumnModel, xFieldsAsNames, _rxFields );
1706  }
1707  }
1708 }
1709 
1710 void FmGridControl::HideColumn(sal_uInt16 nId)
1711 {
1713 
1714  sal_uInt16 nPos = GetModelColumnPos(nId);
1715  if (nPos == sal_uInt16(-1))
1716  return;
1717 
1718  DbGridColumn* pColumn = GetColumns()[ nPos ].get();
1719  if (pColumn->IsHidden())
1720  GetPeer()->columnHidden(pColumn);
1721 
1722  if (nId == m_nMarkedColumnId)
1723  m_nMarkedColumnId = sal_uInt16(-1);
1724 }
1725 
1727 {
1728  OSL_ENSURE(_pColumn,"Column can not be null!");
1729  bool bSelected = false;
1730  // if the column which is shown here is selected ...
1731  Reference< css::view::XSelectionSupplier > xSelSupplier(GetPeer()->getColumns(), UNO_QUERY);
1732  if ( xSelSupplier.is() )
1733  {
1734  Reference< css::beans::XPropertySet > xColumn;
1735  xSelSupplier->getSelection() >>= xColumn;
1736  bSelected = (xColumn.get() == _pColumn->getModel().get());
1737  }
1738  return bSelected;
1739 }
1740 
1741 void FmGridControl::ShowColumn(sal_uInt16 nId)
1742 {
1744 
1745  sal_uInt16 nPos = GetModelColumnPos(nId);
1746  if (nPos == sal_uInt16(-1))
1747  return;
1748 
1749  DbGridColumn* pColumn = GetColumns()[ nPos ].get();
1750  if (!pColumn->IsHidden())
1751  GetPeer()->columnVisible(pColumn);
1752 
1753  // if the column which is shown here is selected ...
1754  if ( isColumnSelected(pColumn) )
1755  markColumn(nId); // ... -> mark it
1756 }
1757 
1758 bool FmGridControl::selectBookmarks(const Sequence< Any >& _rBookmarks)
1759 {
1760  SolarMutexGuard aGuard;
1761  // need to lock the SolarMutex so that no paint call disturbs us ...
1762 
1763  if ( !m_pSeekCursor )
1764  {
1765  OSL_FAIL( "FmGridControl::selectBookmarks: no seek cursor!" );
1766  return false;
1767  }
1768 
1769  SetNoSelection();
1770 
1771  bool bAllSuccessfull = true;
1772  try
1773  {
1774  for (const Any& rBookmark : _rBookmarks)
1775  {
1776  // move the seek cursor to the row given
1777  if (m_pSeekCursor->moveToBookmark(rBookmark))
1778  SelectRow( m_pSeekCursor->getRow() - 1);
1779  else
1780  bAllSuccessfull = false;
1781  }
1782  }
1783  catch(Exception&)
1784  {
1785  OSL_FAIL("FmGridControl::selectBookmarks: could not move to one of the bookmarks!");
1786  return false;
1787  }
1788 
1789  return bAllSuccessfull;
1790 }
1791 
1793 {
1794  // lock our update so no paint-triggered seeks interfere ...
1795  SetUpdateMode(false);
1796 
1797  sal_Int32 nSelectedRows = GetSelectRowCount(), i = 0;
1798  Sequence< Any> aBookmarks(nSelectedRows);
1799  if ( nSelectedRows )
1800  {
1801  Any* pBookmarks = aBookmarks.getArray();
1802 
1803  // (I'm not sure if the problem isn't deeper: The scenario: a large table displayed by a grid with a
1804  // thread-safe cursor (dBase). On loading the sdb-cursor started a counting thread. While this counting progress
1805  // was running, I tried do delete 3 records from within the grid. Deletion caused a SeekCursor, which made a
1806  // m_pSeekCursor->moveRelative and a m_pSeekCursor->getPosition.
1807  // Unfortunately the first call caused a propertyChanged(RECORDCOUNT) which resulted in a repaint of the
1808  // navigation bar and the grid. The latter itself will result in SeekRow calls. So after (successfully) returning
1809  // from the moveRelative the getPosition returns an invalid value. And so the SeekCursor fails.
1810  // In the consequence ALL parts of code where two calls to the seek cursor are done, while the second call _relies_ on
1811  // the first one, should be secured against recursion, with a broad-minded interpretation of "recursion": if any of these
1812  // code parts is executed, no other should be accessible. But this sounds very difficult to achieve...
1813  // )
1814 
1815  // The next problem caused by the same behavior (SeekCursor causes a propertyChanged): when adjusting rows we implicitly
1816  // change our selection. So a "FirstSelected(); SeekCursor(); NextSelected();" may produce unpredictable results.
1817  // That's why we _first_ collect the indices of the selected rows and _then_ their bookmarks.
1818  long nIdx = FirstSelectedRow();
1819  while (nIdx != BROWSER_ENDOFSELECTION)
1820  {
1821  // (we misuse the bookmarks array for this ...)
1822  pBookmarks[i++] <<= static_cast<sal_Int32>(nIdx);
1823  nIdx = NextSelectedRow();
1824  }
1825  DBG_ASSERT(i == nSelectedRows, "FmGridControl::DeleteSelectedRows : could not collect the row indices !");
1826 
1827  for (i=0; i<nSelectedRows; ++i)
1828  {
1829  nIdx = ::comphelper::getINT32(pBookmarks[i]);
1830  if (IsInsertionRow(nIdx))
1831  {
1832  // do not delete empty row
1833  aBookmarks.realloc(--nSelectedRows);
1834  SelectRow(nIdx, false); // cancel selection for empty row
1835  break;
1836  }
1837 
1838  // first, position the data cursor on the selected block
1839  if (SeekCursor(nIdx))
1840  {
1841  GetSeekRow()->SetState(m_pSeekCursor.get(), true);
1842 
1843  pBookmarks[i] = m_pSeekCursor->getBookmark();
1844  }
1845  #ifdef DBG_UTIL
1846  else
1847  OSL_FAIL("FmGridControl::DeleteSelectedRows : a bookmark could not be determined !");
1848  #endif
1849  }
1850  }
1851  SetUpdateMode(true);
1852 
1853  // if one of the SeekCursor-calls failed...
1854  aBookmarks.realloc(i);
1855 
1856  // (the alternative : while collecting the bookmarks lock our propertyChanged, this should resolve both our problems.
1857  // but this would be incompatible as we need a locking flag, then...)
1858 
1859  return aBookmarks;
1860 }
1861 
1862 namespace
1863 {
1864  OUString getColumnPropertyFromPeer(FmXGridPeer* _pPeer,sal_Int32 _nPosition,const OUString& _sPropName)
1865  {
1866  OUString sRetText;
1867  if ( _pPeer && _nPosition != -1)
1868  {
1869  Reference<XIndexContainer> xIndex = _pPeer->getColumns();
1870  if ( xIndex.is() && xIndex->getCount() > _nPosition )
1871  {
1873  xIndex->getByIndex( _nPosition ) >>= xProp;
1874  if ( xProp.is() )
1875  {
1876  try {
1877  xProp->getPropertyValue( _sPropName ) >>= sRetText;
1878  } catch (UnknownPropertyException const&) {
1879  TOOLS_WARN_EXCEPTION("svx.fmcomp", "");
1880  }
1881  }
1882  }
1883  }
1884  return sRetText;
1885  }
1886 }
1887 
1888 // Object data and state
1889 OUString FmGridControl::GetAccessibleObjectName( ::vcl::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition ) const
1890 {
1891  OUString sRetText;
1892  switch( _eObjType )
1893  {
1894  case ::vcl::BBTYPE_BROWSEBOX:
1895  if ( GetPeer() )
1896  {
1897  Reference<XPropertySet> xProp(GetPeer()->getColumns(),UNO_QUERY);
1898  if ( xProp.is() )
1899  xProp->getPropertyValue(FM_PROP_NAME) >>= sRetText;
1900  }
1901  break;
1902  case ::vcl::BBTYPE_COLUMNHEADERCELL:
1903  sRetText = getColumnPropertyFromPeer(
1904  GetPeer(),
1906  sal::static_int_cast< sal_uInt16 >(_nPosition)),
1907  FM_PROP_LABEL);
1908  break;
1909  default:
1910  sRetText = DbGridControl::GetAccessibleObjectName(_eObjType,_nPosition);
1911  }
1912  return sRetText;
1913 }
1914 
1915 OUString FmGridControl::GetAccessibleObjectDescription( ::vcl::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition ) const
1916 {
1917  OUString sRetText;
1918  switch( _eObjType )
1919  {
1920  case ::vcl::BBTYPE_BROWSEBOX:
1921  if ( GetPeer() )
1922  {
1923  Reference<XPropertySet> xProp(GetPeer()->getColumns(),UNO_QUERY);
1924  if ( xProp.is() )
1925  {
1926  xProp->getPropertyValue(FM_PROP_HELPTEXT) >>= sRetText;
1927  if ( sRetText.isEmpty() )
1928  xProp->getPropertyValue(FM_PROP_DESCRIPTION) >>= sRetText;
1929  }
1930  }
1931  break;
1932  case ::vcl::BBTYPE_COLUMNHEADERCELL:
1933  sRetText = getColumnPropertyFromPeer(
1934  GetPeer(),
1936  sal::static_int_cast< sal_uInt16 >(_nPosition)),
1938  if ( sRetText.isEmpty() )
1939  sRetText = getColumnPropertyFromPeer(
1940  GetPeer(),
1942  sal::static_int_cast< sal_uInt16 >(_nPosition)),
1944 
1945  break;
1946  default:
1947  sRetText = DbGridControl::GetAccessibleObjectDescription(_eObjType,_nPosition);
1948  }
1949  return sRetText;
1950 }
1951 
1953 {
1955  // ... does it affect our columns?
1956  const MultiSelection* pColumnSelection = GetColumnSelection();
1957 
1958  sal_uInt16 nSelectedColumn =
1959  pColumnSelection && pColumnSelection->GetSelectCount()
1960  ? sal::static_int_cast< sal_uInt16 >(
1961  const_cast<MultiSelection*>(pColumnSelection)->FirstSelected())
1962  : SAL_MAX_UINT16;
1963  // the HandleColumn is not selected
1964  switch (nSelectedColumn)
1965  {
1966  case SAL_MAX_UINT16: break; // no selection
1967  case 0 : nSelectedColumn = SAL_MAX_UINT16; break;
1968  // handle col can't be selected
1969  default :
1970  // get the model col pos instead of the view col pos
1971  nSelectedColumn = GetModelColumnPos(GetColumnIdFromViewPos(nSelectedColumn - 1));
1972  break;
1973  }
1974 
1975  if (nSelectedColumn == m_nCurrentSelectedColumn)
1976  return;
1977 
1978  // BEFORE calling the select at the SelectionSupplier!
1979  m_nCurrentSelectedColumn = nSelectedColumn;
1980 
1981  if (m_bSelecting)
1982  return;
1983 
1984  m_bSelecting = true;
1985 
1986  try
1987  {
1988  Reference< XIndexAccess > xColumns = GetPeer()->getColumns();
1989  Reference< XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY);
1990  if (xSelSupplier.is())
1991  {
1992  if (nSelectedColumn != SAL_MAX_UINT16)
1993  {
1995  xColumns->getByIndex(nSelectedColumn),
1996  css::uno::UNO_QUERY);
1997  xSelSupplier->select(makeAny(xColumn));
1998  }
1999  else
2000  {
2001  xSelSupplier->select(Any());
2002  }
2003  }
2004  }
2005  catch(Exception&)
2006  {
2007  }
2008 
2009 
2010  m_bSelecting = false;
2011 }
2012 
2013 
2014 void FmGridControl::KeyInput( const KeyEvent& rKEvt )
2015 {
2016  bool bDone = false;
2017  const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
2018  if ( IsDesignMode()
2019  && !rKeyCode.IsShift()
2020  && !rKeyCode.IsMod1()
2021  && !rKeyCode.IsMod2()
2022  && GetParent() )
2023  {
2024  switch ( rKeyCode.GetCode() )
2025  {
2026  case KEY_ESCAPE:
2027  GetParent()->GrabFocus();
2028  bDone = true;
2029  break;
2030  case KEY_DELETE:
2032  {
2033  Reference< css::container::XIndexContainer > xCols(GetPeer()->getColumns());
2034  if ( xCols.is() )
2035  {
2036  try
2037  {
2038  if ( m_nCurrentSelectedColumn < xCols->getCount() )
2039  {
2041  xCols->getByIndex(m_nCurrentSelectedColumn) >>= xCol;
2042  xCols->removeByIndex(m_nCurrentSelectedColumn);
2043  ::comphelper::disposeComponent(xCol);
2044  }
2045  }
2046  catch(const Exception&)
2047  {
2048  TOOLS_WARN_EXCEPTION("svx", "exception occurred while deleting a column");
2049  }
2050  }
2051  }
2052  bDone = true;
2053  break;
2054  }
2055  }
2056  if ( !bDone )
2057  DbGridControl::KeyInput( rKEvt );
2058 }
2059 
2060 /* 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:2883
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:1710
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:413
bool m_bSelecting
Definition: fmgridcl.hxx:98
void inserted()
Definition: fmgridcl.cxx:1413
GridRowStatus GetStatus() const
Definition: gridctrl.hxx:83
#define FM_PROP_FORMATSSUPPLIER
Definition: fmprop.hxx:66
bool next()
Definition: fmtools.hxx:119
virtual void Command(const CommandEvent &rCEvt) override
Definition: fmgridcl.cxx:1003
void columnVisible(DbGridColumn const *pColumn)
Definition: fmgridif.cxx:2354
virtual sal_uInt16 AppendColumn(const OUString &rName, sal_uInt16 nWidth, sal_uInt16 nPos=HEADERBAR_APPEND, sal_uInt16 nId=sal_uInt16(-1)) override
Definition: gridctrl.cxx:1453
#define FM_PROP_FIELDTYPE
Definition: fmprop.hxx:75
std::string GetValue
const DbGridRowRef & GetEmptyRow() const
Definition: gridctrl.hxx:585
virtual OUString GetAccessibleObjectName(::vcl::AccessibleBrowseBoxObjType eObjType, sal_Int32 _nPosition=-1) const override
return the name of the specified object.
Definition: fmgridcl.cxx:1889
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:1741
const css::uno::Any & GetBookmark() const
Definition: gridctrl.hxx:87
#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:136
#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:1952
Reference< XNumberFormatsSupplier > getNumberFormats(const Reference< XConnection > &_rxConn, bool _bAlloweDefault, const Reference< XComponentContext > &_rxContext)
virtual void KeyInput(const KeyEvent &rKEvt) override
Definition: fmgridcl.cxx:2014
virtual void ColumnMoved(sal_uInt16 nId) override
Definition: fmgridcl.cxx:1521
HelpEventMode GetMode() const
sal_uInt16 GetModelColumnPos(sal_uInt16 nId) const
Definition: gridctrl.cxx:3208
sal_uInt16 GetModelColCount() const
Definition: gridctrl.hxx:429
#define TYPE_CHECKBOX
Definition: gridcols.hxx:37
bool IsDesignMode() const
Definition: gridctrl.hxx:435
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:2597
#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:1509
virtual void BeginCursorAction()
Definition: gridctrl.cxx:3260
sal_Int8 nDropAction
Definition: fmgridcl.cxx:96
virtual void ColumnMoved(sal_uInt16 nId) override
Definition: gridctrl.cxx:1499
OUString SvxResId(const char *pId)
Definition: dialmgr.cxx:28
#define SAL_MAX_UINT16
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
long LastSelectedRow()
bool IsUpdating() const
Definition: gridctrl.hxx:473
CursorWrapper * getDataSource() const
Definition: gridctrl.hxx:412
bool IsMouseEvent() const
bool IsCurrentAppending() const
Definition: gridctrl.cxx:2873
const DataFlavorExVector & GetDataFlavorExVector() const
virtual long QueryMinimumRowHeight() override
Definition: fmgridcl.cxx:1457
#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:2374
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:431
#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:889
virtual void CellModified() override
Definition: fmgridcl.cxx:1503
Point BottomRight() const
void SetNew(bool _bNew)
Definition: gridctrl.hxx:84
static OUString GetUIRootDir()
void startCursorListening()
Definition: fmgridif.cxx:2083
#define FM_COL_TIMEFIELD
Definition: gridcols.hxx:28
#define DBG_UNHANDLED_EXCEPTION(...)
const MultiSelection * GetColumnSelection() const
#define FM_COL_PATTERNFIELD
Definition: gridcols.hxx:32
#define TOOLS_WARN_EXCEPTION(area, stream)
sal_Int32 GetCurrentPos() const
Definition: gridctrl.hxx:581
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:1758
bool CompareBookmark(const Any &aLeft, const Any &aRight)
Definition: gridctrl.cxx:238
int i
#define FM_PROP_WIDTH
Definition: fmprop.hxx:49
void CellModified()
Definition: fmgridif.cxx:1315
void InitColumnsByModels(const css::uno::Reference< css::container::XIndexContainer > &xColumns)
Definition: fmgridcl.cxx:1562
virtual bool IsRowSelected(long nRow) const override
void markColumn(sal_uInt16 nId)
Definition: fmgridcl.cxx:1431
void propertyChange(const css::beans::PropertyChangeEvent &evt)
Definition: fmgridcl.cxx:1061
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:1792
SfxBindings & GetBindings()
sal_uInt16 GetItemId(sal_uInt16 nPos) const
virtual void DeleteSelectedRows() override
Definition: fmgridcl.cxx:1125
void triggerColumnContextMenu(const ::Point &_rPreferredPos)
Definition: fmgridcl.cxx:983
void AdjustDataSource(bool bFull=false)
Definition: gridctrl.cxx:1983
void SetRight(long v)
bool isColumnSelected(DbGridColumn const *_pColumn)
returns if a column is selected
Definition: fmgridcl.cxx:1726
virtual void ShowColumn(sal_uInt16 nId)
show a column
Definition: gridctrl.cxx:3116
std::unique_ptr< CursorWrapper > m_pSeekCursor
Definition: gridctrl.hxx:274
virtual void RowHeightChanged() override
Definition: fmgridcl.cxx:1464
CommandEventId GetCommand() const
virtual void CellModified() override
Definition: gridctrl.cxx:2696
virtual css::uno::Reference< css::container::XIndexContainer > SAL_CALL getColumns() override
Definition: fmgridif.cxx:1545
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:1089
virtual void EndCursorAction()
Definition: gridctrl.cxx:3277
sal_uInt16 m_nMarkedColumnId
Definition: fmgridcl.hxx:97
const DbGridRowRef & GetCurrentRow() const
Definition: gridctrl.hxx:488
void columnHidden(DbGridColumn const *pColumn)
Definition: fmgridif.cxx:2369
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:3181
#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:1020
#define Y
#define TYPE_DATEFIELD
Definition: gridcols.hxx:40
void EnableItem(sal_uInt16 nItemId, bool bEnable=true)
#define TYPE_LISTBOX
Definition: gridcols.hxx:42
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:1915
const Point & GetMousePosPixel() const
#define FM_PROP_HIDDEN
Definition: fmprop.hxx:106
void implAdjustInSolarThread(bool _bRows)
Definition: gridctrl.cxx:3217
const LanguageTag & getLocale()
void SetSeekPos(sal_Int32 nPos, GrantControlAccess)
Definition: gridctrl.hxx:535
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:1614
void setModel(const css::uno::Reference< css::beans::XPropertySet > &_xModel)
Definition: gridcell.cxx:293
tools::Rectangle GetFieldRectPixel(long nRow, sal_uInt16 nColId, bool bRelToBrowser=true) const
virtual void Command(const CommandEvent &rEvt) override
Definition: fmgridcl.cxx:1035
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:2857
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:2878
virtual void EndCursorAction() override
Definition: fmgridcl.cxx:1515
virtual void ColumnResized(sal_uInt16 nColId) override
void SetState(CursorWrapper *pCur, bool bPaintCursor)
Definition: gridctrl.cxx:694
#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:1438
const o3tl::enumarray< SvxAdjust, unsigned short > aSvxToUnoAdjust USHRT_MAX
sal_Int32 GetTotalCount() const
Definition: gridctrl.hxx:583
void ShowItem(sal_uInt16 nItemId, bool bVisible=true)
const CellControllerRef & Controller() const
#define SAL_INFO(area, stream)
OUString aName
void InsertHandleColumn()
Definition: gridctrl.cxx:781
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:781
void SetBottom(long v)
virtual VclPtr< BrowserHeader > imp_CreateHeaderBar(BrowseBox *pParent) override
Definition: fmgridcl.cxx:1425
#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:273
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:82
void set(reference_type *pBody)
void stopCursorListening()
Definition: fmgridif.cxx:2106
#define SRV_SDB_CONNECTION
Definition: fmservs.hxx:53
Reference< XColumn > xColumn
sal_Int32 GetSeekPos() const
Definition: gridctrl.hxx:582
virtual void HideColumn(sal_uInt16 nId)
hide a column
Definition: gridctrl.cxx:3087
bool hasProperty(const OUString &_rName, const Reference< XPropertySet > &_rxSet)
SfxDispatcher * GetDispatcher() const
virtual void KeyInput(const KeyEvent &rEvt) override
Definition: gridctrl.cxx:3070
void SetLeft(long v)
const DbGridRowRef & GetSeekRow() const
Definition: gridctrl.hxx:586
Reference< XSingleServiceFactory > xFactory
Reference< XModel > xModel
class FmSearchEngine - Impl class for FmSearchDialog
bool isColumnMarked(sal_uInt16 nId) const
Definition: fmgridcl.cxx:1452
#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:51
virtual void ColumnResized(sal_uInt16 nId) override
Definition: fmgridcl.cxx:1485
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:1391
sal_Int8 mnAction
InspectorAction
Definition: fmgridcl.cxx:777
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:1686
#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:2104
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)