LibreOffice Module sc (master)  1
docuno.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 <config_feature_opencl.h>
21 
22 #include <scitems.hxx>
23 #include <comphelper/sequence.hxx>
24 #include <editeng/brushitem.hxx>
25 #include <editeng/editview.hxx>
26 #include <editeng/outliner.hxx>
27 #include <o3tl/any.hxx>
28 #include <o3tl/safeint.hxx>
29 #include <svx/fmview.hxx>
30 #include <svx/svditer.hxx>
31 #include <svx/svdpage.hxx>
32 #include <svx/svxids.hrc>
33 #include <svx/unoshape.hxx>
34 
35 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
37 #include <officecfg/Office/Common.hxx>
38 #include <officecfg/Office/Calc.hxx>
39 #include <svl/numuno.hxx>
40 #include <svl/hint.hxx>
42 #include <sfx2/bindings.hxx>
43 #include <sfx2/dispatch.hxx>
44 #include <sfx2/viewfrm.hxx>
45 #include <svx/unopage.hxx>
46 #include <vcl/pdfextoutdevdata.hxx>
47 #include <vcl/print.hxx>
48 #include <vcl/svapp.hxx>
49 #include <tools/json_writer.hxx>
50 #include <tools/multisel.hxx>
51 #include <tools/UnitConversion.hxx>
53 #include <unotools/saveopt.hxx>
54 
55 #include <float.h>
56 
57 #include <com/sun/star/beans/PropertyAttribute.hpp>
58 #include <com/sun/star/util/Date.hpp>
59 #include <com/sun/star/sheet/XNamedRanges.hpp>
60 #include <com/sun/star/sheet/XLabelRanges.hpp>
61 #include <com/sun/star/sheet/XSelectedSheetsSupplier.hpp>
62 #include <com/sun/star/sheet/XUnnamedDatabaseRanges.hpp>
63 #include <com/sun/star/i18n/XForbiddenCharacters.hpp>
64 #include <com/sun/star/script/XLibraryContainer.hpp>
65 #include <com/sun/star/lang/XInitialization.hpp>
66 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
67 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
68 #include <com/sun/star/document/IndexedPropertyValues.hpp>
69 #include <com/sun/star/script/XInvocation.hpp>
70 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
71 #include <com/sun/star/beans/XFastPropertySet.hpp>
72 #include <comphelper/lok.hxx>
76 #include <comphelper/string.hxx>
78 #if HAVE_FEATURE_OPENCL
79 #include <opencl/platforminfo.hxx>
80 #endif
81 #include <sfx2/lokhelper.hxx>
82 #include <sfx2/lokcharthelper.hxx>
84 
85 #include <cellsuno.hxx>
86 #include <columnspanset.hxx>
87 #include <convuno.hxx>
88 #include <datauno.hxx>
89 #include <docfunc.hxx>
90 #include <docoptio.hxx>
91 #include <docsh.hxx>
92 #include <docuno.hxx>
93 #include <drwlayer.hxx>
94 #include <forbiuno.hxx>
95 #include <formulagroup.hxx>
96 #include <gridwin.hxx>
97 #include <hints.hxx>
98 #include <inputhdl.hxx>
99 #include <inputopt.hxx>
100 #include <interpre.hxx>
101 #include <linkuno.hxx>
102 #include <markdata.hxx>
103 #include <miscuno.hxx>
104 #include <nameuno.hxx>
105 #include <notesuno.hxx>
106 #include <optuno.hxx>
107 #include <pfuncache.hxx>
108 #include <postit.hxx>
109 #include <printfun.hxx>
110 #include <rangeutl.hxx>
111 #include <scmod.hxx>
112 #include <scresid.hxx>
113 #include <servuno.hxx>
114 #include <shapeuno.hxx>
115 #include <sheetevents.hxx>
116 #include <styleuno.hxx>
117 #include <tabvwsh.hxx>
118 #include <targuno.hxx>
119 #include <unonames.hxx>
121 #include <editsh.hxx>
122 #include <drawsh.hxx>
123 #include <drtxtob.hxx>
124 #include <transobj.hxx>
125 #include <chgtrack.hxx>
126 #include <table.hxx>
127 #include <appoptio.hxx>
128 #include <formulaopt.hxx>
129 
130 #include <strings.hrc>
131 
132 using namespace com::sun::star;
133 
134 // #i111553# provides the name of the VBA constant for this document type (e.g. 'ThisExcelDoc' for Calc)
135 constexpr OUStringLiteral SC_UNO_VBAGLOBNAME = u"VBAGlobalConstantName";
136 
137 // no Which-ID here, map only for PropertySetInfo
138 
141 {
142  static const SfxItemPropertyMapEntry aDocOptPropertyMap_Impl[] =
143  {
147  {u"" SC_UNO_BASICLIBRARIES, 0, cppu::UnoType<script::XLibraryContainer>::get(), beans::PropertyAttribute::READONLY, 0},
148  {u"" SC_UNO_DIALOGLIBRARIES, 0, cppu::UnoType<script::XLibraryContainer>::get(), beans::PropertyAttribute::READONLY, 0},
149  { SC_UNO_VBAGLOBNAME, 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0},
158  {u"" SC_UNO_FORBIDDEN, 0, cppu::UnoType<i18n::XForbiddenCharacters>::get(), beans::PropertyAttribute::READONLY, 0},
159  {u"" SC_UNO_HASDRAWPAGES, 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::READONLY, 0},
175  {u"" SC_UNO_RUNTIMEUID, 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0},
176  {u"" SC_UNO_HASVALIDSIGNATURES, 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::READONLY, 0},
180  {u"" SC_UNO_ISRECORDCHANGESPROTECTED,0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::READONLY, 0},
184  {u"" SC_UNO_REFERENCEDEVICE, 0, cppu::UnoType<awt::XDevice>::get(), beans::PropertyAttribute::READONLY, 0},
185  {u"BuildId", 0, ::cppu::UnoType<OUString>::get(), 0, 0},
188  { u"", 0, css::uno::Type(), 0, 0 }
189  };
190  return aDocOptPropertyMap_Impl;
191 }
192 
194 
196 {
197  static const SfxItemPropertyMapEntry aColumnsPropertyMap_Impl[] =
198  {
204  { u"", 0, css::uno::Type(), 0, 0 }
205  };
206  return aColumnsPropertyMap_Impl;
207 }
208 
210 {
211  static const SfxItemPropertyMapEntry aRowsPropertyMap_Impl[] =
212  {
221  // not sorted, not used with SfxItemPropertyMapEntry::GetByName
222  { u"", 0, css::uno::Type(), 0, 0 }
223  };
224  return aRowsPropertyMap_Impl;
225 }
226 
227 constexpr OUStringLiteral SCMODELOBJ_SERVICE = u"com.sun.star.sheet.SpreadsheetDocument";
228 constexpr OUStringLiteral SCDOCSETTINGS_SERVICE = u"com.sun.star.sheet.SpreadsheetDocumentSettings";
229 constexpr OUStringLiteral SCDOC_SERVICE = u"com.sun.star.document.OfficeDocument";
230 
231 SC_SIMPLE_SERVICE_INFO( ScAnnotationsObj, "ScAnnotationsObj", "com.sun.star.sheet.CellAnnotations" )
232 SC_SIMPLE_SERVICE_INFO( ScDrawPagesObj, "ScDrawPagesObj", "com.sun.star.drawing.DrawPages" )
233 SC_SIMPLE_SERVICE_INFO( ScScenariosObj, "ScScenariosObj", "com.sun.star.sheet.Scenarios" )
234 SC_SIMPLE_SERVICE_INFO( ScSpreadsheetSettingsObj, "ScSpreadsheetSettingsObj", "com.sun.star.sheet.SpreadsheetDocumentSettings" )
235 SC_SIMPLE_SERVICE_INFO( ScTableColumnsObj, "ScTableColumnsObj", "com.sun.star.table.TableColumns" )
236 SC_SIMPLE_SERVICE_INFO( ScTableRowsObj, "ScTableRowsObj", "com.sun.star.table.TableRows" )
237 SC_SIMPLE_SERVICE_INFO( ScTableSheetsObj, "ScTableSheetsObj", "com.sun.star.sheet.Spreadsheets" )
238 
239 class ScPrintUIOptions : public vcl::PrinterOptionsHelper
240 {
241 public:
243  void SetDefaults();
244 };
245 
247 {
248  const ScPrintOptions& rPrintOpt = SC_MOD()->GetPrintOptions();
249  sal_Int32 nContent = rPrintOpt.GetAllSheets() ? 0 : 1;
250  bool bSuppress = rPrintOpt.GetSkipEmpty();
251 
252  sal_Int32 nNumProps= 10, nIdx = 0;
253 
254  m_aUIProperties.resize(nNumProps);
255 
256  // load the writer PrinterOptions into the custom tab
257  m_aUIProperties[nIdx].Name = "OptionsUIFile";
258  m_aUIProperties[nIdx++].Value <<= OUString("modules/scalc/ui/printeroptions.ui");
259 
260  // create Section for spreadsheet (results in an extra tab page in dialog)
261  SvtModuleOptions aOpt;
262  OUString aAppGroupname( ScResId( SCSTR_PRINTOPT_PRODNAME ) );
263  aAppGroupname = aAppGroupname.replaceFirst( "%s", aOpt.GetModuleName( SvtModuleOptions::EModule::CALC ) );
264  m_aUIProperties[nIdx++].Value = setGroupControlOpt("tabcontrol-page2", aAppGroupname, OUString());
265 
266  // show subgroup for pages
267  m_aUIProperties[nIdx++].Value = setSubgroupControlOpt("pages", ScResId( SCSTR_PRINTOPT_PAGES ), OUString());
268 
269  // create a bool option for empty pages
270  m_aUIProperties[nIdx++].Value = setBoolControlOpt("suppressemptypages", ScResId( SCSTR_PRINTOPT_SUPPRESSEMPTY ),
271  ".HelpID:vcl:PrintDialog:IsSuppressEmptyPages:CheckBox",
272  "IsSuppressEmptyPages",
273  bSuppress);
274  // show Subgroup for print content
276  aPrintRangeOpt.maGroupHint = "PrintRange";
277  m_aUIProperties[nIdx++].Value = setSubgroupControlOpt("printrange", ScResId( SCSTR_PRINTOPT_PAGES ),
278  OUString(),
279  aPrintRangeOpt);
280 
281  // create a choice for the content to create
282  uno::Sequence< OUString > aChoices{
283  ScResId( SCSTR_PRINTOPT_ALLSHEETS ),
284  ScResId( SCSTR_PRINTOPT_SELECTEDSHEETS ),
285  ScResId( SCSTR_PRINTOPT_SELECTEDCELLS )};
286  uno::Sequence< OUString > aHelpIds{
287  ".HelpID:vcl:PrintDialog:PrintContent:ListBox"};
288  m_aUIProperties[nIdx++].Value = setChoiceListControlOpt( "printextrabox", OUString(),
289  aHelpIds, "PrintContent",
290  aChoices, nContent );
291 
292  // show Subgroup for print range
293  aPrintRangeOpt.mbInternalOnly = true;
294  m_aUIProperties[nIdx++].Value = setSubgroupControlOpt("fromwhich", ScResId( SCSTR_PRINTOPT_FROMWHICH ),
295  OUString(),
296  aPrintRangeOpt);
297 
298  // create a choice for the range to print
299  OUString aPrintRangeName( "PrintRange" );
300  aChoices.realloc( 2 );
301  aHelpIds.realloc( 2 );
302  uno::Sequence< OUString > aWidgetIds( 2 );
303  aChoices[0] = ScResId( SCSTR_PRINTOPT_PRINTALLPAGES );
304  aHelpIds[0] = ".HelpID:vcl:PrintDialog:PrintRange:RadioButton:0";
305  aWidgetIds[0] = "rbAllPages";
306  aChoices[1] = ScResId( SCSTR_PRINTOPT_PRINTPAGES );
307  aHelpIds[1] = ".HelpID:vcl:PrintDialog:PrintRange:RadioButton:1";
308  aWidgetIds[1] = "rbRangePages";
309  m_aUIProperties[nIdx++].Value = setChoiceRadiosControlOpt(aWidgetIds, OUString(),
310  aHelpIds,
311  aPrintRangeName,
312  aChoices,
313  0 );
314 
315  // create an Edit dependent on "Pages" selected
316  vcl::PrinterOptionsHelper::UIControlOptions aPageRangeOpt( aPrintRangeName, 1, true );
317  m_aUIProperties[nIdx++].Value = setEditControlOpt("pagerange", OUString(),
318  ".HelpID:vcl:PrintDialog:PageRange:Edit",
319  "PageRange", OUString(), aPageRangeOpt);
320 
321  vcl::PrinterOptionsHelper::UIControlOptions aEvenOddOpt(aPrintRangeName, 0, true);
322  m_aUIProperties[ nIdx++ ].Value = setChoiceListControlOpt("evenoddbox",
323  OUString(),
324  uno::Sequence<OUString>(),
325  "EvenOdd",
326  uno::Sequence<OUString>(),
327  0,
328  uno::Sequence< sal_Bool >(),
329  aEvenOddOpt);
330 
331  assert(nIdx == nNumProps);
332 }
333 
335 {
336  // re-initialize the default values from print options
337 
338  const ScPrintOptions& rPrintOpt = SC_MOD()->GetPrintOptions();
339  sal_Int32 nContent = rPrintOpt.GetAllSheets() ? 0 : 1;
340  bool bSuppress = rPrintOpt.GetSkipEmpty();
341 
342  for (beans::PropertyValue & rPropValue : m_aUIProperties)
343  {
344  uno::Sequence<beans::PropertyValue> aUIProp;
345  if ( rPropValue.Value >>= aUIProp )
346  {
347  for (auto& rProp : asNonConstRange(aUIProp))
348  {
349  OUString aName = rProp.Name;
350  if ( aName == "Property" )
351  {
352  beans::PropertyValue aPropertyValue;
353  if ( rProp.Value >>= aPropertyValue )
354  {
355  if ( aPropertyValue.Name == "PrintContent" )
356  {
357  aPropertyValue.Value <<= nContent;
358  rProp.Value <<= aPropertyValue;
359  }
360  else if ( aPropertyValue.Name == "IsSuppressEmptyPages" )
361  {
362  aPropertyValue.Value <<= bSuppress;
363  rProp.Value <<= aPropertyValue;
364  }
365  }
366  }
367  }
368  rPropValue.Value <<= aUIProp;
369  }
370  }
371 }
372 
374 {
375  if (pDocSh)
376  pDocSh->SetBaseModel( new ScModelObj(pDocSh) );
377 }
378 
380 {
381  ScDocument& rDoc(pDocShell->GetDocument());
382 
383  if(!rDoc.GetDrawLayer())
384  {
385  rDoc.InitDrawLayer();
386  }
387 
388  return *rDoc.GetDrawLayer(); // TTTT should be reference
389 }
390 
392  SfxBaseModel( pDocSh ),
393  aPropSet( lcl_GetDocOptPropertyMap() ),
394  pDocShell( pDocSh ),
395  maChangesListeners( m_aMutex )
396 {
397  // pDocShell may be NULL if this is the base of a ScDocOptionsObj
398  if ( pDocShell )
399  {
400  pDocShell->GetDocument().AddUnoObject(*this); // SfxModel is derived from SfxListener
401  }
402 }
403 
405 {
406  SolarMutexGuard g;
407 
408  if (pDocShell)
410 
411  if (xNumberAgg.is())
412  xNumberAgg->setDelegator(uno::Reference<uno::XInterface>());
413 
414  pPrintFuncCache.reset();
415  pPrinterOptions.reset();
416 }
417 
418 uno::Reference< uno::XAggregation> const & ScModelObj::GetFormatter()
419 {
420  // pDocShell may be NULL if this is the base of a ScDocOptionsObj
421  if ( !xNumberAgg.is() && pDocShell )
422  {
423  // setDelegator changes RefCount, so we'd better hold the reference ourselves
424  // (directly in m_refCount, so we don't delete ourselves with release())
425  osl_atomic_increment( &m_refCount );
426  // we need a reference to SvNumberFormatsSupplierObj during queryInterface,
427  // otherwise it'll be deleted
428  uno::Reference<util::XNumberFormatsSupplier> xFormatter(
430  {
431  xNumberAgg.set(uno::Reference<uno::XAggregation>( xFormatter, uno::UNO_QUERY ));
432  // extra block to force deletion of the temporary before setDelegator
433  }
434 
435  // during setDelegator no additional reference should exist
436  xFormatter = nullptr;
437 
438  if (xNumberAgg.is())
439  xNumberAgg->setDelegator( static_cast<cppu::OWeakObject*>(this) );
440  osl_atomic_decrement( &m_refCount );
441  } // if ( !xNumberAgg.is() )
442  return xNumberAgg;
443 }
444 
446 {
447  if (pDocShell)
448  return &pDocShell->GetDocument();
449  return nullptr;
450 }
451 
453 {
454  return pDocShell;
455 }
456 
458 {
459  if (pDocShell)
461 }
462 
464 {
465  if (pDocShell)
467 }
468 
470 {
471  if (pDocShell)
472  pDocShell->AfterXMLLoading(true);
473 }
474 
476 {
477  if (pDocShell)
478  return pDocShell->GetSheetSaveData();
479  return nullptr;
480 }
481 
483 {
484  if (pDocShell)
485  return pDocShell->GetFormatSaveData();
486  return nullptr;
487 }
488 
489 void ScModelObj::RepaintRange( const ScRange& rRange )
490 {
491  if (pDocShell)
493 }
494 
496 {
497  if (pDocShell)
499 }
500 
502  const Fraction& rZoomY,
503  const SCTAB nTab,
504  const ViewShellDocId& rDocId)
505 {
506  constexpr size_t nMaxIter = 5;
507  size_t nIter = 0;
508  for (SfxViewShell* pViewShell = SfxViewShell::GetFirst();
509  pViewShell && nIter < nMaxIter;
510  (pViewShell = SfxViewShell::GetNext(*pViewShell)), ++nIter)
511  {
512  if (pViewShell->GetDocId() != rDocId)
513  continue;
514 
515  ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
516  if (!pTabViewShell)
517  continue;
518 
519  ScViewData& rData = pTabViewShell->GetViewData();
520  if (rData.GetTabNo() == nTab && rData.GetZoomX() == rZoomX && rData.GetZoomY() == rZoomY)
521  return &rData;
522  }
523 
524  return nullptr;
525 }
526 
528  int nOutputWidth, int nOutputHeight,
529  int nTilePosX, int nTilePosY,
530  tools::Long nTileWidth, tools::Long nTileHeight )
531 {
532  ScTabViewShell* pViewShell = pDocShell->GetBestViewShell(false);
533 
534  // FIXME: Can this happen? What should we do?
535  if (!pViewShell)
536  return;
537 
538  ScViewData* pActiveViewData = &pViewShell->GetViewData();
539  Fraction aFracX(tools::Long(nOutputWidth * TWIPS_PER_PIXEL), nTileWidth);
540  Fraction aFracY(tools::Long(nOutputHeight * TWIPS_PER_PIXEL), nTileHeight);
541 
542  // Try to find a view that matches the tile-zoom requested by iterating over
543  // first few shells. This is to avoid switching of zooms in ScGridWindow::PaintTile
544  // and hence avoid grid-offset recomputation on all shapes which is not cheap.
545  ScViewData* pViewData = lcl_getViewMatchingDocZoomTab(aFracX, aFracY,
546  pActiveViewData->GetTabNo(), pViewShell->GetDocId());
547  if (!pViewData)
548  pViewData = pActiveViewData;
549 
550  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
551 
552  // update the size of the area we are painting
553  // FIXME we want to use only the minimal necessary size, like the
554  // following; but for the moment there is too many problems with that and
555  // interaction with editeng used for the cell editing
556  //Size aTileSize(nOutputWidth, nOutputHeight);
557  //if (pGridWindow->GetOutputSizePixel() != aTileSize)
558  // pGridWindow->SetOutputSizePixel(Size(nOutputWidth, nOutputHeight));
559  // so instead for now, set the viewport size to document size
560  Size aDocSize = getDocumentSize();
561  pGridWindow->SetOutputSizePixel(Size(aDocSize.Width() * pViewData->GetPPTX(), aDocSize.Height() * pViewData->GetPPTY()));
562 
563  pGridWindow->PaintTile( rDevice, nOutputWidth, nOutputHeight,
564  nTilePosX, nTilePosY, nTileWidth, nTileHeight );
565 
566  LokChartHelper::PaintAllChartsOnTile(rDevice, nOutputWidth, nOutputHeight,
567  nTilePosX, nTilePosY, nTileWidth, nTileHeight);
568 
569  // Draw Form controls
570  ScDrawLayer* pDrawLayer = pDocShell->GetDocument().GetDrawLayer();
571  SdrPage* pPage = pDrawLayer->GetPage(sal_uInt16(pViewData->GetTabNo()));
572  SdrView* pDrawView = pViewData->GetViewShell()->GetScDrawView();
573  tools::Rectangle aTileRect(Point(nTilePosX, nTilePosY), Size(nTileWidth, nTileHeight));
574  Size aOutputSize(nOutputWidth, nOutputHeight);
575  LokControlHandler::paintControlTile(pPage, pDrawView, *pGridWindow, rDevice, aOutputSize, aTileRect);
576 }
577 
578 void ScModelObj::setPart( int nPart, bool /*bAllowChangeFocus*/ )
579 {
580  ScViewData* pViewData = ScDocShell::GetViewData();
581  ScTabView* pTabView = pViewData->GetView();
582 
583  if (pTabView)
584  pTabView->SelectTabPage(nPart + 1);
585 }
586 
588 {
589  ScDocument& rDoc = pDocShell->GetDocument();
590  return rDoc.GetTableCount();
591 }
592 
594 {
595  ScViewData* pViewData = ScDocShell::GetViewData();
596  return pViewData ? pViewData->GetViewShell()->getPart() : 0;
597 }
598 
599 OUString ScModelObj::getPartInfo( int nPart )
600 {
601  ScViewData* pViewData = ScDocShell::GetViewData();
602  const bool bIsVisible = pViewData->GetDocument().IsVisible(nPart);
603  //FIXME: Implement IsSelected().
604  const bool bIsSelected = false; //pViewData->GetDocument()->IsSelected(nPart);
605 
606  OUString aPartInfo = "{ \"visible\": \"" +
607  OUString::number(static_cast<unsigned int>(bIsVisible)) +
608  "\", \"selected\": \"" +
609  OUString::number(static_cast<unsigned int>(bIsSelected)) +
610  "\" }";
611  return aPartInfo;
612 }
613 
614 OUString ScModelObj::getPartName( int nPart )
615 {
616  OUString sTabName;
617  ScViewData* pViewData = ScDocShell::GetViewData();
618  pViewData->GetDocument().GetName(nPart, sTabName);
619  return sTabName;
620 }
621 
622 OUString ScModelObj::getPartHash( int nPart )
623 {
624  sal_Int64 nHashCode;
625  ScViewData* pViewData = ScDocShell::GetViewData();
626  return (pViewData->GetDocument().GetHashCode(nPart, nHashCode) ? OUString::number(nHashCode) : OUString());
627 }
628 
630 {
631  SolarMutexGuard aGuard;
632 
633  ScTabViewShell* pViewShell = pDocShell->GetBestViewShell(false);
634 
635  // FIXME: Can this happen? What should we do?
636  if (!pViewShell)
637  return VclPtr<vcl::Window>();
638 
639  ScViewData* pViewData = &pViewShell->GetViewData();
640 
641  VclPtr<vcl::Window> pWindow;
642  if (pViewData)
643  {
644  pWindow = pViewData->GetActiveWin();
645 
646  LokChartHelper aChartHelper(pViewData->GetViewShell());
647  vcl::Window* pChartWindow = aChartHelper.GetWindow();
648  if (pChartWindow)
649  pWindow = pChartWindow;
650  }
651 
652  return pWindow;
653 }
654 
656 {
657  Size aSize(10, 10); // minimum size
658 
659  ScViewData* pViewData = ScDocShell::GetViewData();
660  if (!pViewData)
661  return aSize;
662 
663  SCTAB nTab = pViewData->GetTabNo();
664  SCCOL nEndCol = 0;
665  SCROW nEndRow = 0;
666  const ScDocument& rDoc = pDocShell->GetDocument();
667 
668  rDoc.GetTiledRenderingArea(nTab, nEndCol, nEndRow);
669 
670  const ScDocument* pThisDoc = &rDoc;
671  const double fPPTX = pViewData->GetPPTX();
672  const double fPPTY = pViewData->GetPPTY();
673 
674  auto GetColWidthPx = [pThisDoc, fPPTX, nTab](SCCOL nCol) {
675  const sal_uInt16 nSize = pThisDoc->GetColWidth(nCol, nTab);
676  return ScViewData::ToPixel(nSize, fPPTX);
677  };
678 
679  tools::Long nDocWidthPixel = pViewData->GetLOKWidthHelper().computePosition(nEndCol, GetColWidthPx);
680  tools::Long nDocHeightPixel = pThisDoc->GetScaledRowHeight(0, nEndRow, nTab, fPPTY);
681 
682  if (nDocWidthPixel > 0 && nDocHeightPixel > 0)
683  {
684  // convert to twips
685  aSize.setWidth(nDocWidthPixel / fPPTX);
686  aSize.setHeight(nDocHeightPixel / fPPTY);
687  }
688  else
689  {
690  // convert to twips
691  aSize.setWidth(rDoc.GetColWidth(0, nEndCol, nTab));
692  aSize.setHeight(rDoc.GetRowHeight(0, nEndRow, nTab));
693  }
694 
695  return aSize;
696 }
697 
698 
699 void ScModelObj::postKeyEvent(int nType, int nCharCode, int nKeyCode)
700 {
701  SolarMutexGuard aGuard;
702  SfxLokHelper::postKeyEventAsync(getDocWindow(), nType, nCharCode, nKeyCode);
703 }
704 
705 void ScModelObj::postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons, int nModifier)
706 {
707  SolarMutexGuard aGuard;
708 
709  ScTabViewShell* pViewShell = pDocShell->GetBestViewShell(false);
710 
711  // FIXME: Can this happen? What should we do?
712  if (!pViewShell)
713  return;
714 
715  ScViewData* pViewData = &pViewShell->GetViewData();
716 
717  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
718 
719  if (!pGridWindow)
720  return;
721 
722  // check if user hit a chart which is being edited by him
723  ScTabViewShell * pTabViewShell = pViewData->GetViewShell();
724  LokChartHelper aChartHelper(pTabViewShell);
725  if (aChartHelper.postMouseEvent(nType, nX, nY,
726  nCount, nButtons, nModifier,
727  pViewData->GetPPTX(), pViewData->GetPPTY()))
728  {
729  return;
730  }
731 
732  Point aPointTwip(nX, nY);
733 
734  // check if the user hit a chart which is being edited by someone else
735  // and, if so, skip current mouse event
736  if (nType != LOK_MOUSEEVENT_MOUSEMOVE)
737  {
738  if (LokChartHelper::HitAny(aPointTwip))
739  return;
740  }
741 
742  // Check if a control is hit
743  Point aPointHMM = o3tl::convert(aPointTwip, o3tl::Length::twip, o3tl::Length::mm100);
744  ScDrawLayer* pDrawLayer = pDocShell->GetDocument().GetDrawLayer();
745  SdrPage* pPage = pDrawLayer->GetPage(sal_uInt16(pViewData->GetTabNo()));
746  SdrView* pDrawView = pViewData->GetViewShell()->GetScDrawView();
747  if (LokControlHandler::postMouseEvent(pPage, pDrawView, *pGridWindow, nType, aPointHMM, nCount, nButtons, nModifier))
748  return;
749 
750  // Calc operates in pixels...
751  const Point aPosition(nX * pViewData->GetPPTX(), nY * pViewData->GetPPTY());
752  LokMouseEventData aMouseEventData(nType, aPosition, nCount, MouseEventModifiers::SIMPLECLICK,
753  nButtons, nModifier);
754  aMouseEventData.maLogicPosition = aPointHMM;
755  SfxLokHelper::postMouseEventAsync(pGridWindow, aMouseEventData);
756 }
757 
758 void ScModelObj::setTextSelection(int nType, int nX, int nY)
759 {
760  SolarMutexGuard aGuard;
761  ScViewData* pViewData = ScDocShell::GetViewData();
762  ScTabViewShell* pViewShell = pViewData->GetViewShell();
763 
764  LokChartHelper aChartHelper(pViewShell);
765  if (aChartHelper.setTextSelection(nType, nX, nY))
766  return;
767 
768  ScInputHandler* pInputHandler = SC_MOD()->GetInputHdl(pViewShell);
769  ScDrawView* pDrawView = pViewData->GetScDrawView();
770 
771  bool bHandled = false;
772 
773  if (pInputHandler && pInputHandler->IsInputMode())
774  {
775  // forwarding to editeng - we are editing the cell content
776  EditView* pTableView = pInputHandler->GetTableView();
777  assert(pTableView);
778 
780 
781  if (pTableView->GetOutputArea().Contains(aPoint))
782  {
783  switch (nType)
784  {
785  case LOK_SETTEXTSELECTION_START:
786  pTableView->SetCursorLogicPosition(aPoint, /*bPoint=*/false, /*bClearMark=*/false);
787  break;
788  case LOK_SETTEXTSELECTION_END:
789  pTableView->SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/false);
790  break;
791  case LOK_SETTEXTSELECTION_RESET:
792  pTableView->SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/true);
793  break;
794  default:
795  assert(false);
796  break;
797  }
798  bHandled = true;
799  }
800  }
801  else if (pDrawView && pDrawView->IsTextEdit())
802  {
803  // forwarding to editeng - we are editing the text in shape
804  OutlinerView* pOutlinerView = pDrawView->GetTextEditOutlinerView();
805  EditView& rEditView = pOutlinerView->GetEditView();
806 
808  switch (nType)
809  {
810  case LOK_SETTEXTSELECTION_START:
811  rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/false, /*bClearMark=*/false);
812  break;
813  case LOK_SETTEXTSELECTION_END:
814  rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/false);
815  break;
816  case LOK_SETTEXTSELECTION_RESET:
817  rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/true);
818  break;
819  default:
820  assert(false);
821  break;
822  }
823  bHandled = true;
824  }
825 
826  if (!bHandled)
827  {
828  // just update the cell selection
829  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
830  if (!pGridWindow)
831  return;
832 
833  // move the cell selection handles
834  pGridWindow->SetCellSelectionPixel(nType, nX * pViewData->GetPPTX(), nY * pViewData->GetPPTY());
835  }
836 }
837 
838 uno::Reference<datatransfer::XTransferable> ScModelObj::getSelection()
839 {
840  SolarMutexGuard aGuard;
841 
842  TransferableDataHelper aDataHelper;
843  ScViewData* pViewData = ScDocShell::GetViewData();
844  uno::Reference<datatransfer::XTransferable> xTransferable;
845 
846  if ( ScEditShell * pShell = dynamic_cast<ScEditShell*>( pViewData->GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) ) )
847  xTransferable = pShell->GetEditView()->GetTransferable();
848  else if ( nullptr != dynamic_cast<ScDrawTextObjectBar*>( pViewData->GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) ))
849  {
850  ScDrawView* pView = pViewData->GetScDrawView();
851  OutlinerView* pOutView = pView->GetTextEditOutlinerView();
852  if (pOutView)
853  xTransferable = pOutView->GetEditView().GetTransferable();
854  }
855  else if ( ScDrawShell * pDrawShell = dynamic_cast<ScDrawShell*>( pViewData->GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) ) )
856  xTransferable = pDrawShell->GetDrawView()->CopyToTransferable();
857  else
858  xTransferable = pViewData->GetViewShell()->CopyToTransferable();
859 
860  if (!xTransferable.is())
861  xTransferable.set( aDataHelper.GetTransferable() );
862 
863  return xTransferable;
864 }
865 
866 void ScModelObj::setGraphicSelection(int nType, int nX, int nY)
867 {
868  SolarMutexGuard aGuard;
869 
870  ScTabViewShell* pViewShell = pDocShell->GetBestViewShell(false);
871 
872  // FIXME: Can this happen? What should we do?
873  if (!pViewShell)
874  return;
875 
876  ScViewData* pViewData = &pViewShell->GetViewData();
877 
878  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
879 
880  double fPPTX = pViewData->GetPPTX();
881  double fPPTY = pViewData->GetPPTY();
882 
883  pViewShell = pViewData->GetViewShell();
884  LokChartHelper aChartHelper(pViewShell);
885  if (aChartHelper.setGraphicSelection(nType, nX, nY, fPPTX, fPPTY))
886  return;
887 
888  int nPixelX = nX * fPPTX;
889  int nPixelY = nY * fPPTY;
890 
891  switch (nType)
892  {
893  case LOK_SETGRAPHICSELECTION_START:
894  {
895  MouseEvent aClickEvent(Point(nPixelX, nPixelY), 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
896  pGridWindow->MouseButtonDown(aClickEvent);
897  MouseEvent aMoveEvent(Point(nPixelX, nPixelY), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
898  pGridWindow->MouseMove(aMoveEvent);
899  }
900  break;
901  case LOK_SETGRAPHICSELECTION_END:
902  {
903  MouseEvent aMoveEvent(Point(nPixelX, nPixelY), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
904  pGridWindow->MouseMove(aMoveEvent);
905  MouseEvent aClickEvent(Point(nPixelX, nPixelY), 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
906  pGridWindow->MouseButtonUp(aClickEvent);
907  }
908  break;
909  default:
910  assert(false);
911  break;
912  }
913 }
914 
916 {
917  SolarMutexGuard aGuard;
918 
919  ScViewData* pViewData = ScDocShell::GetViewData();
920  ScTabViewShell* pViewShell = pViewData->GetViewShell();
921 
922  // deselect the shapes & texts
923  ScDrawView* pDrawView = pViewShell->GetScDrawView();
924  if (pDrawView)
925  {
926  pDrawView->ScEndTextEdit();
927  pDrawView->UnmarkAll();
928  }
929  else
930  pViewShell->Unmark();
931 
932  // and hide the cell and text selection
933  pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, "");
934  SfxLokHelper::notifyOtherViews(pViewShell, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", "");
935 }
936 
937 void ScModelObj::setClipboard(const uno::Reference<datatransfer::clipboard::XClipboard>& xClipboard)
938 {
939  SolarMutexGuard aGuard;
940 
941  ScViewData* pViewData = ScDocShell::GetViewData();
942  if (!pViewData)
943  return;
944 
945  pViewData->GetActiveWin()->SetClipboard(xClipboard);
946 }
947 
949 {
950  SolarMutexGuard aGuard;
951 
952  ScViewData* pViewData = ScDocShell::GetViewData();
953  if (!pViewData)
954  return false;
955 
956 
958  return EditEngine::HasValidData(aDataHelper.GetTransferable());
959 }
960 
961 static void lcl_sendLOKDocumentBackground(const ScViewData* pViewData)
962 {
963  ScDocShell* pDocSh = pViewData->GetDocShell();
964  ScDocument& rDoc = pDocSh->GetDocument();
965  const ScPatternAttr *pAttr = rDoc.GetDefPattern();
966  const SfxPoolItem& rItem = pAttr->GetItem(ATTR_BACKGROUND);
967  const SvxBrushItem& rBackground = static_cast<const SvxBrushItem&>(rItem);
968  const Color& rColor = rBackground.GetColor();
969 
970  ScTabViewShell* pViewShell = pViewData->GetViewShell();
971  pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_DOCUMENT_BACKGROUND_COLOR, rColor.AsRGBHexString().toUtf8().getStr());
972 }
973 
974 void ScModelObj::setClientZoom(int nTilePixelWidth_, int nTilePixelHeight_, int nTileTwipWidth_, int nTileTwipHeight_)
975 {
976  ScViewData* pViewData = ScDocShell::GetViewData();
977 
978  if (!pViewData)
979  return;
980 
981  // Currently in LOK clients the doc background cannot be changed, so send this sparingly as possible but for every view.
982  // FIXME: Find a better place to trigger this callback where it would be called just once per view creation.
983  // Doing this in ScTabViewShell init code does not work because callbacks do not work at that point for the first view.
985 
986  const Fraction newZoomX(nTilePixelWidth_ * TWIPS_PER_PIXEL, nTileTwipWidth_);
987  const Fraction newZoomY(nTilePixelHeight_ * TWIPS_PER_PIXEL, nTileTwipHeight_);
988 
989  if (pViewData->GetZoomX() == newZoomX && pViewData->GetZoomY() == newZoomY)
990  return;
991 
992  pViewData->SetZoom(newZoomX, newZoomY, true);
993 
994  // refresh our view's take on other view's cursors & selections
995  pViewData->GetActiveWin()->updateKitOtherCursors();
996  pViewData->GetActiveWin()->updateOtherKitSelections();
997 
998  if (ScDrawView* pDrawView = pViewData->GetScDrawView())
999  pDrawView->resetGridOffsetsForAllSdrPageViews();
1000 }
1001 
1003 {
1004  ScViewData* pViewData = ScDocShell::GetViewData();
1005 
1006  if (!pViewData)
1007  return;
1008 
1009  ScTabView* pTabView = pViewData->GetView();
1010  if (!pTabView)
1011  return;
1012 
1013  pTabView->getRowColumnHeaders(rRectangle, rJsonWriter);
1014 }
1015 
1016 OString ScModelObj::getSheetGeometryData(bool bColumns, bool bRows, bool bSizes, bool bHidden,
1017  bool bFiltered, bool bGroups)
1018 {
1019  ScViewData* pViewData = ScDocShell::GetViewData();
1020 
1021  if (!pViewData)
1022  return "";
1023 
1024  ScTabView* pTabView = pViewData->GetView();
1025  if (!pTabView)
1026  return "";
1027 
1028  return pTabView->getSheetGeometryData(bColumns, bRows, bSizes, bHidden, bFiltered, bGroups);
1029 }
1030 
1032 {
1033  SolarMutexGuard aGuard;
1034 
1035  ScViewData* pViewData = ScDocShell::GetViewData();
1036 
1037  if (!pViewData)
1038  return;
1039 
1040  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
1041  if (!pGridWindow)
1042  return;
1043 
1044  rJsonWriter.put("commandName", ".uno:CellCursor");
1045  rJsonWriter.put("commandValues", pGridWindow->getCellCursor());
1046 }
1047 
1049 {
1050  SolarMutexGuard aGuard;
1051 
1052  ScViewData* pViewData = ScDocShell::GetViewData();
1053  if (!pViewData)
1054  return PointerStyle::Arrow;
1055 
1056  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
1057  if (!pGridWindow)
1058  return PointerStyle::Arrow;
1059 
1060  return pGridWindow->GetPointer();
1061 }
1062 
1064 {
1065  if (pDocShell)
1066  {
1067  if (ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack())
1068  pChangeTrack->GetChangeTrackInfo(rJson);
1069  }
1070 }
1071 
1073 {
1074  ScViewData* pViewData = ScDocShell::GetViewData();
1075  if (!pViewData)
1076  return;
1077 
1078  // set the PgUp/PgDown offset
1079  pViewData->ForcePageUpDownOffset(rRectangle.GetHeight());
1080 
1081  // Store the visible area so that we can use at places like shape insertion
1082  pViewData->setLOKVisibleArea(rRectangle);
1083 
1085  comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
1086  {
1087  ScTabView* pTabView = pViewData->GetView();
1088  if (pTabView)
1089  pTabView->extendTiledAreaIfNeeded();
1090  }
1091 }
1092 
1093 void ScModelObj::setOutlineState(bool bColumn, int nLevel, int nIndex, bool bHidden)
1094 {
1095  ScViewData* pViewData = ScDocShell::GetViewData();
1096 
1097  if (!pViewData)
1098  return;
1099 
1100  ScDBFunc* pFunc = pViewData->GetView();
1101 
1102  if (pFunc)
1103  pFunc->SetOutlineState(bColumn, nLevel, nIndex, bHidden);
1104 }
1105 
1107 {
1108  if (!pDocShell)
1109  return;
1110 
1111  ScDocument& rDoc = pDocShell->GetDocument();
1112  std::vector<sc::NoteEntry> aNotes;
1113  rDoc.GetAllNoteEntries(aNotes);
1114 
1115  auto commentsNode = rJsonWriter.startArray("comments");
1116  for (const sc::NoteEntry& aNote : aNotes)
1117  {
1118  auto commentNode = rJsonWriter.startStruct();
1119 
1120  rJsonWriter.put("id", aNote.mpNote->GetId());
1121  rJsonWriter.put("tab", aNote.maPos.Tab());
1122  rJsonWriter.put("author", aNote.mpNote->GetAuthor());
1123  rJsonWriter.put("dateTime", aNote.mpNote->GetDate());
1124  rJsonWriter.put("text", aNote.mpNote->GetText());
1125 
1126  // Calculating the cell cursor position
1127  ScViewData* pViewData = ScDocShell::GetViewData();
1128  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
1129  if (pGridWindow)
1130  {
1131  SCCOL nX = aNote.maPos.Col();
1132  SCROW nY = aNote.maPos.Row();
1133  Point aScrPos = pViewData->GetScrPos(nX, nY, pViewData->GetActivePart(), true);
1134  tools::Long nSizeXPix;
1135  tools::Long nSizeYPix;
1136  pViewData->GetMergeSizePixel(nX, nY, nSizeXPix, nSizeYPix);
1137 
1138  double fPPTX = pViewData->GetPPTX();
1139  double fPPTY = pViewData->GetPPTY();
1140  tools::Rectangle aRect(Point(aScrPos.getX() / fPPTX, aScrPos.getY() / fPPTY),
1141  Size(nSizeXPix / fPPTX, nSizeYPix / fPPTY));
1142 
1143  rJsonWriter.put("cellPos", aRect.toString());
1144  }
1145  }
1146 }
1147 
1149 {
1150  if (!pDocShell)
1151  return;
1152 
1153  ScDocument& rDoc = pDocShell->GetDocument();
1154  std::vector<sc::NoteEntry> aNotes;
1155  rDoc.GetAllNoteEntries(aNotes);
1156 
1157  auto commentsNode = rJsonWriter.startArray("commentsPos");
1158  for (const sc::NoteEntry& aNote : aNotes)
1159  {
1160  auto commentNode = rJsonWriter.startStruct();
1161 
1162  rJsonWriter.put("id", aNote.mpNote->GetId());
1163  rJsonWriter.put("tab", aNote.maPos.Tab());
1164 
1165  // Calculating the cell cursor position
1166  ScViewData* pViewData = ScDocShell::GetViewData();
1167  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
1168  if (pGridWindow)
1169  {
1170  SCCOL nX = aNote.maPos.Col();
1171  SCROW nY = aNote.maPos.Row();
1172  Point aScrPos = pViewData->GetScrPos(nX, nY, pViewData->GetActivePart(), true);
1173  tools::Long nSizeXPix;
1174  tools::Long nSizeYPix;
1175  pViewData->GetMergeSizePixel(nX, nY, nSizeXPix, nSizeYPix);
1176 
1177  double fPPTX = pViewData->GetPPTX();
1178  double fPPTY = pViewData->GetPPTY();
1179  tools::Rectangle aRect(Point(aScrPos.getX() / fPPTX, aScrPos.getY() / fPPTY),
1180  Size(nSizeXPix / fPPTX, nSizeYPix / fPPTY));
1181 
1182  rJsonWriter.put("cellPos", aRect.toString());
1183  }
1184  }
1185 }
1186 
1187 void ScModelObj::completeFunction(const OUString& rFunctionName)
1188 {
1189  ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1190  if (pHdl)
1191  {
1192  assert(!rFunctionName.isEmpty());
1193  pHdl->LOKPasteFunctionData(rFunctionName);
1194  }
1195 }
1196 
1197 void ScModelObj::initializeForTiledRendering(const css::uno::Sequence<css::beans::PropertyValue>& rArguments)
1198 {
1199  SolarMutexGuard aGuard;
1200 
1201  for (const beans::PropertyValue& rValue : rArguments)
1202  {
1203  if (rValue.Name == ".uno:SpellOnline" && rValue.Value.has<bool>())
1204  {
1205  ScDocOptions options = GetDocument()->GetDocOptions();
1206  options.SetAutoSpell(rValue.Value.get<bool>());
1207  GetDocument()->SetDocOptions(options);
1208  }
1209  }
1210 
1211  // show us the text exactly
1212  ScInputOptions aInputOptions(SC_MOD()->GetInputOptions());
1213  aInputOptions.SetTextWysiwyg(true);
1214  aInputOptions.SetReplaceCellsWarn(false);
1215  SC_MOD()->SetInputOptions(aInputOptions);
1217 
1218  // when the "This document may contain formatting or content that cannot
1219  // be saved..." dialog appears, it is auto-cancelled with tiled rendering,
1220  // causing 'Save' being disabled; so let's always save to the original
1221  // format
1222  auto xChanges = comphelper::ConfigurationChanges::create();
1223  officecfg::Office::Common::Save::Document::WarnAlienFormat::set(false, xChanges);
1224  xChanges->commit();
1225 }
1226 
1228 {
1229  SC_QUERYINTERFACE( sheet::XSpreadsheetDocument )
1230  SC_QUERYINTERFACE( document::XActionLockable )
1231  SC_QUERYINTERFACE( sheet::XCalculatable )
1232  SC_QUERYINTERFACE( util::XProtectable )
1233  SC_QUERYINTERFACE( drawing::XDrawPagesSupplier )
1234  SC_QUERYINTERFACE( sheet::XGoalSeek )
1235  SC_QUERYINTERFACE( sheet::XConsolidatable )
1236  SC_QUERYINTERFACE( sheet::XDocumentAuditing )
1237  SC_QUERYINTERFACE( style::XStyleFamiliesSupplier )
1238  SC_QUERYINTERFACE( view::XRenderable )
1239  SC_QUERYINTERFACE( document::XLinkTargetSupplier )
1240  SC_QUERYINTERFACE( beans::XPropertySet )
1241  SC_QUERYINTERFACE( lang::XMultiServiceFactory )
1242  SC_QUERYINTERFACE( lang::XServiceInfo )
1243  SC_QUERYINTERFACE( util::XChangesNotifier )
1244  SC_QUERYINTERFACE( sheet::opencl::XOpenCLSelection )
1245  SC_QUERYINTERFACE( chart2::XDataProviderAccess )
1246 
1247  uno::Any aRet(SfxBaseModel::queryInterface( rType ));
1248  if ( !aRet.hasValue()
1255  {
1256  GetFormatter();
1257  if ( xNumberAgg.is() )
1258  aRet = xNumberAgg->queryAggregation( rType );
1259  }
1260 
1261  return aRet;
1262 }
1263 
1264 void SAL_CALL ScModelObj::acquire() noexcept
1265 {
1267 }
1268 
1269 void SAL_CALL ScModelObj::release() noexcept
1270 {
1272 }
1273 
1274 uno::Sequence<uno::Type> SAL_CALL ScModelObj::getTypes()
1275 {
1276  static const uno::Sequence<uno::Type> aTypes = [&]()
1277  {
1278  uno::Sequence<uno::Type> aAggTypes;
1279  if ( GetFormatter().is() )
1280  {
1282  uno::Any aNumProv(xNumberAgg->queryAggregation(rProvType));
1283  if(auto xNumProv
1284  = o3tl::tryAccess<uno::Reference<lang::XTypeProvider>>(aNumProv))
1285  {
1286  aAggTypes = (*xNumProv)->getTypes();
1287  }
1288  }
1291  aAggTypes,
1292  uno::Sequence<uno::Type>
1293  {
1310  } );
1311  }();
1312  return aTypes;
1313 }
1314 
1315 uno::Sequence<sal_Int8> SAL_CALL ScModelObj::getImplementationId()
1316 {
1317  return css::uno::Sequence<sal_Int8>();
1318 }
1319 
1320 void ScModelObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1321 {
1322  // Not interested in reference update hints here
1323 
1324  const SfxHintId nId = rHint.GetId();
1325  if ( nId == SfxHintId::Dying )
1326  {
1327  pDocShell = nullptr; // has become invalid
1328  if (xNumberAgg.is())
1329  {
1330  SvNumberFormatsSupplierObj* pNumFmt =
1331  comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(
1332  uno::Reference<util::XNumberFormatsSupplier>(xNumberAgg, uno::UNO_QUERY) );
1333  if ( pNumFmt )
1334  pNumFmt->SetNumberFormatter( nullptr );
1335  }
1336 
1337  pPrintFuncCache.reset(); // must be deleted because it has a pointer to the DocShell
1338  m_pPrintState.reset();
1339  }
1340  else if ( nId == SfxHintId::DataChanged )
1341  {
1342  // cached data for rendering become invalid when contents change
1343  // (if a broadcast is added to SetDrawModified, is has to be tested here, too)
1344 
1345  pPrintFuncCache.reset();
1346  m_pPrintState.reset();
1347 
1348  // handle "OnCalculate" sheet events (search also for VBA event handlers)
1349  if ( pDocShell )
1350  {
1351  ScDocument& rDoc = pDocShell->GetDocument();
1352  if ( rDoc.GetVbaEventProcessor().is() )
1353  {
1354  // If the VBA event processor is set, HasAnyCalcNotification is much faster than HasAnySheetEventScript
1357  }
1358  else
1359  {
1362  }
1363  }
1364  }
1365 
1366  // always call parent - SfxBaseModel might need to handle the same hints again
1367  SfxBaseModel::Notify( rBC, rHint ); // SfxBaseModel is derived from SfxListener
1368 }
1369 
1370 // XSpreadsheetDocument
1371 
1372 uno::Reference<sheet::XSpreadsheets> SAL_CALL ScModelObj::getSheets()
1373 {
1374  SolarMutexGuard aGuard;
1375  if (pDocShell)
1376  return new ScTableSheetsObj(pDocShell);
1377  return nullptr;
1378 }
1379 
1380 css::uno::Reference< ::css::chart2::data::XDataProvider > SAL_CALL ScModelObj::createDataProvider()
1381 {
1382  if (pDocShell)
1383  {
1384  return css::uno::Reference< ::css::chart2::data::XDataProvider > (
1386  }
1387  return nullptr;
1388 }
1389 
1390 // XStyleFamiliesSupplier
1391 
1392 uno::Reference<container::XNameAccess> SAL_CALL ScModelObj::getStyleFamilies()
1393 {
1394  SolarMutexGuard aGuard;
1395  if (pDocShell)
1396  return new ScStyleFamiliesObj(pDocShell);
1397  return nullptr;
1398 }
1399 
1400 // XRenderable
1401 
1402 static OutputDevice* lcl_GetRenderDevice( const uno::Sequence<beans::PropertyValue>& rOptions )
1403 {
1404  OutputDevice* pRet = nullptr;
1405  for (const beans::PropertyValue& rProp : rOptions)
1406  {
1407  const OUString & rPropName = rProp.Name;
1408 
1409  if (rPropName == SC_UNONAME_RENDERDEV)
1410  {
1411  uno::Reference<awt::XDevice> xRenderDevice(rProp.Value, uno::UNO_QUERY);
1412  if ( xRenderDevice.is() )
1413  {
1414  VCLXDevice* pDevice = comphelper::getFromUnoTunnel<VCLXDevice>( xRenderDevice );
1415  if ( pDevice )
1416  {
1417  pRet = pDevice->GetOutputDevice().get();
1418  pRet->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
1419  }
1420  }
1421  }
1422  }
1423  return pRet;
1424 }
1425 
1426 static bool lcl_ParseTarget( const OUString& rTarget, ScRange& rTargetRange, tools::Rectangle& rTargetRect,
1427  bool& rIsSheet, ScDocument& rDoc, SCTAB nSourceTab )
1428 {
1429  // test in same order as in SID_CURRENTCELL execute
1430 
1431  ScAddress aAddress;
1432  SCTAB nNameTab;
1433  sal_Int32 nNumeric = 0;
1434 
1435  bool bRangeValid = false;
1436  bool bRectValid = false;
1437 
1438  if ( rTargetRange.Parse( rTarget, rDoc ) & ScRefFlags::VALID )
1439  {
1440  bRangeValid = true; // range reference
1441  }
1442  else if ( aAddress.Parse( rTarget, rDoc ) & ScRefFlags::VALID )
1443  {
1444  rTargetRange = aAddress;
1445  bRangeValid = true; // cell reference
1446  }
1447  else if ( ScRangeUtil::MakeRangeFromName( rTarget, rDoc, nSourceTab, rTargetRange ) ||
1448  ScRangeUtil::MakeRangeFromName( rTarget, rDoc, nSourceTab, rTargetRange, RUTL_DBASE ) )
1449  {
1450  bRangeValid = true; // named range or database range
1451  }
1452  else if ( comphelper::string::isdigitAsciiString(rTarget) &&
1453  ( nNumeric = rTarget.toInt32() ) > 0 && nNumeric <= rDoc.MaxRow()+1 )
1454  {
1455  // row number is always mapped to cell A(row) on the same sheet
1456  rTargetRange = ScAddress( 0, static_cast<SCROW>(nNumeric-1), nSourceTab ); // target row number is 1-based
1457  bRangeValid = true; // row number
1458  }
1459  else if ( rDoc.GetTable( rTarget, nNameTab ) )
1460  {
1461  rTargetRange = ScAddress(0,0,nNameTab);
1462  bRangeValid = true; // sheet name
1463  rIsSheet = true; // needs special handling (first page of the sheet)
1464  }
1465  else
1466  {
1467  // look for named drawing object
1468 
1469  ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
1470  if ( pDrawLayer )
1471  {
1472  SCTAB nTabCount = rDoc.GetTableCount();
1473  for (SCTAB i=0; i<nTabCount && !bRangeValid; i++)
1474  {
1475  SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(i));
1476  OSL_ENSURE(pPage,"Page ?");
1477  if (pPage)
1478  {
1479  SdrObjListIter aIter( pPage, SdrIterMode::DeepWithGroups );
1480  SdrObject* pObject = aIter.Next();
1481  while (pObject && !bRangeValid)
1482  {
1483  if ( ScDrawLayer::GetVisibleName( pObject ) == rTarget )
1484  {
1485  rTargetRect = pObject->GetLogicRect(); // 1/100th mm
1486  rTargetRange = rDoc.GetRange( i, rTargetRect ); // underlying cells
1487  bRangeValid = bRectValid = true; // rectangle is valid
1488  }
1489  pObject = aIter.Next();
1490  }
1491  }
1492  }
1493  }
1494  }
1495  if ( bRangeValid && !bRectValid )
1496  {
1497  // get rectangle for cell range
1498  rTargetRect = rDoc.GetMMRect( rTargetRange.aStart.Col(), rTargetRange.aStart.Row(),
1499  rTargetRange.aEnd.Col(), rTargetRange.aEnd.Row(),
1500  rTargetRange.aStart.Tab() );
1501  }
1502 
1503  return bRangeValid;
1504 }
1505 
1507  const uno::Sequence< beans::PropertyValue >& rOptions,
1508  ScMarkData& rMark,
1509  ScPrintSelectionStatus& rStatus, OUString& rPagesStr,
1510  bool& rbRenderToGraphic ) const
1511 {
1512  OSL_ENSURE( !rMark.IsMarked() && !rMark.IsMultiMarked(), "FillRenderMarkData: MarkData must be empty" );
1513  OSL_ENSURE( pDocShell, "FillRenderMarkData: DocShell must be set" );
1514 
1515  bool bDone = false;
1516 
1517  uno::Reference<frame::XController> xView;
1518 
1519  // defaults when no options are passed: all sheets, include empty pages
1520  bool bSelectedSheetsOnly = false;
1521  bool bSuppressEmptyPages = true;
1522 
1523  bool bHasPrintContent = false;
1524  sal_Int32 nPrintContent = 0; // all sheets / selected sheets / selected cells
1525  sal_Int32 nPrintRange = 0; // all pages / pages
1526  sal_Int32 nEOContent = 0; // even pages / odd pages
1527  OUString aPageRange; // "pages" edit value
1528 
1529  for( const auto& rOption : rOptions )
1530  {
1531  if ( rOption.Name == "IsOnlySelectedSheets" )
1532  {
1533  rOption.Value >>= bSelectedSheetsOnly;
1534  }
1535  else if ( rOption.Name == "IsSuppressEmptyPages" )
1536  {
1537  rOption.Value >>= bSuppressEmptyPages;
1538  }
1539  else if ( rOption.Name == "PageRange" )
1540  {
1541  rOption.Value >>= aPageRange;
1542  }
1543  else if ( rOption.Name == "PrintRange" )
1544  {
1545  rOption.Value >>= nPrintRange;
1546  }
1547  else if ( rOption.Name == "EvenOdd" )
1548  {
1549  rOption.Value >>= nEOContent;
1550  }
1551  else if ( rOption.Name == "PrintContent" )
1552  {
1553  bHasPrintContent = true;
1554  rOption.Value >>= nPrintContent;
1555  }
1556  else if ( rOption.Name == "View" )
1557  {
1558  rOption.Value >>= xView;
1559  }
1560  else if ( rOption.Name == "RenderToGraphic" )
1561  {
1562  rOption.Value >>= rbRenderToGraphic;
1563  }
1564  }
1565 
1566  // "Print Content" selection wins over "Selected Sheets" option
1567  if ( bHasPrintContent )
1568  bSelectedSheetsOnly = ( nPrintContent != 0 );
1569 
1570  uno::Reference<uno::XInterface> xInterface(aSelection, uno::UNO_QUERY);
1571  if ( xInterface.is() )
1572  {
1573  ScCellRangesBase* pSelObj = comphelper::getFromUnoTunnel<ScCellRangesBase>( xInterface );
1574  uno::Reference< drawing::XShapes > xShapes( xInterface, uno::UNO_QUERY );
1575  if ( pSelObj && pSelObj->GetDocShell() == pDocShell )
1576  {
1577  bool bSheet = ( comphelper::getFromUnoTunnel<ScTableSheetObj>( xInterface ) != nullptr );
1578  bool bCursor = pSelObj->IsCursorOnly();
1579  const ScRangeList& rRanges = pSelObj->GetRangeList();
1580 
1581  rMark.MarkFromRangeList( rRanges, false );
1582  rMark.MarkToSimple();
1583 
1584  if ( rMark.IsMultiMarked() )
1585  {
1586  // #i115266# copy behavior of old printing:
1587  // treat multiple selection like a single selection with the enclosing range
1588  ScRange aMultiMarkArea;
1589  rMark.GetMultiMarkArea( aMultiMarkArea );
1590  rMark.ResetMark();
1591  rMark.SetMarkArea( aMultiMarkArea );
1592  }
1593 
1594  if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
1595  {
1596  // a sheet object is treated like an empty selection: print the used area of the sheet
1597 
1598  if ( bCursor || bSheet ) // nothing selected -> use whole tables
1599  {
1600  rMark.ResetMark(); // doesn't change table selection
1602  }
1603  else
1605 
1606  rStatus.SetRanges( rRanges );
1607  bDone = true;
1608  }
1609  // multi selection isn't supported
1610  }
1611  else if( xShapes.is() )
1612  {
1613  //print a selected ole object
1614  // multi selection isn't supported yet
1615  uno::Reference< drawing::XShape > xShape( xShapes->getByIndex(0), uno::UNO_QUERY );
1616  SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape );
1617  if( pSdrObj && pDocShell )
1618  {
1619  ScDocument& rDoc = pDocShell->GetDocument();
1620  tools::Rectangle aObjRect = pSdrObj->GetCurrentBoundRect();
1621  SCTAB nCurrentTab = ScDocShell::GetCurTab();
1622  ScRange aRange = rDoc.GetRange( nCurrentTab, aObjRect );
1623  rMark.SetMarkArea( aRange );
1624 
1625  if( rMark.IsMarked() && !rMark.IsMultiMarked() )
1626  {
1628  bDone = true;
1629  }
1630  }
1631  }
1632  else if ( comphelper::getFromUnoTunnel<ScModelObj>( xInterface ) == this )
1633  {
1634  // render the whole document
1635  // -> no selection, all sheets
1636 
1637  SCTAB nTabCount = pDocShell->GetDocument().GetTableCount();
1638  for (SCTAB nTab = 0; nTab < nTabCount; nTab++)
1639  rMark.SelectTable( nTab, true );
1641  bDone = true;
1642  }
1643  // other selection types aren't supported
1644  }
1645 
1646  // restrict to selected sheets if a view is available
1647  uno::Reference<sheet::XSelectedSheetsSupplier> xSelectedSheets(xView, uno::UNO_QUERY);
1648  if (bSelectedSheetsOnly && xSelectedSheets.is())
1649  {
1650  const uno::Sequence<sal_Int32> aSelected = xSelectedSheets->getSelectedSheets();
1651  ScMarkData::MarkedTabsType aSelectedTabs;
1652  SCTAB nMaxTab = pDocShell->GetDocument().GetTableCount() -1;
1653  for (const auto& rSelected : aSelected)
1654  {
1655  SCTAB nSelected = static_cast<SCTAB>(rSelected);
1656  if (ValidTab(nSelected, nMaxTab))
1657  aSelectedTabs.insert(nSelected);
1658  }
1659  rMark.SetSelectedTabs(aSelectedTabs);
1660  }
1661 
1662  ScPrintOptions aNewOptions;
1663  aNewOptions.SetSkipEmpty( bSuppressEmptyPages );
1664  aNewOptions.SetAllSheets( !bSelectedSheetsOnly );
1665  rStatus.SetOptions( aNewOptions );
1666 
1667  // "PrintRange" enables (1) or disables (0) the "PageRange" edit
1668  if ( nPrintRange == 1 )
1669  rPagesStr = aPageRange;
1670  else
1671  rPagesStr.clear();
1672 
1673  return bDone;
1674 }
1675 
1676 sal_Int32 SAL_CALL ScModelObj::getRendererCount(const uno::Any& aSelection,
1677  const uno::Sequence<beans::PropertyValue>& rOptions)
1678 {
1679  SolarMutexGuard aGuard;
1680  if (!pDocShell)
1681  {
1682  throw lang::DisposedException( OUString(),
1683  static_cast< sheet::XSpreadsheetDocument* >(this) );
1684  }
1685 
1686  ScMarkData aMark(GetDocument()->GetSheetLimits());
1687  ScPrintSelectionStatus aStatus;
1688  OUString aPagesStr;
1689  bool bRenderToGraphic = false;
1690  if ( !FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr, bRenderToGraphic ) )
1691  return 0;
1692 
1693  // The same ScPrintFuncCache object in pPrintFuncCache is used as long as
1694  // the same selection is used (aStatus) and the document isn't changed
1695  // (pPrintFuncCache is cleared in Notify handler)
1696 
1697  if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) )
1698  {
1699  pPrintFuncCache.reset(new ScPrintFuncCache( pDocShell, aMark, aStatus ));
1700  }
1701  sal_Int32 nPages = pPrintFuncCache->GetPageCount();
1702 
1703  m_pPrintState.reset();
1704  maValidPages.clear();
1705 
1706  sal_Int32 nContent = 0;
1707  sal_Int32 nEOContent = 0;
1708  bool bSinglePageSheets = false;
1709  for ( const auto& rValue : rOptions)
1710  {
1711  if ( rValue.Name == "PrintRange" )
1712  {
1713  rValue.Value >>= nContent;
1714  }
1715  else if ( rValue.Name == "SinglePageSheets" )
1716  {
1717  rValue.Value >>= bSinglePageSheets;
1718  }
1719  else if ( rValue.Name == "EvenOdd" )
1720  {
1721  rValue.Value >>= nEOContent;
1722  }
1723  }
1724 
1725  if (bSinglePageSheets)
1726  {
1727  return pDocShell->GetDocument().GetTableCount();
1728  }
1729 
1730  bool bIsPrintEvenPages = (nEOContent != 1 && nContent == 0) || nContent != 0;
1731  bool bIsPrintOddPages = (nEOContent != 2 && nContent == 0) || nContent != 0;
1732 
1733  for ( sal_Int32 nPage = 1; nPage <= nPages; nPage++ )
1734  {
1735  if ( (bIsPrintEvenPages && IsOnEvenPage( nPage )) || (bIsPrintOddPages && !IsOnEvenPage( nPage )) )
1736  maValidPages.push_back( nPage );
1737  }
1738 
1739  sal_Int32 nSelectCount = static_cast<sal_Int32>( maValidPages.size() );
1740 
1741  if ( nEOContent == 1 || nEOContent == 2 ) // even pages / odd pages
1742  return nSelectCount;
1743 
1744  if ( !aPagesStr.isEmpty() )
1745  {
1746  StringRangeEnumerator aRangeEnum( aPagesStr, 0, nPages-1 );
1747  nSelectCount = aRangeEnum.size();
1748  }
1749  return (nSelectCount > 0) ? nSelectCount : 1;
1750 }
1751 
1752 static sal_Int32 lcl_GetRendererNum( sal_Int32 nSelRenderer, const OUString& rPagesStr, sal_Int32 nTotalPages )
1753 {
1754  if ( rPagesStr.isEmpty() )
1755  return nSelRenderer;
1756 
1757  StringRangeEnumerator aRangeEnum( rPagesStr, 0, nTotalPages-1 );
1758  StringRangeEnumerator::Iterator aIter = aRangeEnum.begin();
1759  StringRangeEnumerator::Iterator aEnd = aRangeEnum.end();
1760  for ( ; nSelRenderer > 0 && aIter != aEnd; --nSelRenderer )
1761  ++aIter;
1762 
1763  return *aIter; // returns -1 if reached the end
1764 }
1765 
1766 static bool lcl_renderSelectionToGraphic( bool bRenderToGraphic, const ScPrintSelectionStatus& rStatus )
1767 {
1768  return bRenderToGraphic && rStatus.GetMode() == ScPrintSelectionMode::Range;
1769 }
1770 
1771 uno::Sequence<beans::PropertyValue> SAL_CALL ScModelObj::getRenderer( sal_Int32 nSelRenderer,
1772  const uno::Any& aSelection, const uno::Sequence<beans::PropertyValue>& rOptions )
1773 {
1774  SolarMutexGuard aGuard;
1775  if (!pDocShell)
1776  {
1777  throw lang::DisposedException( OUString(),
1778  static_cast< sheet::XSpreadsheetDocument* >(this) );
1779  }
1780 
1782  ScPrintSelectionStatus aStatus;
1783  OUString aPagesStr;
1784  // #i115266# if FillRenderMarkData fails, keep nTotalPages at 0, but still handle getRenderer(0) below
1785  tools::Long nTotalPages = 0;
1786  bool bRenderToGraphic = false;
1787  bool bSinglePageSheets = false;
1788  if ( FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr, bRenderToGraphic ) )
1789  {
1790  if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) )
1791  {
1792  pPrintFuncCache.reset(new ScPrintFuncCache( pDocShell, aMark, aStatus ));
1793  }
1794  nTotalPages = pPrintFuncCache->GetPageCount();
1795  }
1796 
1797  for ( const auto& rValue : rOptions)
1798  {
1799  if ( rValue.Name == "SinglePageSheets" )
1800  {
1801  rValue.Value >>= bSinglePageSheets;
1802  break;
1803  }
1804  }
1805 
1806  if (bSinglePageSheets)
1807  nTotalPages = pDocShell->GetDocument().GetTableCount();
1808 
1809  sal_Int32 nRenderer = lcl_GetRendererNum( nSelRenderer, aPagesStr, nTotalPages );
1810 
1811  if ( nRenderer < 0 )
1812  {
1813  if ( nSelRenderer != 0 )
1814  throw lang::IllegalArgumentException();
1815 
1816  // getRenderer(0) is used to query the settings, so it must always return something
1817 
1818  awt::Size aPageSize;
1819  if (lcl_renderSelectionToGraphic( bRenderToGraphic, aStatus))
1820  {
1821  assert( aMark.IsMarked());
1822  ScRange aRange;
1823  aMark.GetMarkArea( aRange );
1825  aRange.aStart.Col(), aRange.aStart.Row(),
1826  aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
1827  aPageSize.Width = aMMRect.GetWidth();
1828  aPageSize.Height = aMMRect.GetHeight();
1829  }
1830  else
1831  {
1832  SCTAB const nCurTab = 0;
1833  ScPrintFunc aDefaultFunc( pDocShell, pDocShell->GetPrinter(), nCurTab );
1834  Size aTwips = aDefaultFunc.GetPageSize();
1835  aPageSize.Width = convertTwipToMm100(aTwips.Width());
1836  aPageSize.Height = convertTwipToMm100(aTwips.Height());
1837  }
1838 
1839  uno::Sequence<beans::PropertyValue> aSequence( comphelper::InitPropertySequence({
1840  { SC_UNONAME_PAGESIZE, uno::Any(aPageSize) }
1841  }));
1842 
1843  if( ! pPrinterOptions )
1844  pPrinterOptions.reset(new ScPrintUIOptions);
1845  else
1846  pPrinterOptions->SetDefaults();
1847  pPrinterOptions->appendPrintUIOptions( aSequence );
1848  return aSequence;
1849 
1850  }
1851 
1852  // printer is used as device (just for page layout), draw view is not needed
1853 
1854  SCTAB nTab;
1855  if (bSinglePageSheets)
1856  nTab = nSelRenderer;
1857  else if ( !maValidPages.empty() )
1858  nTab = pPrintFuncCache->GetTabForPage( maValidPages.at( nRenderer )-1 );
1859  else
1860  nTab = pPrintFuncCache->GetTabForPage( nRenderer );
1861 
1862 
1863  ScRange aRange;
1864  const ScRange* pSelRange = nullptr;
1865  if ( bSinglePageSheets )
1866  {
1867  SCCOL nStartCol;
1868  SCROW nStartRow;
1869  const ScDocument* pDocument = &pDocShell->GetDocument();
1870  pDocument->GetDataStart( nTab, nStartCol, nStartRow );
1871  SCCOL nEndCol;
1872  SCROW nEndRow;
1873  pDocument->GetPrintArea( nTab, nEndCol, nEndRow );
1874 
1875  aRange.aStart = ScAddress(nStartCol, nStartRow, nTab);
1876  aRange.aEnd = ScAddress(nEndCol, nEndRow, nTab);
1877 
1878  table::CellRangeAddress aRangeAddress( nTab,
1879  aRange.aStart.Col(), aRange.aStart.Row(),
1880  aRange.aEnd.Col(), aRange.aEnd.Row() );
1882  aRange.aStart.Col(), aRange.aStart.Row(),
1883  aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
1884 
1885  const awt::Size aPageSize(aMMRect.GetWidth(), aMMRect.GetHeight());
1886  const awt::Point aCalcPagePos(aMMRect.Left(), aMMRect.Top());
1887 
1888  uno::Sequence<beans::PropertyValue> aSequence(5);
1889  beans::PropertyValue* pArray = aSequence.getArray();
1890  pArray[0].Name = SC_UNONAME_PAGESIZE;
1891  pArray[0].Value <<= aPageSize;
1892  // #i111158# all positions are relative to the whole page, including non-printable area
1893  pArray[1].Name = SC_UNONAME_INC_NP_AREA;
1894  pArray[1].Value <<= true;
1895  pArray[2].Name = SC_UNONAME_SOURCERANGE;
1896  pArray[2].Value <<= aRangeAddress;
1897  pArray[3].Name = SC_UNONAME_CALCPAGESIZE;
1898  pArray[3].Value <<= aPageSize;
1899  pArray[4].Name = SC_UNONAME_CALCPAGEPOS;
1900  pArray[4].Value <<= aCalcPagePos;
1901 
1902  if( ! pPrinterOptions )
1903  pPrinterOptions.reset(new ScPrintUIOptions);
1904  else
1905  pPrinterOptions->SetDefaults();
1906  pPrinterOptions->appendPrintUIOptions( aSequence );
1907  return aSequence;
1908  }
1909  else if ( aMark.IsMarked() )
1910  {
1911  aMark.GetMarkArea( aRange );
1912  pSelRange = &aRange;
1913  }
1914 
1915  awt::Size aPageSize;
1916  bool bWasCellRange = false;
1917  ScRange aCellRange;
1918  if (lcl_renderSelectionToGraphic( bRenderToGraphic, aStatus))
1919  {
1920  bWasCellRange = true;
1921  aCellRange = aRange;
1923  aRange.aStart.Col(), aRange.aStart.Row(),
1924  aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
1925  aPageSize.Width = aMMRect.GetWidth();
1926  aPageSize.Height = aMMRect.GetHeight();
1927  }
1928  else
1929  {
1930  std::unique_ptr<ScPrintFunc, o3tl::default_delete<ScPrintFunc>> pPrintFunc;
1931  if (m_pPrintState && m_pPrintState->nPrintTab == nTab)
1932  pPrintFunc.reset(new ScPrintFunc(pDocShell, pDocShell->GetPrinter(), *m_pPrintState, &aStatus.GetOptions()));
1933  else
1934  pPrintFunc.reset(new ScPrintFunc(pDocShell, pDocShell->GetPrinter(), nTab,
1935  pPrintFuncCache->GetFirstAttr(nTab), nTotalPages, pSelRange, &aStatus.GetOptions()));
1936  pPrintFunc->SetRenderFlag( true );
1937 
1938  sal_Int32 nContent = 0;
1939  sal_Int32 nEOContent = 0;
1940  for ( const auto& rValue : rOptions)
1941  {
1942  if ( rValue.Name == "PrintRange" )
1943  {
1944  rValue.Value >>= nContent;
1945  }
1946  else if ( rValue.Name == "EvenOdd" )
1947  {
1948  rValue.Value >>= nEOContent;
1949  }
1950  }
1951 
1952  MultiSelection aPage;
1953  aPage.SetTotalRange( Range(0,RANGE_MAX) );
1954 
1955  bool bOddOrEven = (nContent == 0 && nEOContent == 1) || (nContent == 1 && nEOContent == 2); // even pages or odd pages
1956  // tdf#127682 when odd/even allow nRenderer of 0 even when maValidPages is empty
1957  // to allow PrinterController::abortJob to spool an empty page as part of
1958  // its abort procedure
1959  if (bOddOrEven && !maValidPages.empty())
1960  aPage.Select( maValidPages.at(nRenderer) );
1961  else
1962  aPage.Select( nRenderer+1 );
1963 
1964  tools::Long nDisplayStart = pPrintFuncCache->GetDisplayStart( nTab );
1965  tools::Long nTabStart = pPrintFuncCache->GetTabStart( nTab );
1966 
1967  (void)pPrintFunc->DoPrint( aPage, nTabStart, nDisplayStart, false, nullptr );
1968 
1969  bWasCellRange = pPrintFunc->GetLastSourceRange( aCellRange );
1970  Size aTwips = pPrintFunc->GetPageSize();
1971 
1972  if (!m_pPrintState)
1973  {
1974  m_pPrintState.reset(new ScPrintState());
1975  pPrintFunc->GetPrintState(*m_pPrintState, true);
1976  }
1977 
1978  aPageSize.Width = convertTwipToMm100(aTwips.Width());
1979  aPageSize.Height = convertTwipToMm100(aTwips.Height());
1980  }
1981 
1982  tools::Long nPropCount = bWasCellRange ? 5 : 4;
1983  uno::Sequence<beans::PropertyValue> aSequence(nPropCount);
1984  beans::PropertyValue* pArray = aSequence.getArray();
1985  pArray[0].Name = SC_UNONAME_PAGESIZE;
1986  pArray[0].Value <<= aPageSize;
1987  // #i111158# all positions are relative to the whole page, including non-printable area
1988  pArray[1].Name = SC_UNONAME_INC_NP_AREA;
1989  pArray[1].Value <<= true;
1990  if ( bWasCellRange )
1991  {
1992  table::CellRangeAddress aRangeAddress( nTab,
1993  aCellRange.aStart.Col(), aCellRange.aStart.Row(),
1994  aCellRange.aEnd.Col(), aCellRange.aEnd.Row() );
1996  aCellRange.aStart.Col(), aCellRange.aStart.Row(),
1997  aCellRange.aEnd.Col(), aCellRange.aEnd.Row(), aCellRange.aStart.Tab()));
1998 
1999  const awt::Size aCalcPageSize(aMMRect.GetWidth(), aMMRect.GetHeight());
2000  const awt::Point aCalcPagePos(aMMRect.Left(), aMMRect.Top());
2001 
2002  pArray[2].Name = SC_UNONAME_SOURCERANGE;
2003  pArray[2].Value <<= aRangeAddress;
2004  pArray[3].Name = SC_UNONAME_CALCPAGESIZE;
2005  pArray[3].Value <<= aCalcPageSize;
2006  pArray[4].Name = SC_UNONAME_CALCPAGEPOS;
2007  pArray[4].Value <<= aCalcPagePos;
2008  }
2009 
2010  if( ! pPrinterOptions )
2011  pPrinterOptions.reset(new ScPrintUIOptions);
2012  else
2013  pPrinterOptions->SetDefaults();
2014  pPrinterOptions->appendPrintUIOptions( aSequence );
2015  return aSequence;
2016 }
2017 
2018 void SAL_CALL ScModelObj::render( sal_Int32 nSelRenderer, const uno::Any& aSelection,
2019  const uno::Sequence<beans::PropertyValue>& rOptions )
2020 {
2021  SolarMutexGuard aGuard;
2022  if (!pDocShell)
2023  {
2024  throw lang::DisposedException( OUString(),
2025  static_cast< sheet::XSpreadsheetDocument* >(this) );
2026  }
2027 
2029  ScPrintSelectionStatus aStatus;
2030  OUString aPagesStr;
2031  bool bRenderToGraphic = false;
2032  bool bSinglePageSheets = false;
2033  if ( !FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr, bRenderToGraphic ) )
2034  throw lang::IllegalArgumentException();
2035 
2036  if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) )
2037  {
2038  pPrintFuncCache.reset(new ScPrintFuncCache( pDocShell, aMark, aStatus ));
2039  }
2040  tools::Long nTotalPages = pPrintFuncCache->GetPageCount();
2041 
2042  for ( const auto& rValue : rOptions)
2043  {
2044  if ( rValue.Name == "SinglePageSheets" )
2045  {
2046  rValue.Value >>= bSinglePageSheets;
2047  break;
2048  }
2049  }
2050 
2051  if (bSinglePageSheets)
2052  nTotalPages = pDocShell->GetDocument().GetTableCount();
2053 
2054  sal_Int32 nRenderer = lcl_GetRendererNum( nSelRenderer, aPagesStr, nTotalPages );
2055  if ( nRenderer < 0 )
2056  throw lang::IllegalArgumentException();
2057 
2058  OutputDevice* pDev = lcl_GetRenderDevice( rOptions );
2059  if ( !pDev )
2060  throw lang::IllegalArgumentException();
2061 
2062  ScDocument& rDoc = pDocShell->GetDocument();
2063 
2064  ScRange aRange;
2065  const ScRange* pSelRange = nullptr;
2066  if ( bSinglePageSheets )
2067  {
2068  awt::Size aPageSize;
2069  SCCOL nStartCol;
2070  SCROW nStartRow;
2071  rDoc.GetDataStart( nSelRenderer, nStartCol, nStartRow );
2072  SCCOL nEndCol;
2073  SCROW nEndRow;
2074  rDoc.GetPrintArea( nSelRenderer, nEndCol, nEndRow );
2075 
2076  aRange.aStart = ScAddress(nStartCol, nStartRow, nSelRenderer);
2077  aRange.aEnd = ScAddress(nEndCol, nEndRow, nSelRenderer);
2078 
2080  aRange.aStart.Col(), aRange.aStart.Row(),
2081  aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
2082 
2083  aPageSize.Width = aMMRect.GetWidth();
2084  aPageSize.Height = aMMRect.GetHeight();
2085 
2086  //Set visible tab
2087  SCTAB nVisTab = rDoc.GetVisibleTab();
2088  if (nVisTab != nSelRenderer)
2089  {
2090  nVisTab = nSelRenderer;
2091  rDoc.SetVisibleTab(nVisTab);
2092  }
2093 
2094  pDocShell->DoDraw(pDev, Point(0,0), Size(aPageSize.Width, aPageSize.Height), JobSetup());
2095 
2096  return;
2097  }
2098  else if ( aMark.IsMarked() )
2099  {
2100  aMark.GetMarkArea( aRange );
2101  pSelRange = &aRange;
2102  }
2103 
2104  if (lcl_renderSelectionToGraphic( bRenderToGraphic, aStatus))
2105  {
2106  // Similar to as in and when calling ScTransferObj::PaintToDev()
2107 
2108  tools::Rectangle aBound( Point(), pDev->GetOutputSize());
2109 
2110  ScViewData aViewData(rDoc);
2111 
2112  aViewData.SetTabNo( aRange.aStart.Tab() );
2113  aViewData.SetScreen( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row() );
2114 
2115  const double nPrintFactor = 1.0; /* XXX: currently (2017-08-28) is not evaluated */
2116  // The bMetaFile argument maybe could be
2117  // pDev->GetConnectMetaFile() != nullptr
2118  // but for some yet unknown reason does not draw cell content if true.
2119  ScPrintFunc::DrawToDev( rDoc, pDev, nPrintFactor, aBound, &aViewData, false /*bMetaFile*/ );
2120 
2121  return;
2122  }
2123 
2124  struct DrawViewKeeper
2125  {
2126  std::unique_ptr<FmFormView> mpDrawView;
2127  DrawViewKeeper() {}
2128  ~DrawViewKeeper()
2129  {
2130  if (mpDrawView)
2131  {
2132  mpDrawView->HideSdrPage();
2133  mpDrawView.reset();
2134  }
2135  }
2136  } aDrawViewKeeper;
2137 
2138  SCTAB nTab;
2139  if ( !maValidPages.empty() )
2140  nTab = pPrintFuncCache->GetTabForPage( maValidPages.at( nRenderer )-1 );
2141  else
2142  nTab = pPrintFuncCache->GetTabForPage( nRenderer );
2143 
2144  ScDrawLayer* pModel = rDoc.GetDrawLayer();
2145 
2146  if( pModel )
2147  {
2148  aDrawViewKeeper.mpDrawView.reset( new FmFormView(
2149  *pModel,
2150  pDev) );
2151  aDrawViewKeeper.mpDrawView->ShowSdrPage(aDrawViewKeeper.mpDrawView->GetModel()->GetPage(nTab));
2152  aDrawViewKeeper.mpDrawView->SetPrintPreview();
2153  }
2154 
2155  // to increase performance, ScPrintState might be used here for subsequent
2156  // pages of the same sheet
2157 
2158 
2159  std::unique_ptr<ScPrintFunc, o3tl::default_delete<ScPrintFunc>> pPrintFunc;
2160  if (m_pPrintState && m_pPrintState->nPrintTab == nTab
2161  && ! pSelRange) // tdf#120161 use selection to set required printed area
2162  pPrintFunc.reset(new ScPrintFunc(pDev, pDocShell, *m_pPrintState, &aStatus.GetOptions()));
2163  else
2164  pPrintFunc.reset(new ScPrintFunc(pDev, pDocShell, nTab, pPrintFuncCache->GetFirstAttr(nTab), nTotalPages, pSelRange, &aStatus.GetOptions()));
2165 
2166  pPrintFunc->SetDrawView( aDrawViewKeeper.mpDrawView.get() );
2167  pPrintFunc->SetRenderFlag( true );
2169  pPrintFunc->SetExclusivelyDrawOleAndDrawObjects();
2170 
2171  sal_Int32 nContent = 0;
2172  sal_Int32 nEOContent = 0;
2173  for ( const auto& rValue : rOptions)
2174  {
2175  if ( rValue.Name == "PrintRange" )
2176  {
2177  rValue.Value >>= nContent;
2178  }
2179  else if ( rValue.Name == "EvenOdd" )
2180  {
2181  rValue.Value >>= nEOContent;
2182  }
2183  }
2184 
2185  MultiSelection aPage;
2186  aPage.SetTotalRange( Range(0,RANGE_MAX) );
2187 
2188  bool bOddOrEven = (nContent == 0 && nEOContent == 1) || (nContent == 0 && nEOContent == 2); // even pages or odd pages
2189  // tdf#127682 when odd/even allow nRenderer of 0 even when maValidPages is empty
2190  // to allow PrinterController::abortJob to spool an empty page as part of
2191  // its abort procedure
2192  if (bOddOrEven && !maValidPages.empty())
2193  aPage.Select( maValidPages.at( nRenderer ) );
2194  else
2195  aPage.Select( nRenderer+1 );
2196 
2197  tools::Long nDisplayStart = pPrintFuncCache->GetDisplayStart( nTab );
2198  tools::Long nTabStart = pPrintFuncCache->GetTabStart( nTab );
2199 
2200  vcl::PDFExtOutDevData* pPDFData = dynamic_cast< vcl::PDFExtOutDevData* >(pDev->GetExtOutDevData() );
2201  if ( nRenderer == nTabStart )
2202  {
2203  // first page of a sheet: add outline item for the sheet name
2204 
2205  if ( pPDFData && pPDFData->GetIsExportBookmarks() )
2206  {
2207  // the sheet starts at the top of the page
2208  tools::Rectangle aArea( pDev->PixelToLogic( tools::Rectangle( 0,0,0,0 ) ) );
2209  sal_Int32 nDestID = pPDFData->CreateDest( aArea );
2210  OUString aTabName;
2211  rDoc.GetName( nTab, aTabName );
2212  // top-level
2213  pPDFData->CreateOutlineItem( -1/*nParent*/, aTabName, nDestID );
2214  }
2215  // #i56629# add the named destination stuff
2216  if( pPDFData && pPDFData->GetIsExportNamedDestinations() )
2217  {
2218  tools::Rectangle aArea( pDev->PixelToLogic( tools::Rectangle( 0,0,0,0 ) ) );
2219  OUString aTabName;
2220  rDoc.GetName( nTab, aTabName );
2221  //need the PDF page number here
2222  pPDFData->CreateNamedDest( aTabName, aArea );
2223  }
2224  }
2225 
2226  (void)pPrintFunc->DoPrint( aPage, nTabStart, nDisplayStart, true, nullptr );
2227 
2228  if (!m_pPrintState)
2229  {
2230  m_pPrintState.reset(new ScPrintState());
2231  pPrintFunc->GetPrintState(*m_pPrintState, true);
2232  }
2233 
2234  // resolve the hyperlinks for PDF export
2235 
2236  if ( !pPDFData || pPDFData->GetBookmarks().empty() )
2237  return;
2238 
2239  // iterate over the hyperlinks that were output for this page
2240 
2241  std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFData->GetBookmarks();
2242  for ( const auto& rBookmark : rBookmarks )
2243  {
2244  OUString aBookmark = rBookmark.aBookmark;
2245  if ( aBookmark.toChar() == '#' )
2246  {
2247  // try to resolve internal link
2248 
2249  OUString aTarget( aBookmark.copy( 1 ) );
2250 
2251  ScRange aTargetRange;
2252  tools::Rectangle aTargetRect; // 1/100th mm
2253  bool bIsSheet = false;
2254  bool bValid = lcl_ParseTarget( aTarget, aTargetRange, aTargetRect, bIsSheet, rDoc, nTab );
2255 
2256  if ( bValid )
2257  {
2258  sal_Int32 nPage = -1;
2259  tools::Rectangle aArea;
2260  if ( bIsSheet )
2261  {
2262  // Get first page for sheet (if nothing from that sheet is printed,
2263  // this page can show a different sheet)
2264  nPage = pPrintFuncCache->GetTabStart( aTargetRange.aStart.Tab() );
2265  aArea = pDev->PixelToLogic( tools::Rectangle( 0,0,0,0 ) );
2266  }
2267  else
2268  {
2269  pPrintFuncCache->InitLocations( aMark, pDev ); // does nothing if already initialized
2270 
2271  ScPrintPageLocation aLocation;
2272  if ( pPrintFuncCache->FindLocation( aTargetRange.aStart, aLocation ) )
2273  {
2274  nPage = aLocation.nPage;
2275 
2276  // get the rectangle of the page's cell range in 1/100th mm
2277  ScRange aLocRange = aLocation.aCellRange;
2278  tools::Rectangle aLocationMM = rDoc.GetMMRect(
2279  aLocRange.aStart.Col(), aLocRange.aStart.Row(),
2280  aLocRange.aEnd.Col(), aLocRange.aEnd.Row(),
2281  aLocRange.aStart.Tab() );
2282  tools::Rectangle aLocationPixel = aLocation.aRectangle;
2283 
2284  // Scale and move the target rectangle from aLocationMM to aLocationPixel,
2285  // to get the target rectangle in pixels.
2286  assert(aLocationPixel.GetWidth() != 0 && aLocationPixel.GetHeight() != 0);
2287 
2288  Fraction aScaleX( aLocationPixel.GetWidth(), aLocationMM.GetWidth() );
2289  Fraction aScaleY( aLocationPixel.GetHeight(), aLocationMM.GetHeight() );
2290 
2291  tools::Long nX1 = aLocationPixel.Left() + static_cast<tools::Long>( Fraction( aTargetRect.Left() - aLocationMM.Left(), 1 ) * aScaleX );
2292  tools::Long nX2 = aLocationPixel.Left() + static_cast<tools::Long>( Fraction( aTargetRect.Right() - aLocationMM.Left(), 1 ) * aScaleX );
2293  tools::Long nY1 = aLocationPixel.Top() + static_cast<tools::Long>( Fraction( aTargetRect.Top() - aLocationMM.Top(), 1 ) * aScaleY );
2294  tools::Long nY2 = aLocationPixel.Top() + static_cast<tools::Long>( Fraction( aTargetRect.Bottom() - aLocationMM.Top(), 1 ) * aScaleY );
2295 
2296  if ( nX1 > aLocationPixel.Right() ) nX1 = aLocationPixel.Right();
2297  if ( nX2 > aLocationPixel.Right() ) nX2 = aLocationPixel.Right();
2298  if ( nY1 > aLocationPixel.Bottom() ) nY1 = aLocationPixel.Bottom();
2299  if ( nY2 > aLocationPixel.Bottom() ) nY2 = aLocationPixel.Bottom();
2300 
2301  // The link target area is interpreted using the device's MapMode at
2302  // the time of the CreateDest call, so PixelToLogic can be used here,
2303  // regardless of the MapMode that is actually selected.
2304  aArea = pDev->PixelToLogic( tools::Rectangle( nX1, nY1, nX2, nY2 ) );
2305  }
2306  }
2307 
2308  if ( nPage >= 0 )
2309  pPDFData->SetLinkDest( rBookmark.nLinkId, pPDFData->CreateDest( aArea, nPage ) );
2310  }
2311  }
2312  else
2313  {
2314  // external link, use as-is
2315  pPDFData->SetLinkURL( rBookmark.nLinkId, aBookmark );
2316  }
2317  }
2318  rBookmarks.clear();
2319 }
2320 
2321 // XLinkTargetSupplier
2322 
2323 uno::Reference<container::XNameAccess> SAL_CALL ScModelObj::getLinks()
2324 {
2325  SolarMutexGuard aGuard;
2326  if (pDocShell)
2327  return new ScLinkTargetTypesObj(pDocShell);
2328  return nullptr;
2329 }
2330 
2331 // XActionLockable
2332 
2334 {
2335  SolarMutexGuard aGuard;
2336  bool bLocked = false;
2337  if (pDocShell)
2338  bLocked = ( pDocShell->GetLockCount() != 0 );
2339  return bLocked;
2340 }
2341 
2343 {
2344  SolarMutexGuard aGuard;
2345  if (pDocShell)
2347 }
2348 
2350 {
2351  SolarMutexGuard aGuard;
2352  if (pDocShell)
2354 }
2355 
2356 void SAL_CALL ScModelObj::setActionLocks( sal_Int16 nLock )
2357 {
2358  SolarMutexGuard aGuard;
2359  if (pDocShell)
2360  pDocShell->SetLockCount(nLock);
2361 }
2362 
2363 sal_Int16 SAL_CALL ScModelObj::resetActionLocks()
2364 {
2365  SolarMutexGuard aGuard;
2366  sal_uInt16 nRet = 0;
2367  if (pDocShell)
2368  {
2369  nRet = pDocShell->GetLockCount();
2370  pDocShell->SetLockCount(0);
2371  }
2372  return nRet;
2373 }
2374 
2376 {
2377  SolarMutexGuard aGuard;
2379  if (pDocShell)
2380  pDocShell->LockPaint();
2381 }
2382 
2384 {
2385  SolarMutexGuard aGuard;
2386  if (hasControllersLocked())
2387  {
2389  if (pDocShell)
2391  }
2392 }
2393 
2394 // XCalculate
2395 
2396 void SAL_CALL ScModelObj::calculate()
2397 {
2398  SolarMutexGuard aGuard;
2399  if (pDocShell)
2400  {
2401  comphelper::ProfileZone aZone("calculate");
2402  pDocShell->DoRecalc(true);
2403  }
2404  else
2405  {
2406  OSL_FAIL("no DocShell");
2407  }
2408 }
2409 
2411 {
2412  SolarMutexGuard aGuard;
2413  if (pDocShell)
2414  {
2415  comphelper::ProfileZone aZone("calculateAll");
2417  }
2418  else
2419  {
2420  OSL_FAIL("no DocShell");
2421  }
2422 }
2423 
2425 {
2426  SolarMutexGuard aGuard;
2427  if (pDocShell)
2428  return pDocShell->GetDocument().GetAutoCalc();
2429 
2430  OSL_FAIL("no DocShell");
2431  return false;
2432 }
2433 
2435 {
2436  bool bEnabled(bEnabledIn);
2437  SolarMutexGuard aGuard;
2438  if (pDocShell)
2439  {
2440  ScDocument& rDoc = pDocShell->GetDocument();
2441  if ( rDoc.GetAutoCalc() != bEnabled )
2442  {
2443  rDoc.SetAutoCalc( bEnabled );
2445  }
2446  }
2447  else
2448  {
2449  OSL_FAIL("no DocShell");
2450  }
2451 }
2452 
2453 // XProtectable
2454 
2455 void SAL_CALL ScModelObj::protect( const OUString& aPassword )
2456 {
2457  SolarMutexGuard aGuard;
2458  // #i108245# if already protected, don't change anything
2460  {
2461  pDocShell->GetDocFunc().Protect( TABLEID_DOC, aPassword );
2462  }
2463 }
2464 
2465 void SAL_CALL ScModelObj::unprotect( const OUString& aPassword )
2466 {
2467  SolarMutexGuard aGuard;
2468  if (pDocShell)
2469  {
2470  bool bDone = pDocShell->GetDocFunc().Unprotect( TABLEID_DOC, aPassword, true );
2471  if (!bDone)
2472  throw lang::IllegalArgumentException();
2473  }
2474 }
2475 
2477 {
2478  SolarMutexGuard aGuard;
2479  if (pDocShell)
2480  return pDocShell->GetDocument().IsDocProtected();
2481 
2482  OSL_FAIL("no DocShell");
2483  return false;
2484 }
2485 
2486 // XDrawPagesSupplier
2487 
2488 uno::Reference<drawing::XDrawPages> SAL_CALL ScModelObj::getDrawPages()
2489 {
2490  SolarMutexGuard aGuard;
2491  if (pDocShell)
2492  return new ScDrawPagesObj(pDocShell);
2493 
2494  OSL_FAIL("no DocShell");
2495  return nullptr;
2496 }
2497 
2498 // XGoalSeek
2499 
2500 sheet::GoalResult SAL_CALL ScModelObj::seekGoal(
2501  const table::CellAddress& aFormulaPosition,
2502  const table::CellAddress& aVariablePosition,
2503  const OUString& aGoalValue )
2504 {
2505  SolarMutexGuard aGuard;
2506  sheet::GoalResult aResult;
2507  aResult.Divergence = DBL_MAX; // not found
2508  if (pDocShell)
2509  {
2511  ScDocument& rDoc = pDocShell->GetDocument();
2512  double fValue = 0.0;
2513  bool bFound = rDoc.Solver(
2514  static_cast<SCCOL>(aFormulaPosition.Column), static_cast<SCROW>(aFormulaPosition.Row), aFormulaPosition.Sheet,
2515  static_cast<SCCOL>(aVariablePosition.Column), static_cast<SCROW>(aVariablePosition.Row), aVariablePosition.Sheet,
2516  aGoalValue, fValue );
2517  aResult.Result = fValue;
2518  if (bFound)
2519  aResult.Divergence = 0.0;
2520  }
2521  return aResult;
2522 }
2523 
2524 // XConsolidatable
2525 
2526 uno::Reference<sheet::XConsolidationDescriptor> SAL_CALL ScModelObj::createConsolidationDescriptor(
2527  sal_Bool bEmpty )
2528 {
2529  SolarMutexGuard aGuard;
2531  if ( pDocShell && !bEmpty )
2532  {
2533  ScDocument& rDoc = pDocShell->GetDocument();
2534  const ScConsolidateParam* pParam = rDoc.GetConsolidateDlgData();
2535  if (pParam)
2536  pNew->SetParam( *pParam );
2537  }
2538  return pNew;
2539 }
2540 
2542  const uno::Reference<sheet::XConsolidationDescriptor>& xDescriptor )
2543 {
2544  SolarMutexGuard aGuard;
2545  // in theory, this could also be a different object, so use only
2546  // public XConsolidationDescriptor interface to copy the data into
2547  // ScConsolidationDescriptor object
2549 
2551  xImpl->setFunction( xDescriptor->getFunction() );
2552  xImpl->setSources( xDescriptor->getSources() );
2553  xImpl->setStartOutputPosition( xDescriptor->getStartOutputPosition() );
2554  xImpl->setUseColumnHeaders( xDescriptor->getUseColumnHeaders() );
2555  xImpl->setUseRowHeaders( xDescriptor->getUseRowHeaders() );
2556  xImpl->setInsertLinks( xDescriptor->getInsertLinks() );
2557 
2558  if (pDocShell)
2559  {
2560  const ScConsolidateParam& rParam = xImpl->GetParam();
2561  pDocShell->DoConsolidate( rParam );
2562  pDocShell->GetDocument().SetConsolidateDlgData( std::unique_ptr<ScConsolidateParam>(new ScConsolidateParam(rParam)) );
2563  }
2564 }
2565 
2566 // XDocumentAuditing
2567 
2569 {
2570  SolarMutexGuard aGuard;
2571  if (pDocShell)
2573 }
2574 
2575 // XViewDataSupplier
2576 uno::Reference< container::XIndexAccess > SAL_CALL ScModelObj::getViewData( )
2577 {
2578  uno::Reference < container::XIndexAccess > xRet( SfxBaseModel::getViewData() );
2579 
2580  if( !xRet.is() )
2581  {
2582  SolarMutexGuard aGuard;
2583  if (pDocShell && pDocShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED)
2584  {
2585  uno::Reference < container::XIndexContainer > xCont = document::IndexedPropertyValues::create( ::comphelper::getProcessComponentContext() );
2586  xRet.set( xCont, uno::UNO_QUERY_THROW );
2587 
2588  uno::Sequence< beans::PropertyValue > aSeq;
2589  aSeq.realloc(3);
2590  OUString sName;
2592  OUString sOUName(sName);
2593  aSeq[0].Name = SC_ACTIVETABLE;
2594  aSeq[0].Value <<= sOUName;
2595  SCCOL nPosLeft = pDocShell->GetDocument().GetPosLeft();
2596  aSeq[1].Name = SC_POSITIONLEFT;
2597  aSeq[1].Value <<= nPosLeft;
2598  SCROW nPosTop = pDocShell->GetDocument().GetPosTop();
2599  aSeq[2].Name = SC_POSITIONTOP;
2600  aSeq[2].Value <<= nPosTop;
2601  xCont->insertByIndex( 0, uno::makeAny( aSeq ) );
2602  }
2603  }
2604 
2605  return xRet;
2606 }
2607 
2608 // XPropertySet (Doc-Options)
2610 
2611 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScModelObj::getPropertySetInfo()
2612 {
2613  SolarMutexGuard aGuard;
2614  static uno::Reference<beans::XPropertySetInfo> aRef(
2616  return aRef;
2617 }
2618 
2620  const OUString& aPropertyName, const uno::Any& aValue )
2621 {
2622  SolarMutexGuard aGuard;
2623 
2624  if (!pDocShell)
2625  return;
2626 
2627  ScDocument& rDoc = pDocShell->GetDocument();
2628  const ScDocOptions& rOldOpt = rDoc.GetDocOptions();
2629  ScDocOptions aNewOpt = rOldOpt;
2630  // Don't recalculate while loading XML, when the formula text is stored
2631  // Recalculation after loading is handled separately.
2632  bool bHardRecalc = !rDoc.IsImportingXML();
2633 
2634  bool bOpt = ScDocOptionsHelper::setPropertyValue( aNewOpt, aPropSet.getPropertyMap(), aPropertyName, aValue );
2635  if (bOpt)
2636  {
2637  // done...
2638  if ( aPropertyName == SC_UNO_IGNORECASE ||
2639  aPropertyName == SC_UNONAME_REGEXP ||
2640  aPropertyName == SC_UNONAME_WILDCARDS ||
2641  aPropertyName == SC_UNO_LOOKUPLABELS )
2642  bHardRecalc = false;
2643  }
2644  else if ( aPropertyName == SC_UNONAME_CLOCAL )
2645  {
2646  lang::Locale aLocale;
2647  if ( aValue >>= aLocale )
2648  {
2649  LanguageType eLatin, eCjk, eCtl;
2650  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2651  eLatin = ScUnoConversion::GetLanguage(aLocale);
2652  rDoc.SetLanguage( eLatin, eCjk, eCtl );
2653  }
2654  }
2655  else if ( aPropertyName == SC_UNO_CODENAME )
2656  {
2657  OUString sCodeName;
2658  if ( aValue >>= sCodeName )
2659  rDoc.SetCodeName( sCodeName );
2660  }
2661  else if ( aPropertyName == SC_UNO_CJK_CLOCAL )
2662  {
2663  lang::Locale aLocale;
2664  if ( aValue >>= aLocale )
2665  {
2666  LanguageType eLatin, eCjk, eCtl;
2667  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2668  eCjk = ScUnoConversion::GetLanguage(aLocale);
2669  rDoc.SetLanguage( eLatin, eCjk, eCtl );
2670  }
2671  }
2672  else if ( aPropertyName == SC_UNO_CTL_CLOCAL )
2673  {
2674  lang::Locale aLocale;
2675  if ( aValue >>= aLocale )
2676  {
2677  LanguageType eLatin, eCjk, eCtl;
2678  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2679  eCtl = ScUnoConversion::GetLanguage(aLocale);
2680  rDoc.SetLanguage( eLatin, eCjk, eCtl );
2681  }
2682  }
2683  else if ( aPropertyName == SC_UNO_APPLYFMDES )
2684  {
2685  // model is created if not there
2686  ScDrawLayer* pModel = pDocShell->MakeDrawLayer();
2688 
2689  SfxBindings* pBindings = pDocShell->GetViewBindings();
2690  if (pBindings)
2691  pBindings->Invalidate( SID_FM_OPEN_READONLY );
2692  }
2693  else if ( aPropertyName == SC_UNO_AUTOCONTFOC )
2694  {
2695  // model is created if not there
2696  ScDrawLayer* pModel = pDocShell->MakeDrawLayer();
2698 
2699  SfxBindings* pBindings = pDocShell->GetViewBindings();
2700  if (pBindings)
2701  pBindings->Invalidate( SID_FM_AUTOCONTROLFOCUS );
2702  }
2703  else if ( aPropertyName == SC_UNO_ISLOADED )
2704  {
2706  }
2707  else if ( aPropertyName == SC_UNO_ISUNDOENABLED )
2708  {
2709  bool bUndoEnabled = ScUnoHelpFunctions::GetBoolFromAny( aValue );
2710  rDoc.EnableUndo( bUndoEnabled );
2712  bUndoEnabled
2713  ? officecfg::Office::Common::Undo::Steps::get() : 0);
2714  }
2715  else if ( aPropertyName == SC_UNO_RECORDCHANGES )
2716  {
2717  bool bRecordChangesEnabled = ScUnoHelpFunctions::GetBoolFromAny( aValue );
2718 
2719  bool bChangeAllowed = true;
2720  if (!bRecordChangesEnabled)
2721  bChangeAllowed = !pDocShell->HasChangeRecordProtection();
2722 
2723  if (bChangeAllowed)
2724  pDocShell->SetChangeRecording(bRecordChangesEnabled);
2725  }
2726  else if ( aPropertyName == SC_UNO_ISADJUSTHEIGHTENABLED )
2727  {
2728  if( ScUnoHelpFunctions::GetBoolFromAny( aValue ) )
2729  rDoc.UnlockAdjustHeight();
2730  else
2731  rDoc.LockAdjustHeight();
2732  }
2733  else if ( aPropertyName == SC_UNO_ISEXECUTELINKENABLED )
2734  {
2736  }
2737  else if ( aPropertyName == SC_UNO_ISCHANGEREADONLYENABLED )
2738  {
2740  }
2741  else if ( aPropertyName == "BuildId" )
2742  {
2743  aValue >>= maBuildId;
2744  }
2745  else if ( aPropertyName == "SavedObject" ) // set from chart after saving
2746  {
2747  OUString aObjName;
2748  aValue >>= aObjName;
2749  if ( !aObjName.isEmpty() )
2750  rDoc.RestoreChartListener( aObjName );
2751  }
2752  else if ( aPropertyName == SC_UNO_INTEROPGRABBAG )
2753  {
2754  setGrabBagItem(aValue);
2755  }
2756 
2757  if ( aNewOpt != rOldOpt )
2758  {
2759  rDoc.SetDocOptions( aNewOpt );
2761  if ( bHardRecalc )
2764  }
2765 }
2766 
2767 uno::Any SAL_CALL ScModelObj::getPropertyValue( const OUString& aPropertyName )
2768 {
2769  SolarMutexGuard aGuard;
2770  uno::Any aRet;
2771 
2772  if (pDocShell)
2773  {
2774  ScDocument& rDoc = pDocShell->GetDocument();
2775  const ScDocOptions& rOpt = rDoc.GetDocOptions();
2776  aRet = ScDocOptionsHelper::getPropertyValue( rOpt, aPropSet.getPropertyMap(), aPropertyName );
2777  if ( aRet.hasValue() )
2778  {
2779  // done...
2780  }
2781  else if ( aPropertyName == SC_UNONAME_CLOCAL )
2782  {
2783  LanguageType eLatin, eCjk, eCtl;
2784  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2785 
2786  lang::Locale aLocale;
2787  ScUnoConversion::FillLocale( aLocale, eLatin );
2788  aRet <<= aLocale;
2789  }
2790  else if ( aPropertyName == SC_UNO_CODENAME )
2791  {
2792  aRet <<= rDoc.GetCodeName();
2793  }
2794 
2795  else if ( aPropertyName == SC_UNO_CJK_CLOCAL )
2796  {
2797  LanguageType eLatin, eCjk, eCtl;
2798  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2799 
2800  lang::Locale aLocale;
2801  ScUnoConversion::FillLocale( aLocale, eCjk );
2802  aRet <<= aLocale;
2803  }
2804  else if ( aPropertyName == SC_UNO_CTL_CLOCAL )
2805  {
2806  LanguageType eLatin, eCjk, eCtl;
2807  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2808 
2809  lang::Locale aLocale;
2810  ScUnoConversion::FillLocale( aLocale, eCtl );
2811  aRet <<= aLocale;
2812  }
2813  else if ( aPropertyName == SC_UNO_NAMEDRANGES )
2814  {
2815  aRet <<= uno::Reference<sheet::XNamedRanges>(new ScGlobalNamedRangesObj( pDocShell ));
2816  }
2817  else if ( aPropertyName == SC_UNO_DATABASERNG )
2818  {
2819  aRet <<= uno::Reference<sheet::XDatabaseRanges>(new ScDatabaseRangesObj( pDocShell ));
2820  }
2821  else if ( aPropertyName == SC_UNO_UNNAMEDDBRNG )
2822  {
2823  aRet <<= uno::Reference<sheet::XUnnamedDatabaseRanges>(new ScUnnamedDatabaseRangesObj(pDocShell));
2824  }
2825  else if ( aPropertyName == SC_UNO_COLLABELRNG )
2826  {
2827  aRet <<= uno::Reference<sheet::XLabelRanges>(new ScLabelRangesObj( pDocShell, true ));
2828  }
2829  else if ( aPropertyName == SC_UNO_ROWLABELRNG )
2830  {
2831  aRet <<= uno::Reference<sheet::XLabelRanges>(new ScLabelRangesObj( pDocShell, false ));
2832  }
2833  else if ( aPropertyName == SC_UNO_AREALINKS )
2834  {
2835  aRet <<= uno::Reference<sheet::XAreaLinks>(new ScAreaLinksObj( pDocShell ));
2836  }
2837  else if ( aPropertyName == SC_UNO_DDELINKS )
2838  {
2839  aRet <<= uno::Reference<container::XNameAccess>(new ScDDELinksObj( pDocShell ));
2840  }
2841  else if ( aPropertyName == SC_UNO_EXTERNALDOCLINKS )
2842  {
2843  aRet <<= uno::Reference<sheet::XExternalDocLinks>(new ScExternalDocLinksObj(pDocShell));
2844  }
2845  else if ( aPropertyName == SC_UNO_SHEETLINKS )
2846  {
2847  aRet <<= uno::Reference<container::XNameAccess>(new ScSheetLinksObj( pDocShell ));
2848  }
2849  else if ( aPropertyName == SC_UNO_APPLYFMDES )
2850  {
2851  // default for no model is TRUE
2852  ScDrawLayer* pModel = rDoc.GetDrawLayer();
2853  bool bOpenInDesign = pModel == nullptr || pModel->GetOpenInDesignMode();
2854  aRet <<= bOpenInDesign;
2855  }
2856  else if ( aPropertyName == SC_UNO_AUTOCONTFOC )
2857  {
2858  // default for no model is FALSE
2859  ScDrawLayer* pModel = rDoc.GetDrawLayer();
2860  bool bAutoControlFocus = pModel && pModel->GetAutoControlFocus();
2861  aRet <<= bAutoControlFocus;
2862  }
2863  else if ( aPropertyName == SC_UNO_FORBIDDEN )
2864  {
2865  aRet <<= uno::Reference<i18n::XForbiddenCharacters>(new ScForbiddenCharsObj( pDocShell ));
2866  }
2867  else if ( aPropertyName == SC_UNO_HASDRAWPAGES )
2868  {
2869  aRet <<= (pDocShell->GetDocument().GetDrawLayer() != nullptr);
2870  }
2871  else if ( aPropertyName == SC_UNO_BASICLIBRARIES )
2872  {
2873  aRet <<= pDocShell->GetBasicContainer();
2874  }
2875  else if ( aPropertyName == SC_UNO_DIALOGLIBRARIES )
2876  {
2877  aRet <<= pDocShell->GetDialogContainer();
2878  }
2879  else if ( aPropertyName == SC_UNO_VBAGLOBNAME )
2880  {
2881  /* #i111553# This property provides the name of the constant that
2882  will be used to store this model in the global Basic manager.
2883  That constant will be equivalent to 'ThisComponent' but for
2884  each application, so e.g. a 'ThisExcelDoc' and a 'ThisWordDoc'
2885  constant can co-exist, as required by VBA. */
2886  aRet <<= OUString( "ThisExcelDoc" );
2887  }
2888  else if ( aPropertyName == SC_UNO_RUNTIMEUID )
2889  {
2890  aRet <<= getRuntimeUID();
2891  }
2892  else if ( aPropertyName == SC_UNO_HASVALIDSIGNATURES )
2893  {
2894  aRet <<= hasValidSignatures();
2895  }
2896  else if ( aPropertyName == SC_UNO_ISLOADED )
2897  {
2898  aRet <<= !pDocShell->IsEmpty();
2899  }
2900  else if ( aPropertyName == SC_UNO_ISUNDOENABLED )
2901  {
2902  aRet <<= rDoc.IsUndoEnabled();
2903  }
2904  else if ( aPropertyName == SC_UNO_RECORDCHANGES )
2905  {
2906  aRet <<= pDocShell->IsChangeRecording();
2907  }
2908  else if ( aPropertyName == SC_UNO_ISRECORDCHANGESPROTECTED )
2909  {
2911  }
2912  else if ( aPropertyName == SC_UNO_ISADJUSTHEIGHTENABLED )
2913  {
2914  aRet <<= !( rDoc.IsAdjustHeightLocked() );
2915  }
2916  else if ( aPropertyName == SC_UNO_ISEXECUTELINKENABLED )
2917  {
2918  aRet <<= rDoc.IsExecuteLinkEnabled();
2919  }
2920  else if ( aPropertyName == SC_UNO_ISCHANGEREADONLYENABLED )
2921  {
2922  aRet <<= rDoc.IsChangeReadOnlyEnabled();
2923  }
2924  else if ( aPropertyName == SC_UNO_REFERENCEDEVICE )
2925  {
2926  rtl::Reference<VCLXDevice> pXDev = new VCLXDevice();
2927  pXDev->SetOutputDevice( rDoc.GetRefDevice() );
2928  aRet <<= uno::Reference< awt::XDevice >( pXDev );
2929  }
2930  else if ( aPropertyName == "BuildId" )
2931  {
2932  aRet <<= maBuildId;
2933  }
2934  else if ( aPropertyName == "InternalDocument" )
2935  {
2936  aRet <<= (pDocShell->GetCreateMode() == SfxObjectCreateMode::INTERNAL);
2937  }
2938  else if ( aPropertyName == SC_UNO_INTEROPGRABBAG )
2939  {
2940  getGrabBagItem(aRet);
2941  }
2942  }
2943 
2944  return aRet;
2945 }
2946 
2948 
2949 // XMultiServiceFactory
2950 
2951 css::uno::Reference<css::uno::XInterface> ScModelObj::create(
2952  OUString const & aServiceSpecifier,
2953  css::uno::Sequence<css::uno::Any> const * arguments)
2954 {
2956 
2957  uno::Reference<uno::XInterface> xRet;
2959  if ( nType != ServiceType::INVALID )
2960  {
2961  // drawing layer tables must be kept as long as the model is alive
2962  // return stored instance if already set
2963  switch ( nType )
2964  {
2965  case ServiceType::GRADTAB: xRet.set(xDrawGradTab); break;
2966  case ServiceType::HATCHTAB: xRet.set(xDrawHatchTab); break;
2967  case ServiceType::BITMAPTAB: xRet.set(xDrawBitmapTab); break;
2968  case ServiceType::TRGRADTAB: xRet.set(xDrawTrGradTab); break;
2969  case ServiceType::MARKERTAB: xRet.set(xDrawMarkerTab); break;
2970  case ServiceType::DASHTAB: xRet.set(xDrawDashTab); break;
2971  case ServiceType::CHDATAPROV: xRet.set(xChartDataProv); break;
2972  case ServiceType::VBAOBJECTPROVIDER: xRet.set(xObjProvider); break;
2973  default: break;
2974  }
2975 
2976  // #i64497# If a chart is in a temporary document during clipboard paste,
2977  // there should be no data provider, so that own data is used
2978  bool bCreate =
2979  ( nType != ServiceType::CHDATAPROV ||
2980  ( pDocShell->GetCreateMode() != SfxObjectCreateMode::INTERNAL ));
2981  // this should never happen, i.e. the temporary document should never be
2982  // loaded, because this unlinks the data
2983  assert(bCreate);
2984 
2985  if ( !xRet.is() && bCreate )
2986  {
2987  xRet.set(ScServiceProvider::MakeInstance( nType, pDocShell ));
2988 
2989  // store created instance
2990  switch ( nType )
2991  {
2992  case ServiceType::GRADTAB: xDrawGradTab.set(xRet); break;
2993  case ServiceType::HATCHTAB: xDrawHatchTab.set(xRet); break;
2994  case ServiceType::BITMAPTAB: xDrawBitmapTab.set(xRet); break;
2995  case ServiceType::TRGRADTAB: xDrawTrGradTab.set(xRet); break;
2996  case ServiceType::MARKERTAB: xDrawMarkerTab.set(xRet); break;
2997  case ServiceType::DASHTAB: xDrawDashTab.set(xRet); break;
2998  case ServiceType::CHDATAPROV: xChartDataProv.set(xRet); break;
2999  case ServiceType::VBAOBJECTPROVIDER: xObjProvider.set(xRet); break;
3000  default: break;
3001  }
3002  }
3003  }
3004  else
3005  {
3006  // we offload everything we don't know to SvxFmMSFactory,
3007  // it'll throw exception if this isn't okay ...
3008 
3009  try
3010  {
3011  xRet = arguments == nullptr
3012  ? SvxFmMSFactory::createInstance(aServiceSpecifier)
3014  aServiceSpecifier, *arguments);
3015  // extra block to force deletion of the temporary before ScShapeObj ctor (setDelegator)
3016  }
3017  catch ( lang::ServiceNotRegisteredException & )
3018  {
3019  }
3020 
3021  // if the drawing factory created a shape, a ScShapeObj has to be used
3022  // to support own properties like ImageMap:
3023 
3024  uno::Reference<drawing::XShape> xShape( xRet, uno::UNO_QUERY );
3025  if ( xShape.is() )
3026  {
3027  xRet.clear(); // for aggregation, xShape must be the object's only ref
3028  new ScShapeObj( xShape ); // aggregates object and modifies xShape
3029  xRet.set(xShape);
3030  }
3031  }
3032  return xRet;
3033 }
3034 
3035 uno::Reference<uno::XInterface> SAL_CALL ScModelObj::createInstance(
3036  const OUString& aServiceSpecifier )
3037 {
3038  SolarMutexGuard aGuard;
3039  return create(aServiceSpecifier, nullptr);
3040 }
3041 
3042 uno::Reference<uno::XInterface> SAL_CALL ScModelObj::createInstanceWithArguments(
3043  const OUString& ServiceSpecifier,
3044  const uno::Sequence<uno::Any>& aArgs )
3045 {
3047 
3048  SolarMutexGuard aGuard;
3049  uno::Reference<uno::XInterface> xInt(create(ServiceSpecifier, &aArgs));
3050 
3051  if ( aArgs.hasElements() )
3052  {
3053  // used only for cell value binding so far - it can be initialized after creating
3054 
3055  uno::Reference<lang::XInitialization> xInit( xInt, uno::UNO_QUERY );
3056  if ( xInit.is() )
3057  xInit->initialize( aArgs );
3058  }
3059 
3060  return xInt;
3061 }
3062 
3063 uno::Sequence<OUString> SAL_CALL ScModelObj::getAvailableServiceNames()
3064 {
3065  SolarMutexGuard aGuard;
3066 
3069 }
3070 
3071 // XServiceInfo
3073 {
3074  return "ScModelObj";
3075  /* // Matching the .component information:
3076  return OUString( "com.sun.star.comp.Calc.SpreadsheetDocument" );
3077  */
3078 }
3079 
3080 sal_Bool SAL_CALL ScModelObj::supportsService( const OUString& rServiceName )
3081 {
3082  return cppu::supportsService(this, rServiceName);
3083 }
3084 
3085 uno::Sequence<OUString> SAL_CALL ScModelObj::getSupportedServiceNames()
3086 {
3088 }
3089 
3090 // XUnoTunnel
3091 
3092 sal_Int64 SAL_CALL ScModelObj::getSomething(
3093  const uno::Sequence<sal_Int8 >& rId )
3094 {
3095  if ( comphelper::isUnoTunnelId<ScModelObj>(rId) )
3096  {
3097  return comphelper::getSomething_cast(this);
3098  }
3099 
3100  if ( comphelper::isUnoTunnelId<SfxObjectShell>(rId) )
3101  {
3103  }
3104 
3105  // aggregated number formats supplier has XUnoTunnel, too
3106  // interface from aggregated object must be obtained via queryAggregation
3107 
3108  sal_Int64 nRet = SfxBaseModel::getSomething( rId );
3109  if ( nRet )
3110  return nRet;
3111 
3112  if ( GetFormatter().is() )
3113  {
3114  const uno::Type& rTunnelType = cppu::UnoType<lang::XUnoTunnel>::get();
3115  uno::Any aNumTunnel(xNumberAgg->queryAggregation(rTunnelType));
3116  if(auto xTunnelAgg = o3tl::tryAccess<uno::Reference<lang::XUnoTunnel>>(
3117  aNumTunnel))
3118  {
3119  return (*xTunnelAgg)->getSomething( rId );
3120  }
3121  }
3122 
3123  return 0;
3124 }
3125 
3126 const uno::Sequence<sal_Int8>& ScModelObj::getUnoTunnelId()
3127 {
3128  static const comphelper::UnoIdInit theScModelObjUnoTunnelId;
3129  return theScModelObjUnoTunnelId.getSeq();
3130 }
3131 
3132 // XChangesNotifier
3133 
3134 void ScModelObj::addChangesListener( const uno::Reference< util::XChangesListener >& aListener )
3135 {
3136  SolarMutexGuard aGuard;
3137  maChangesListeners.addInterface( aListener );
3138 }
3139 
3140 void ScModelObj::removeChangesListener( const uno::Reference< util::XChangesListener >& aListener )
3141 {
3142  SolarMutexGuard aGuard;
3143  maChangesListeners.removeInterface( aListener );
3144 }
3145 
3147 {
3148  if ( maChangesListeners.getLength() > 0 )
3149  return true;
3150 
3151  // "change" event set in any sheet?
3153 }
3154 
3155 void ScModelObj::NotifyChanges( const OUString& rOperation, const ScRangeList& rRanges,
3156  const uno::Sequence< beans::PropertyValue >& rProperties )
3157 {
3158  if ( pDocShell && HasChangesListeners() )
3159  {
3160  util::ChangesEvent aEvent;
3161  aEvent.Source.set( static_cast< cppu::OWeakObject* >( this ) );
3162  aEvent.Base <<= aEvent.Source;
3163 
3164  size_t nRangeCount = rRanges.size();
3165  aEvent.Changes.realloc( static_cast< sal_Int32 >( nRangeCount ) );
3166  for ( size_t nIndex = 0; nIndex < nRangeCount; ++nIndex )
3167  {
3168  uno::Reference< table::XCellRange > xRangeObj;
3169 
3170  ScRange const & rRange = rRanges[ nIndex ];
3171  if ( rRange.aStart == rRange.aEnd )
3172  {
3173  xRangeObj.set( new ScCellObj( pDocShell, rRange.aStart ) );
3174  }
3175  else
3176  {
3177  xRangeObj.set( new ScCellRangeObj( pDocShell, rRange ) );
3178  }
3179 
3180  util::ElementChange& rChange = aEvent.Changes[ static_cast< sal_Int32 >( nIndex ) ];
3181  rChange.Accessor <<= rOperation;
3182  rChange.Element <<= rProperties;
3183  rChange.ReplacedElement <<= xRangeObj;
3184  }
3185 
3187  while ( aIter.hasMoreElements() )
3188  {
3189  try
3190  {
3191  static_cast< util::XChangesListener* >( aIter.next() )->changesOccurred( aEvent );
3192  }
3193  catch( uno::Exception& )
3194  {
3195  }
3196  }
3197  }
3198 
3199  // handle sheet events
3201  if ( !(rOperation == "cell-change" && pDocShell) )
3202  return;
3203 
3205  aMarkData.MarkFromRangeList( rRanges, false );
3206  ScDocument& rDoc = pDocShell->GetDocument();
3207  SCTAB nTabCount = rDoc.GetTableCount();
3208  for (const SCTAB& nTab : aMarkData)
3209  {
3210  if (nTab >= nTabCount)
3211  break;
3212  const ScSheetEvents* pEvents = rDoc.GetSheetEvents(nTab);
3213  if (pEvents)
3214  {
3215  const OUString* pScript = pEvents->GetScript(ScSheetEventId::CHANGE);
3216  if (pScript)
3217  {
3218  ScRangeList aTabRanges; // collect ranges on this sheet
3219  size_t nRangeCount = rRanges.size();
3220  for ( size_t nIndex = 0; nIndex < nRangeCount; ++nIndex )
3221  {
3222  ScRange const & rRange = rRanges[ nIndex ];
3223  if ( rRange.aStart.Tab() == nTab )
3224  aTabRanges.push_back( rRange );
3225  }
3226  size_t nTabRangeCount = aTabRanges.size();
3227  if ( nTabRangeCount > 0 )
3228  {
3229  uno::Reference<uno::XInterface> xTarget;
3230  if ( nTabRangeCount == 1 )
3231  {
3232  ScRange const & rRange = aTabRanges[ 0 ];
3233  if ( rRange.aStart == rRange.aEnd )
3234  xTarget.set( static_cast<cppu::OWeakObject*>( new ScCellObj( pDocShell, rRange.aStart ) ) );
3235  else
3236  xTarget.set( static_cast<cppu::OWeakObject*>( new ScCellRangeObj( pDocShell, rRange ) ) );
3237  }
3238  else
3239  xTarget.set( static_cast<cppu::OWeakObject*>( new ScCellRangesObj( pDocShell, aTabRanges ) ) );
3240 
3241  uno::Sequence<uno::Any> aParams(1);
3242  aParams[0] <<= xTarget;
3243 
3244  uno::Any aRet;
3245  uno::Sequence<sal_Int16> aOutArgsIndex;
3246  uno::Sequence<uno::Any> aOutArgs;
3247 
3248  /*ErrCode eRet =*/ pDocShell->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs );
3249  }
3250  }
3251  }
3252  }
3253 }
3254 
3256 {
3257  if (!pDocShell)
3258  return;
3259 
3260  ScDocument& rDoc = pDocShell->GetDocument();
3261  // don't call events before the document is visible
3262  // (might also set a flag on SfxEventHintId::LoadFinished and only disable while loading)
3263  if ( rDoc.IsDocVisible() )
3264  {
3265  SCTAB nTabCount = rDoc.GetTableCount();
3266  for (SCTAB nTab = 0; nTab < nTabCount; nTab++)
3267  {
3268  if (rDoc.HasCalcNotification(nTab))
3269  {
3270  if (const ScSheetEvents* pEvents = rDoc.GetSheetEvents( nTab ))
3271  {
3272  if (const OUString* pScript = pEvents->GetScript(ScSheetEventId::CALCULATE))
3273  {
3274  uno::Any aRet;
3275  uno::Sequence<uno::Any> aParams;
3276  uno::Sequence<sal_Int16> aOutArgsIndex;
3277  uno::Sequence<uno::Any> aOutArgs;
3278  pDocShell->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs );
3279  }
3280  }
3281 
3282  try
3283  {
3284  uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( rDoc.GetVbaEventProcessor(), uno::UNO_SET_THROW );
3285  uno::Sequence< uno::Any > aArgs( 1 );
3286  aArgs[ 0 ] <<= nTab;
3287  xVbaEvents->processVbaEvent( ScSheetEvents::GetVbaSheetEventId( ScSheetEventId::CALCULATE ), aArgs );
3288  }
3289  catch( uno::Exception& )
3290  {
3291  }
3292  }
3293  }
3294  }
3295  rDoc.ResetCalcNotifications();
3296 }
3297 
3298 // XOpenCLSelection
3299 
3301 {
3303 }
3304 
3306 {
3307  if (ScCalcConfig::isOpenCLEnabled() == static_cast<bool>(bEnable))
3308  return;
3310  return;
3311 
3312  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
3313  officecfg::Office::Common::Misc::UseOpenCL::set(bEnable, batch);
3314  batch->commit();
3315 
3317  if (bEnable)
3318  aConfig.setOpenCLConfigToDefault();
3320 
3321 #if HAVE_FEATURE_OPENCL
3322  sc::FormulaGroupInterpreter::switchOpenCLDevice(OUString(), true);
3323 #endif
3324 
3325  ScDocument* pDoc = GetDocument();
3326  pDoc->CheckVectorizationState();
3327 
3328 }
3329 
3331 {
3333  aConfig.mbOpenCLAutoSelect = true;
3335  ScFormulaOptions aOptions = SC_MOD()->GetFormulaOptions();
3336  aOptions.SetCalcConfig(aConfig);
3337  SC_MOD()->SetFormulaOptions(aOptions);
3338 #if !HAVE_FEATURE_OPENCL
3339  (void) bForce;
3340 #else
3341  sc::FormulaGroupInterpreter::switchOpenCLDevice(OUString(), true, bForce);
3342 #endif
3343 }
3344 
3346 {
3348  aConfig.mbOpenCLAutoSelect = false;
3350  ScFormulaOptions aOptions = SC_MOD()->GetFormulaOptions();
3351  aOptions.SetCalcConfig(aConfig);
3352  SC_MOD()->SetFormulaOptions(aOptions);
3353 }
3354 
3355 void ScModelObj::selectOpenCLDevice( sal_Int32 nPlatform, sal_Int32 nDevice )
3356 {
3357  if(nPlatform < 0 || nDevice < 0)
3358  throw uno::RuntimeException();
3359 
3360 #if !HAVE_FEATURE_OPENCL
3361  throw uno::RuntimeException();
3362 #else
3363  std::vector<OpenCLPlatformInfo> aPlatformInfo;
3364  sc::FormulaGroupInterpreter::fillOpenCLInfo(aPlatformInfo);
3365  if(o3tl::make_unsigned(nPlatform) >= aPlatformInfo.size())
3366  throw uno::RuntimeException();
3367 
3368  if(o3tl::make_unsigned(nDevice) >= aPlatformInfo[nPlatform].maDevices.size())
3369  throw uno::RuntimeException();
3370 
3371  OUString aDeviceString = aPlatformInfo[nPlatform].maVendor + " " + aPlatformInfo[nPlatform].maDevices[nDevice].maName;
3372  sc::FormulaGroupInterpreter::switchOpenCLDevice(aDeviceString, false);
3373 #endif
3374 }
3375 
3377 {
3378 #if !HAVE_FEATURE_OPENCL
3379  return -1;
3380 #else
3381  sal_Int32 nPlatformId;
3382  sal_Int32 nDeviceId;
3383  sc::FormulaGroupInterpreter::getOpenCLDeviceInfo(nDeviceId, nPlatformId);
3384  return nPlatformId;
3385 #endif
3386 }
3387 
3389 {
3390 #if !HAVE_FEATURE_OPENCL
3391  return -1;
3392 #else
3393  sal_Int32 nPlatformId;
3394  sal_Int32 nDeviceId;
3395  sc::FormulaGroupInterpreter::getOpenCLDeviceInfo(nDeviceId, nPlatformId);
3396  return nDeviceId;
3397 #endif
3398 }
3399 
3400 uno::Sequence< sheet::opencl::OpenCLPlatform > ScModelObj::getOpenCLPlatforms()
3401 {
3402 #if !HAVE_FEATURE_OPENCL
3403  return uno::Sequence<sheet::opencl::OpenCLPlatform>();
3404 #else
3405  std::vector<OpenCLPlatformInfo> aPlatformInfo;
3406  sc::FormulaGroupInterpreter::fillOpenCLInfo(aPlatformInfo);
3407 
3408  uno::Sequence<sheet::opencl::OpenCLPlatform> aRet(aPlatformInfo.size());
3409  for(size_t i = 0; i < aPlatformInfo.size(); ++i)
3410  {
3411  aRet[i].Name = aPlatformInfo[i].maName;
3412  aRet[i].Vendor = aPlatformInfo[i].maVendor;
3413 
3414  aRet[i].Devices.realloc(aPlatformInfo[i].maDevices.size());
3415  for(size_t j = 0; j < aPlatformInfo[i].maDevices.size(); ++j)
3416  {
3417  const OpenCLDeviceInfo& rDevice = aPlatformInfo[i].maDevices[j];
3418  aRet[i].Devices[j].Name = rDevice.maName;
3419  aRet[i].Devices[j].Vendor = rDevice.maVendor;
3420  aRet[i].Devices[j].Driver = rDevice.maDriver;
3421  }
3422  }
3423 
3424  return aRet;
3425 #endif
3426 }
3427 
3428 namespace {
3429 
3431 void setOpcodeSubsetTest(bool bFlag)
3432 {
3433  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
3434  officecfg::Office::Calc::Formula::Calculation::OpenCLSubsetOnly::set(bFlag, batch);
3435  batch->commit();
3436 }
3437 
3438 }
3439 
3441 {
3442  setOpcodeSubsetTest(true);
3443 }
3444 
3446 {
3447  setOpcodeSubsetTest(false);
3448 }
3449 
3451 {
3452  return officecfg::Office::Calc::Formula::Calculation::OpenCLSubsetOnly::get();
3453 }
3454 
3456 {
3457  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
3458  officecfg::Office::Calc::Formula::Calculation::OpenCLMinimumDataSize::set(number, batch);
3459  batch->commit();
3460 }
3461 
3463 {
3464  return officecfg::Office::Calc::Formula::Calculation::OpenCLMinimumDataSize::get();
3465 }
3466 
3468  pDocShell( pDocSh )
3469 {
3471 }
3472 
3474 {
3475  SolarMutexGuard g;
3476 
3477  if (pDocShell)
3479 }
3480 
3482 {
3483  // we don't care about update of references here
3484 
3485  if ( rHint.GetId() == SfxHintId::Dying )
3486  {
3487  pDocShell = nullptr; // became invalid
3488  }
3489 }
3490 
3491 uno::Reference<drawing::XDrawPage> ScDrawPagesObj::GetObjectByIndex_Impl(sal_Int32 nIndex) const
3492 {
3493  if (pDocShell)
3494  {
3495  ScDrawLayer* pDrawLayer = pDocShell->MakeDrawLayer();
3496  OSL_ENSURE(pDrawLayer,"Cannot create Draw-Layer");
3497  if ( pDrawLayer && nIndex >= 0 && nIndex < pDocShell->GetDocument().GetTableCount() )
3498  {
3499  SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nIndex));
3500  OSL_ENSURE(pPage,"Draw-Page not found");
3501  if (pPage)
3502  {
3503  return uno::Reference<drawing::XDrawPage> (pPage->getUnoPage(), uno::UNO_QUERY);
3504  }
3505  }
3506  }
3507  return nullptr;
3508 }
3509 
3510 // XDrawPages
3511 
3512 uno::Reference<drawing::XDrawPage> SAL_CALL ScDrawPagesObj::insertNewByIndex( sal_Int32 nPos )
3513 {
3514  SolarMutexGuard aGuard;
3515  uno::Reference<drawing::XDrawPage> xRet;
3516  if (pDocShell)
3517  {
3518  OUString aNewName;
3520  if ( pDocShell->GetDocFunc().InsertTable( static_cast<SCTAB>(nPos),
3521  aNewName, true, true ) )
3522  xRet.set(GetObjectByIndex_Impl( nPos ));
3523  }
3524  return xRet;
3525 }
3526 
3527 void SAL_CALL ScDrawPagesObj::remove( const uno::Reference<drawing::XDrawPage>& xPage )
3528 {
3529  SolarMutexGuard aGuard;
3530  SvxDrawPage* pImp = comphelper::getFromUnoTunnel<SvxDrawPage>( xPage );
3531  if ( pDocShell && pImp )
3532  {
3533  SdrPage* pPage = pImp->GetSdrPage();
3534  if (pPage)
3535  {
3536  SCTAB nPageNum = static_cast<SCTAB>(pPage->GetPageNum());
3537  pDocShell->GetDocFunc().DeleteTable( nPageNum, true );
3538  }
3539  }
3540 }
3541 
3542 // XIndexAccess
3543 
3544 sal_Int32 SAL_CALL ScDrawPagesObj::getCount()
3545 {
3546  SolarMutexGuard aGuard;
3547  if (pDocShell)
3548  return pDocShell->GetDocument().GetTableCount();
3549  return 0;
3550 }
3551 
3552 uno::Any SAL_CALL ScDrawPagesObj::getByIndex( sal_Int32 nIndex )
3553 {
3554  SolarMutexGuard aGuard;
3555  uno::Reference<drawing::XDrawPage> xPage(GetObjectByIndex_Impl(nIndex));
3556  if (!xPage.is())
3557  throw lang::IndexOutOfBoundsException();
3558 
3559  return uno::makeAny(xPage);
3560 }
3561 
3563 {
3564  SolarMutexGuard aGuard;
3566 }
3567 
3569 {
3570  SolarMutexGuard aGuard;
3571  return ( getCount() != 0 );
3572 }
3573 
3575  pDocShell( pDocSh )
3576 {
3578 }
3579 
3581 {
3582  SolarMutexGuard g;
3583 
3584  if (pDocShell)
3586 }
3587 
3589 {
3590  // we don't care about update of references here
3591 
3592  if ( rHint.GetId() == SfxHintId::Dying )
3593  {
3594  pDocShell = nullptr; // became invalid
3595  }
3596 }
3597 
3598 // XSpreadsheets
3599 
3601 {
3602  if ( pDocShell && nIndex >= 0 && nIndex < pDocShell->GetDocument().GetTableCount() )
3603  return new ScTableSheetObj( pDocShell, static_cast<SCTAB>(nIndex) );
3604 
3605  return nullptr;
3606 }
3607 
3609 {
3610  if (pDocShell)
3611  {
3612  SCTAB nIndex;
3613  if ( pDocShell->GetDocument().GetTable( aName, nIndex ) )
3614  return new ScTableSheetObj( pDocShell, nIndex );
3615  }
3616  return nullptr;
3617 }
3618 
3619 void SAL_CALL ScTableSheetsObj::insertNewByName( const OUString& aName, sal_Int16 nPosition )
3620 {
3621  SolarMutexGuard aGuard;
3622  bool bDone = false;
3623  if (pDocShell)
3624  {
3625  bDone = pDocShell->GetDocFunc().InsertTable( nPosition, aName, true, true );
3626  }
3627  if (!bDone)
3628  throw uno::RuntimeException(); // no other exceptions specified
3629 }
3630 
3631 void SAL_CALL ScTableSheetsObj::moveByName( const OUString& aName, sal_Int16 nDestination )
3632 {
3633  SolarMutexGuard aGuard;
3634  bool bDone = false;
3635  if (pDocShell)
3636  {
3637  SCTAB nSource;
3638  if ( pDocShell->GetDocument().GetTable( aName, nSource ) )
3639  bDone = pDocShell->MoveTable( nSource, nDestination, false, true );
3640  }
3641  if (!bDone)
3642  throw uno::RuntimeException(); // no other exceptions specified
3643 }
3644 
3645 void SAL_CALL ScTableSheetsObj::copyByName( const OUString& aName,
3646  const OUString& aCopy, sal_Int16 nDestination )
3647 {
3648  SolarMutexGuard aGuard;
3649  bool bDone = false;
3650  if (pDocShell)
3651  {
3652  SCTAB nSource;
3653  if ( pDocShell->GetDocument().GetTable( aName, nSource ) )
3654  {
3655  bDone = pDocShell->MoveTable( nSource, nDestination, true, true );
3656  if (bDone)
3657  {
3658  // #i92477# any index past the last sheet means "append" in MoveTable
3659  SCTAB nResultTab = static_cast<SCTAB>(nDestination);
3660  SCTAB nTabCount = pDocShell->GetDocument().GetTableCount(); // count after copying
3661  if (nResultTab >= nTabCount)
3662  nResultTab = nTabCount - 1;
3663 
3664  bDone = pDocShell->GetDocFunc().RenameTable( nResultTab, aCopy,
3665  true, true );
3666  }
3667  }
3668  }
3669  if (!bDone)
3670  throw uno::RuntimeException(); // no other exceptions specified
3671 }
3672 
3673 void SAL_CALL ScTableSheetsObj::insertByName( const OUString& aName, const uno::Any& aElement )
3674 {
3675  SolarMutexGuard aGuard;
3676  bool bDone = false;
3677  bool bIllArg = false;
3678 
3680 
3681  if ( pDocShell )
3682  {
3683  uno::Reference<uno::XInterface> xInterface(aElement, uno::UNO_QUERY);
3684  if ( xInterface.is() )
3685  {
3686  ScTableSheetObj* pSheetObj = comphelper::getFromUnoTunnel<ScTableSheetObj>( xInterface );
3687  if ( pSheetObj && !pSheetObj->GetDocShell() ) // not inserted yet?
3688  {
3689  ScDocument& rDoc = pDocShell->GetDocument();
3690  SCTAB nDummy;
3691  if ( rDoc.GetTable( aName, nDummy ) )
3692  {
3693  // name already exists
3694  throw container::ElementExistException();
3695  }
3696  SCTAB nPosition = rDoc.GetTableCount();
3697  bDone = pDocShell->GetDocFunc().InsertTable( nPosition, aName,
3698  true, true );
3699  if (bDone)
3700  pSheetObj->InitInsertSheet( pDocShell, nPosition );
3701  // set document and new range in the object
3702  }
3703  else
3704  bIllArg = true;
3705  }
3706  else
3707  bIllArg = true;
3708  }
3709 
3710  if (!bDone)
3711  {
3712  if (bIllArg)
3713  throw lang::IllegalArgumentException();
3714  else
3715  throw uno::RuntimeException(); // ElementExistException is handled above
3716  }
3717 }
3718 
3719 void SAL_CALL ScTableSheetsObj::replaceByName( const OUString& aName, const uno::Any& aElement )
3720 {
3721  SolarMutexGuard aGuard;
3722  bool bDone = false;
3723  bool bIllArg = false;
3724 
3726 
3727  if ( pDocShell )
3728  {
3729  uno::Reference<uno::XInterface> xInterface(aElement, uno::UNO_QUERY);
3730  if ( xInterface.is() )
3731  {
3732  ScTableSheetObj* pSheetObj = comphelper::getFromUnoTunnel<ScTableSheetObj>( xInterface );
3733  if ( pSheetObj && !pSheetObj->GetDocShell() ) // not inserted yet?
3734  {
3735  SCTAB nPosition;
3736  if ( !pDocShell->GetDocument().GetTable( aName, nPosition ) )
3737  {
3738  // not found
3739  throw container::NoSuchElementException();
3740  }
3741 
3742  if ( pDocShell->GetDocFunc().DeleteTable( nPosition, true ) )
3743  {
3744  // InsertTable can't really go wrong now
3745  bDone = pDocShell->GetDocFunc().InsertTable( nPosition, aName, true, true );
3746  if (bDone)
3747  pSheetObj->InitInsertSheet( pDocShell, nPosition );
3748  }
3749 
3750  }
3751  else
3752  bIllArg = true;
3753  }
3754  else
3755  bIllArg = true;
3756  }
3757 
3758  if (!bDone)
3759  {
3760  if (bIllArg)
3761  throw lang::IllegalArgumentException();
3762  else
3763  throw uno::RuntimeException(); // NoSuchElementException is handled above
3764  }
3765 }
3766 
3767 void SAL_CALL ScTableSheetsObj::removeByName( const OUString& aName )
3768 {
3769  SolarMutexGuard aGuard;
3770  bool bDone = false;
3771  if (pDocShell)
3772  {
3773  SCTAB nIndex;
3774  if ( !pDocShell->GetDocument().GetTable( aName, nIndex ) )
3775  throw container::NoSuchElementException(); // not found
3776  bDone = pDocShell->GetDocFunc().DeleteTable( nIndex, true );
3777  }
3778 
3779  if (!bDone)
3780  throw uno::RuntimeException(); // NoSuchElementException is handled above
3781 }
3782 
3784  const uno::Reference < sheet::XSpreadsheetDocument > & xDocSrc,
3785  const OUString& srcName, const sal_Int32 nDestPosition )
3786 {
3787  //pDocShell is the destination
3788  ScDocument& rDocDest = pDocShell->GetDocument();
3789 
3790  // Source document docShell
3791  if ( !xDocSrc.is() )
3792  throw uno::RuntimeException();
3793  ScModelObj* pObj = comphelper::getFromUnoTunnel<ScModelObj>(xDocSrc);
3794  ScDocShell* pDocShellSrc = static_cast<ScDocShell*>(pObj->GetEmbeddedObject());
3795 
3796  // SourceSheet Position and does srcName exists ?
3797  SCTAB nIndexSrc;
3798  if ( !pDocShellSrc->GetDocument().GetTable( srcName, nIndexSrc ) )
3799  throw lang::IllegalArgumentException();
3800 
3801  // Check the validity of destination index.
3802  SCTAB nCount = rDocDest.GetTableCount();
3803  SCTAB nIndexDest = static_cast<SCTAB>(nDestPosition);
3804  if (nIndexDest > nCount || nIndexDest < 0)
3805  throw lang::IndexOutOfBoundsException();
3806 
3807  // Transfer Tab
3809  *pDocShellSrc, nIndexSrc, nIndexDest, true/*bInsertNew*/, true/*bNotifyAndPaint*/ );
3810 
3811  return nIndexDest;
3812 }
3813 
3814 // XCellRangesAccess
3815 
3816 uno::Reference< table::XCell > SAL_CALL ScTableSheetsObj::getCellByPosition( sal_Int32 nColumn, sal_Int32 nRow, sal_Int32 nSheet )
3817 {
3818  SolarMutexGuard aGuard;
3819  rtl::Reference<ScTableSheetObj> xSheet = GetObjectByIndex_Impl(static_cast<sal_uInt16>(nSheet));
3820  if (! xSheet.is())
3821  throw lang::IndexOutOfBoundsException();
3822 
3823  return xSheet->getCellByPosition(nColumn, nRow);
3824 }
3825 
3826 uno::Reference< table::XCellRange > SAL_CALL ScTableSheetsObj::getCellRangeByPosition( sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom, sal_Int32 nSheet )
3827 {
3828  SolarMutexGuard aGuard;
3829  rtl::Reference<ScTableSheetObj> xSheet = GetObjectByIndex_Impl(static_cast<sal_uInt16>(nSheet));
3830  if (! xSheet.is())
3831  throw lang::IndexOutOfBoundsException();
3832 
3833  return xSheet->getCellRangeByPosition(nLeft, nTop, nRight, nBottom);
3834 }
3835 
3836 uno::Sequence < uno::Reference< table::XCellRange > > SAL_CALL ScTableSheetsObj::getCellRangesByName( const OUString& aRange )
3837 {
3838  SolarMutexGuard aGuard;
3839  uno::Sequence < uno::Reference < table::XCellRange > > xRet;
3840 
3841  ScRangeList aRangeList;
3842  ScDocument& rDoc = pDocShell->GetDocument();
3844  throw lang::IllegalArgumentException();
3845 
3846  size_t nCount = aRangeList.size();
3847  if (!nCount)
3848  throw lang::IllegalArgumentException();
3849 
3850  xRet.realloc(nCount);
3851  for( size_t nIndex = 0; nIndex < nCount; nIndex++ )
3852  {
3853  const ScRange & rRange = aRangeList[ nIndex ];
3854  xRet[nIndex] = new ScCellRangeObj(pDocShell, rRange);
3855  }
3856 
3857  return xRet;
3858 }
3859 
3860 // XEnumerationAccess
3861 
3862 uno::Reference<container::XEnumeration> SAL_CALL ScTableSheetsObj::createEnumeration()
3863 {
3864  SolarMutexGuard aGuard;
3865  return new ScIndexEnumeration(this, "com.sun.star.sheet.SpreadsheetsEnumeration");
3866 }
3867 
3868 // XIndexAccess
3869 
3870 sal_Int32 SAL_CALL ScTableSheetsObj::getCount()
3871 {
3872  SolarMutexGuard aGuard;
3873  if (pDocShell)
3874  return pDocShell->GetDocument().GetTableCount();
3875  return 0;
3876 }
3877 
3878 uno::Any SAL_CALL ScTableSheetsObj::getByIndex( sal_Int32 nIndex )
3879 {
3880  SolarMutexGuard aGuard;
3881  uno::Reference<sheet::XSpreadsheet> xSheet(GetObjectByIndex_Impl(nIndex));
3882  if (!xSheet.is())
3883  throw lang::IndexOutOfBoundsException();
3884 
3885  return uno::makeAny(xSheet);
3886 
3887 // return uno::Any();
3888 }
3889 
3891 {
3892  SolarMutexGuard aGuard;
3894 }
3895 
3897 {
3898  SolarMutexGuard aGuard;
3899  return ( getCount() != 0 );
3900 }
3901 
3902 // XNameAccess
3903 
3904 uno::Any SAL_CALL ScTableSheetsObj::getByName( const OUString& aName )
3905 {
3906  SolarMutexGuard aGuard;
3907  uno::Reference<sheet::XSpreadsheet> xSheet(GetObjectByName_Impl(aName));
3908  if (!xSheet.is())
3909  throw container::NoSuchElementException();
3910 
3911  return uno::makeAny(xSheet);
3912 }
3913 
3914 uno::Sequence<OUString> SAL_CALL ScTableSheetsObj::getElementNames()
3915 {
3916  SolarMutexGuard aGuard;
3917  if (pDocShell)
3918  {
3919  ScDocument& rDoc = pDocShell->GetDocument();
3920  SCTAB nCount = rDoc.GetTableCount();
3921  OUString aName;
3922  uno::Sequence<OUString> aSeq(nCount);
3923  OUString* pAry = aSeq.getArray();
3924  for (SCTAB i=0; i<nCount; i++)
3925  {
3926  rDoc.GetName( i, aName );
3927  pAry[i] = aName;
3928  }
3929  return aSeq;
3930  }
3931  return uno::Sequence<OUString>();
3932 }
3933 
3934 sal_Bool SAL_CALL ScTableSheetsObj::hasByName( const OUString& aName )
3935 {
3936  SolarMutexGuard aGuard;
3937  if (pDocShell)
3938  {
3939  SCTAB nIndex;
3940  if ( pDocShell->GetDocument().GetTable( aName, nIndex ) )
3941  return true;
3942  }
3943  return false;
3944 }
3945 
3947  pDocShell( pDocSh ),
3948  nTab ( nT ),
3949  nStartCol( nSC ),
3950  nEndCol ( nEC )
3951 {
3953 }
3954 
3956 {
3957  SolarMutexGuard g;
3958 
3959  if (pDocShell)
3961 }
3962 
3964 {
3965  if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
3966  {
3968  }
3969  else if ( rHint.GetId() == SfxHintId::Dying )
3970  {
3971  pDocShell = nullptr; // became invalid
3972  }
3973 }
3974 
3975 // XTableColumns
3976 
3978 {
3979  SCCOL nCol = static_cast<SCCOL>(nIndex) + nStartCol;
3980  if ( pDocShell && nCol <= nEndCol )
3981  return new ScTableColumnObj( pDocShell, nCol, nTab );
3982 
3983  return nullptr; // wrong index
3984 }
3985 
3987 {
3988  SCCOL nCol = 0;
3989  if ( ::AlphaToCol( pDocShell->GetDocument(), nCol, aName) )
3990  if ( pDocShell && nCol >= nStartCol && nCol <= nEndCol )
3991  return new ScTableColumnObj( pDocShell, nCol, nTab );
3992 
3993  return nullptr;
3994 }
3995 
3996 void SAL_CALL ScTableColumnsObj::insertByIndex( sal_Int32 nPosition, sal_Int32 nCount )
3997 {
3998  SolarMutexGuard aGuard;
3999  bool bDone = false;
4000  if ( pDocShell )
4001  {
4002  const ScDocument& rDoc = pDocShell->GetDocument();
4003  if ( nCount > 0 && nPosition >= 0 && nStartCol+nPosition <= nEndCol &&
4004  nStartCol+nPosition+nCount-1 <= rDoc.MaxCol() )
4005  {
4006  ScRange aRange( static_cast<SCCOL>(nStartCol+nPosition), 0, nTab,
4007  static_cast<SCCOL>(nStartCol+nPosition+nCount-1), rDoc.MaxRow(), nTab );
4008  bDone = pDocShell->GetDocFunc().InsertCells( aRange, nullptr, INS_INSCOLS_BEFORE, true, true );
4009  }
4010  }
4011  if (!bDone)
4012  throw uno::RuntimeException(); // no other exceptions specified
4013 }
4014 
4015 void SAL_CALL ScTableColumnsObj::removeByIndex( sal_Int32 nIndex, sal_Int32 nCount )
4016 {
4017  SolarMutexGuard aGuard;
4018  bool bDone = false;
4019  // the range to be deleted has to lie within the object
4020  if ( pDocShell )
4021  {
4022  const ScDocument& rDoc = pDocShell->GetDocument();
4023  if ( nCount > 0 && nIndex >= 0 && nStartCol+nIndex+nCount-1 <= nEndCol )
4024  {
4025  ScRange aRange( static_cast<SCCOL>(nStartCol+nIndex), 0, nTab,
4026  static_cast<SCCOL>(nStartCol+nIndex+nCount-1), rDoc.MaxRow(), nTab );
4027  bDone = pDocShell->GetDocFunc().DeleteCells( aRange, nullptr, DelCellCmd::Cols, true );
4028  }
4029  }
4030  if (!bDone)
4031  throw uno::RuntimeException(); // no other exceptions specified
4032 }
4033 
4034 // XEnumerationAccess
4035 
4036 uno::Reference<container::XEnumeration> SAL_CALL ScTableColumnsObj::createEnumeration()
4037 {
4038  SolarMutexGuard aGuard;
4039  return new ScIndexEnumeration(this, "com.sun.star.table.TableColumnsEnumeration");
4040 }
4041 
4042 // XIndexAccess
4043 
4044 sal_Int32 SAL_CALL ScTableColumnsObj::getCount()
4045 {
4046  SolarMutexGuard aGuard;
4047  return nEndCol - nStartCol + 1;
4048 }
4049 
4050 uno::Any SAL_CALL ScTableColumnsObj::getByIndex( sal_Int32 nIndex )
4051 {
4052  SolarMutexGuard aGuard;
4053  uno::Reference<table::XCellRange> xColumn(GetObjectByIndex_Impl(nIndex));
4054  if (!xColumn.is())
4055  throw lang::IndexOutOfBoundsException();
4056 
4057  return uno::makeAny(xColumn);
4058 
4059 }
4060 
4062 {
4063  SolarMutexGuard aGuard;
4065 }
4066 
4068 {
4069  SolarMutexGuard aGuard;
4070  return ( getCount() != 0 );
4071 }
4072 
4073 uno::Any SAL_CALL ScTableColumnsObj::getByName( const OUString& aName )
4074 {
4075  SolarMutexGuard aGuard;
4076  uno::Reference<table::XCellRange> xColumn(GetObjectByName_Impl(aName));
4077  if (!xColumn.is())
4078  throw container::NoSuchElementException();
4079 
4080  return uno::makeAny(xColumn);
4081 }
4082 
4083 uno::Sequence<OUString> SAL_CALL ScTableColumnsObj::getElementNames()
4084 {
4085  SolarMutexGuard aGuard;
4086  SCCOL nCount = nEndCol - nStartCol + 1;
4087  uno::Sequence<OUString> aSeq(nCount);
4088  OUString* pAry = aSeq.getArray();
4089  for (SCCOL i=0; i<nCount; i++)
4090  pAry[i] = ::ScColToAlpha( nStartCol + i );
4091 
4092  return aSeq;
4093 }
4094 
4095 sal_Bool SAL_CALL ScTableColumnsObj::hasByName( const OUString& aName )
4096 {
4097  SolarMutexGuard aGuard;
4098  SCCOL nCol = 0;
4099  if ( ::AlphaToCol( pDocShell->GetDocument(), nCol, aName) )
4100  if ( pDocShell && nCol >= nStartCol && nCol <= nEndCol )
4101  return true;
4102 
4103  return false; // not found
4104 }
4105 
4106 // XPropertySet
4107 
4108 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableColumnsObj::getPropertySetInfo()
4109 {
4110  SolarMutexGuard aGuard;
4111  static uno::Reference<beans::XPropertySetInfo> aRef(
4113  return aRef;
4114 }
4115 
4117  const OUString& aPropertyName, const uno::Any& aValue )
4118 {
4119  SolarMutexGuard aGuard;
4120  if (!pDocShell)
4121  throw uno::RuntimeException();
4122 
4123  std::vector<sc::ColRowSpan> aColArr(1, sc::ColRowSpan(nStartCol,nEndCol));
4124  ScDocFunc& rFunc = pDocShell->GetDocFunc();
4125 
4126  if ( aPropertyName == SC_UNONAME_CELLWID )
4127  {
4128  sal_Int32 nNewWidth = 0;
4129  if ( aValue >>= nNewWidth )
4130  rFunc.SetWidthOrHeight(
4131  true, aColArr, nTab, SC_SIZE_ORIGINAL, o3tl::toTwips(nNewWidth, o3tl::Length::mm100), true, true);
4132  }
4133  else if ( aPropertyName == SC_UNONAME_CELLVIS )
4134  {
4135  bool bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4137  rFunc.SetWidthOrHeight(true, aColArr, nTab, eMode, 0, true, true);
4138  // SC_SIZE_DIRECT with size 0: hide
4139  }
4140  else if ( aPropertyName == SC_UNONAME_OWIDTH )
4141  {
4142  bool bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4143  if (bOpt)
4144  rFunc.SetWidthOrHeight(
4145  true, aColArr, nTab, SC_SIZE_OPTIMAL, STD_EXTRA_WIDTH, true, true);
4146  // sal_False for columns currently has no effect
4147  }
4148  else if ( aPropertyName == SC_UNONAME_NEWPAGE || aPropertyName == SC_UNONAME_MANPAGE )
4149  {
4151  bool bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4152  for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
4153  if (bSet)
4154  rFunc.InsertPageBreak( true, ScAddress(nCol,0,nTab), true, true );
4155  else
4156  rFunc.RemovePageBreak( true, ScAddress(nCol,0,nTab), true, true );
4157  }
4158 }
4159 
4160 uno::Any SAL_CALL ScTableColumnsObj::getPropertyValue( const OUString& aPropertyName )
4161 {
4162  SolarMutexGuard aGuard;
4163  if (!pDocShell)
4164  throw uno::RuntimeException();
4165 
4166  ScDocument& rDoc = pDocShell->GetDocument();
4167  uno::Any aAny;
4168 
4170 
4171  if ( aPropertyName == SC_UNONAME_CELLWID )
4172  {
4173  // for hidden column, return original height
4174  sal_uInt16 nWidth = rDoc.GetOriginalWidth( nStartCol, nTab );
4175  aAny <<= static_cast<sal_Int32>(convertTwipToMm100(nWidth));
4176  }
4177  else if ( aPropertyName == SC_UNONAME_CELLVIS )
4178  {
4179  bool bVis = !rDoc.ColHidden(nStartCol, nTab);
4180  aAny <<= bVis;
4181  }
4182  else if ( aPropertyName == SC_UNONAME_OWIDTH )
4183  {
4184  bool bOpt = !(rDoc.GetColFlags( nStartCol, nTab ) & CRFlags::ManualSize);
4185  aAny <<= bOpt;
4186  }
4187  else if ( aPropertyName == SC_UNONAME_NEWPAGE )
4188  {
4189  ScBreakType nBreak = rDoc.HasColBreak(nStartCol, nTab);
4190  aAny <<= (nBreak != ScBreakType::NONE);
4191  }
4192  else if ( aPropertyName == SC_UNONAME_MANPAGE )
4193  {
4194  ScBreakType nBreak = rDoc.HasColBreak(nStartCol, nTab);
4195  aAny <<= bool(nBreak & ScBreakType::Manual);
4196  }
4197 
4198  return aAny;
4199 }
4200 
4202 
4204  pDocShell( pDocSh ),
4205  nTab ( nT ),
4206  nStartRow( nSR ),
4207  nEndRow ( nER )
4208 {
4209  pDocShell->GetDocument().AddUnoObject(*this);
4210 }
4211 
4213 {
4214  SolarMutexGuard g;
4215 
4216  if (pDocShell)
4218 }
4219 
4221 {
4222  if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
4223  {
4225  }
4226  else if ( rHint.GetId() == SfxHintId::Dying )
4227  {
4228  pDocShell = nullptr; // became invalid
4229  }
4230 }
4231 
4232 // XTableRows
4233 
4235 {
4236  SCROW nRow = static_cast<SCROW>(nIndex) + nStartRow;
4237  if ( pDocShell && nRow <= nEndRow )
4238  return new ScTableRowObj( pDocShell, nRow, nTab );
4239 
4240  return nullptr; // wrong index
4241 }
4242 
4243 void SAL_CALL ScTableRowsObj::insertByIndex( sal_Int32 nPosition, sal_Int32 nCount )
4244 {
4245  SolarMutexGuard aGuard;
4246  bool bDone = false;
4247  if ( pDocShell )
4248  {
4249  const ScDocument& rDoc = pDocShell->GetDocument();
4250  if ( nCount > 0 && nPosition >= 0 && nStartRow+nPosition <= nEndRow &&
4251  nStartRow+nPosition+nCount-1 <= rDoc.MaxRow() )
4252  {
4253  ScRange aRange( 0, static_cast<SCROW>(nStartRow+nPosition), nTab,
4254  rDoc.MaxCol(), static_cast<SCROW>(nStartRow+nPosition+nCount-1), nTab );
4255  bDone = pDocShell->GetDocFunc().InsertCells( aRange, nullptr, INS_INSROWS_BEFORE, true, true );
4256  }
4257  }
4258  if (!bDone)
4259  throw uno::RuntimeException(); // no other exceptions specified
4260 }
4261 
4262 void SAL_CALL ScTableRowsObj::removeByIndex( sal_Int32 nIndex, sal_Int32 nCount )
4263 {
4264  SolarMutexGuard aGuard;
4265  bool bDone = false;
4266  // the range to be deleted has to lie within the object
4267  if ( pDocShell && nCount > 0 && nIndex >= 0 && nStartRow+nIndex+nCount-1 <= nEndRow )
4268  {
4269  const ScDocument& rDoc = pDocShell->GetDocument();
4270  ScRange aRange( 0, static_cast<SCROW>(nStartRow+nIndex), nTab,
4271  rDoc.MaxCol(), static_cast<SCROW>(nStartRow+nIndex+nCount-1), nTab );
4272  bDone = pDocShell->GetDocFunc().DeleteCells( aRange, nullptr, DelCellCmd::Rows, true );
4273  }
4274  if (!bDone)
4275  throw uno::RuntimeException(); // no other exceptions specified
4276 }
4277 
4278 // XEnumerationAccess
4279 
4280 uno::Reference<container::XEnumeration> SAL_CALL ScTableRowsObj::createEnumeration()
4281 {
4282  SolarMutexGuard aGuard;
4283  return new ScIndexEnumeration(this, "com.sun.star.table.TableRowsEnumeration");
4284 }
4285 
4286 // XIndexAccess
4287 
4288 sal_Int32 SAL_CALL ScTableRowsObj::getCount()
4289 {
4290  SolarMutexGuard aGuard;
4291  return nEndRow - nStartRow + 1;
4292 }
4293 
4294 uno::Any SAL_CALL ScTableRowsObj::getByIndex( sal_Int32 nIndex )
4295 {
4296  SolarMutexGuard aGuard;
4297  uno::Reference<table::XCellRange> xRow(GetObjectByIndex_Impl(nIndex));
4298  if (!xRow.is())
4299  throw lang::IndexOutOfBoundsException();
4300 
4301  return uno::makeAny(xRow);
4302 }
4303 
4305 {
4306  SolarMutexGuard aGuard;
4308 }
4309 
4311 {
4312  SolarMutexGuard aGuard;
4313  return ( getCount() != 0 );
4314 }
4315 
4316 // XPropertySet
4317 
4318 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableRowsObj::getPropertySetInfo()
4319 {
4320  SolarMutexGuard aGuard;
4321  static uno::Reference<beans::XPropertySetInfo> aRef(
4323  return aRef;
4324 }
4325 
4327  const OUString& aPropertyName, const uno::Any& aValue )
4328 {
4329  SolarMutexGuard aGuard;
4330  if (!pDocShell)
4331  throw uno::RuntimeException();
4332 
4333  ScDocFunc& rFunc = pDocShell->GetDocFunc();
4334  ScDocument& rDoc = pDocShell->GetDocument();
4335  std::vector<sc::ColRowSpan> aRowArr(1, sc::ColRowSpan(nStartRow,nEndRow));
4336 
4337  if ( aPropertyName == SC_UNONAME_OHEIGHT )
4338  {
4339  sal_Int32 nNewHeight = 0;
4340  if ( rDoc.IsImportingXML() && ( aValue >>= nNewHeight ) )
4341  {
4342  // used to set the stored row height for rows with optimal height when loading.
4343 
4344  // TODO: It's probably cleaner to use a different property name
4345  // for this.
4347  }
4348  else
4349  {
4350  bool bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4351  if (bOpt)
4352  rFunc.SetWidthOrHeight(false, aRowArr, nTab, SC_SIZE_OPTIMAL, 0, true, true);
4353  else
4354  {
4356  }
4357  }
4358  }
4359  else if ( aPropertyName == SC_UNONAME_CELLHGT )
4360  {
4361  sal_Int32 nNewHeight = 0;
4362  if ( aValue >>= nNewHeight )
4363  {
4364  if (rDoc.IsImportingXML())
4365  {
4366  // TODO: This is a band-aid fix. Eventually we need to
4367  // re-work ods' style import to get it to set styles to
4368  // ScDocument directly.
4370  rDoc.SetManualHeight( nStartRow, nEndRow, nTab, true );
4371  }
4372  else
4373  rFunc.SetWidthOrHeight(
4374  false, aRowArr, nTab, SC_SIZE_ORIGINAL, o3tl::toTwips(nNewHeight, o3tl::Length::mm100), true, true);
4375  }
4376  }
4377  else if ( aPropertyName == SC_UNONAME_CELLVIS )
4378  {
4379  bool bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4381  rFunc.SetWidthOrHeight(false, aRowArr, nTab, eMode, 0, true, true);
4382  // SC_SIZE_DIRECT with size 0: hide
4383  }
4384  else if ( aPropertyName == SC_UNONAME_VISFLAG )
4385  {
4386  // #i116460# Shortcut to only set the flag, without drawing layer update etc.
4387  // Should only be used from import filters.
4389  }
4390  else if ( aPropertyName == SC_UNONAME_CELLFILT )
4391  {
4393  if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
4394  rDoc.SetRowFiltered(nStartRow, nEndRow, nTab, true);
4395  else
4396  rDoc.SetRowFiltered(nStartRow, nEndRow, nTab, false);
4397  }
4398  else if ( aPropertyName == SC_UNONAME_NEWPAGE || aPropertyName == SC_UNONAME_MANPAGE )
4399  {
4401  bool bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4402  for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++)
4403  if (bSet)
4404  rFunc.InsertPageBreak( false, ScAddress(0,nRow,nTab), true, true );
4405  else
4406  rFunc.RemovePageBreak( false, ScAddress(0,nRow,nTab), true, true );
4407  }
4408  else if ( aPropertyName == SC_UNONAME_CELLBACK || aPropertyName == SC_UNONAME_CELLTRAN )
4409  {
4410  // #i57867# Background color is specified for row styles in the file format,
4411  // so it has to be supported along with the row properties (import only).
4412 
4413  // Use ScCellRangeObj to set the property for all cells in the rows
4414  // (this means, the "row attribute" must be set before individual cell attributes).
4415 
4416  ScRange aRange( 0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab );
4417  uno::Reference<beans::XPropertySet> xRangeObj = new ScCellRangeObj( pDocShell, aRange );
4418  xRangeObj->setPropertyValue( aPropertyName, aValue );
4419  }
4420 }
4421 
4422 uno::Any SAL_CALL ScTableRowsObj::getPropertyValue( const OUString& aPropertyName )
4423 {
4424  SolarMutexGuard aGuard;
4425  if (!pDocShell)
4426  throw uno::RuntimeException();
4427 
4428  ScDocument& rDoc = pDocShell->GetDocument();
4429  uno::Any aAny;
4430 
4432 
4433  if ( aPropertyName == SC_UNONAME_CELLHGT )
4434  {
4435  // for hidden row, return original height
4436  sal_uInt16 nHeight = rDoc.GetOriginalHeight( nStartRow, nTab );
4437  aAny <<= static_cast<sal_Int32>(convertTwipToMm100(nHeight));
4438  }
4439  else if ( aPropertyName == SC_UNONAME_CELLVIS )
4440  {
4441  SCROW nLastRow;
4442  bool bVis = !rDoc.RowHidden(nStartRow, nTab, nullptr, &nLastRow);
4443  aAny <<= bVis;
4444  }
4445  else if ( aPropertyName == SC_UNONAME_CELLFILT )
4446  {
4447  bool bVis = rDoc.RowFiltered(nStartRow, nTab);
4448  aAny <<= bVis;
4449  }
4450  else if ( aPropertyName == SC_UNONAME_OHEIGHT )
4451  {
4452  bool bOpt = !(rDoc.GetRowFlags( nStartRow, nTab ) & CRFlags::ManualSize);
4453  aAny <<= bOpt;
4454  }
4455  else if ( aPropertyName == SC_UNONAME_NEWPAGE )
4456  {
4457  ScBreakType nBreak = rDoc.HasRowBreak(nStartRow, nTab);
4458  aAny <<= (nBreak != ScBreakType::NONE);
4459  }
4460  else if ( aPropertyName == SC_UNONAME_MANPAGE )
4461  {
4462  ScBreakType nBreak = rDoc.HasRowBreak(nStartRow, nTab);
4463  aAny <<= bool(nBreak & ScBreakType::Manual);
4464  }
4465  else if ( aPropertyName == SC_UNONAME_CELLBACK || aPropertyName == SC_UNONAME_CELLTRAN )
4466  {
4467  // Use ScCellRangeObj to get the property from the cell range
4468  // (for completeness only, this is not used by the XML filter).
4469 
4470  ScRange aRange( 0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab );
4471  uno::Reference<beans::XPropertySet> xRangeObj = new ScCellRangeObj( pDocShell, aRange );
4472  aAny = xRangeObj->getPropertyValue( aPropertyName );
4473  }
4474 
4475  return aAny;
4476 }
4477 
4479 
4481 {
4482 }
4483 
4484 // XPropertySet
4485 
4486 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScSpreadsheetSettingsObj::getPropertySetInfo()
4487 {
4488  return nullptr;
4489 }
4490 
4492  const OUString& /* aPropertyName */, const uno::Any& /* aValue */ )
4493 {
4494 }
4495 
4496 uno::Any SAL_CALL ScSpreadsheetSettingsObj::getPropertyValue( const OUString& /* aPropertyName */ )
4497 {
4498  return uno::Any();
4499 }
4500 
4502 
4504  pDocShell( pDocSh ),
4505  nTab( nT )
4506 {
4507  pDocShell->GetDocument().AddUnoObject(*this);
4508 }
4509 
4511 {
4512  SolarMutexGuard g;
4513 
4514  if (pDocShell)
4516 }
4517 
4519 {
4521 
4522  if ( rHint.GetId() == SfxHintId::Dying )
4523  {
4524  pDocShell = nullptr; // became invalid
4525  }
4526 }
4527 
4528 bool ScAnnotationsObj::GetAddressByIndex_Impl( sal_Int32 nIndex, ScAddress& rPos ) const
4529 {
4530  if (!pDocShell)
4531  return false;
4532 
4533  ScDocument& rDoc = pDocShell->GetDocument();
4534  rPos = rDoc.GetNotePosition(nIndex, nTab);
4535  return rPos.IsValid();
4536 }
4537 
4539 {
4540  if (pDocShell)
4541  {
4542  ScAddress aPos;
4543  if ( GetAddressByIndex_Impl( nIndex, aPos ) )
4544  return new ScAnnotationObj( pDocShell, aPos );
4545  }
4546  return nullptr;
4547 }
4548 
4549 // XSheetAnnotations
4550 
4552  const table::CellAddress& aPosition, const OUString& rText )
4553 {
4554  SolarMutexGuard aGuard;
4555  if (pDocShell)
4556  {
4557  OSL_ENSURE( aPosition.Sheet == nTab, "addAnnotation with a wrong Sheet" );
4558  ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
4559  pDocShell->GetDocFunc().ReplaceNote( aPos, rText, nullptr, nullptr, true );
4560  }
4561 }
4562 
4563 void SAL_CALL ScAnnotationsObj::removeByIndex( sal_Int32 nIndex )
4564 {
4565  SolarMutexGuard aGuard;
4566  if (pDocShell)
4567  {
4568  ScAddress aPos;
4569  if ( GetAddressByIndex_Impl( nIndex, aPos ) )
4570  {
4572  aMarkData.SelectTable( aPos.Tab(), true );
4573  aMarkData.SetMultiMarkArea( ScRange(aPos) );
4574 
4575  pDocShell->GetDocFunc().DeleteContents( aMarkData, InsertDeleteFlags::NOTE, true, true );
4576  }
4577  }
4578 }
4579 
4580 // XEnumerationAccess
4581 
4582 uno::Reference<container::XEnumeration> SAL_CALL ScAnnotationsObj::createEnumeration()
4583 {
4585 
4586  SolarMutexGuard aGuard;
4587  return new ScIndexEnumeration(this, "com.sun.star.sheet.CellAnnotationsEnumeration");
4588 }
4589 
4590 // XIndexAccess
4591 
4592 sal_Int32 SAL_CALL ScAnnotationsObj::getCount()
4593 {
4594  SolarMutexGuard aGuard;
4595  sal_Int32 nCount = 0;
4596  if (pDocShell)
4597  {
4598  const ScDocument& rDoc = pDocShell->GetDocument();
4599  for (SCCOL nCol : rDoc.GetColumnsRange(nTab, 0, rDoc.MaxCol()))
4600  nCount += rDoc.GetNoteCount(nTab, nCol);
4601  }
4602  return nCount;
4603 }
4604 
4605 uno::Any SAL_CALL ScAnnotationsObj::getByIndex( sal_Int32 nIndex )
4606 {
4607  SolarMutexGuard aGuard;
4608  uno::Reference<sheet::XSheetAnnotation> xAnnotation(GetObjectByIndex_Impl(nIndex));
4609  if (!xAnnotation.is())
4610  throw lang::IndexOutOfBoundsException();
4611 
4612  return uno::makeAny(xAnnotation);
4613 }
4614 
4616 {
4617  SolarMutexGuard aGuard;
4619 }
4620 
4622 {
4623  SolarMutexGuard aGuard;
4624  return ( getCount() != 0 );
4625 }
4626 
4628  pDocShell( pDocSh ),
4629  nTab ( nT )
4630 {
4632 }
4633 
4635 {
4636  SolarMutexGuard g;
4637 
4638  if (pDocShell)
4640 }
4641 
4643 {
4644  if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
4645  {
4647  }
4648  else if ( rHint.GetId() == SfxHintId::Dying )
4649  {
4650  pDocShell = nullptr; // became invalid
4651  }
4652 }
4653 
4654 // XScenarios
4655 
4656 bool ScScenariosObj::GetScenarioIndex_Impl( std::u16string_view rName, SCTAB& rIndex )
4657 {
4659 
4660  if ( pDocShell )
4661  {
4662  OUString aTabName;
4663  ScDocument& rDoc = pDocShell->GetDocument();
4664  SCTAB nCount = static_cast<SCTAB>(getCount());
4665  for (SCTAB i=0; i<nCount; i++)
4666  if (rDoc.GetName( nTab+i+1, aTabName ))
4667  if (aTabName == rName)
4668  {
4669  rIndex = i;
4670  return true;
4671  }
4672  }
4673 
4674  return false;
4675 }
4676 
4678 {
4679  sal_uInt16 nCount = static_cast<sal_uInt16>(getCount());
4680  if ( pDocShell && nIndex >= 0 && nIndex < nCount )
4681  return new ScTableSheetObj( pDocShell, nTab+static_cast<SCTAB>(nIndex)+1 );
4682 
4683  return nullptr; // no document or wrong index
4684 }
4685 
4687 {
4688  SCTAB nIndex;
4689  if ( pDocShell && GetScenarioIndex_Impl( aName, nIndex ) )
4690  return new ScTableSheetObj( pDocShell, nTab+nIndex+1 );
4691 
4692  return nullptr; // not found
4693 }
4694 
4695 void SAL_CALL ScScenariosObj::addNewByName( const OUString& aName,
4696  const uno::Sequence<table::CellRangeAddress>& aRanges,
4697  const OUString& aComment )
4698 {
4699  SolarMutexGuard aGuard;
4700  if ( !pDocShell )
4701  return;
4702 
4704  aMarkData.SelectTable( nTab, true );
4705 
4706  for (const table::CellRangeAddress& rRange : aRanges)
4707  {
4708  OSL_ENSURE( rRange.Sheet == nTab, "addScenario with a wrong Tab" );
4709  ScRange aRange( static_cast<SCCOL>(rRange.StartColumn), static_cast<SCROW>(rRange.StartRow), nTab,
4710  static_cast<SCCOL>(rRange.EndColumn), static_cast<SCROW>(rRange.EndRow), nTab );
4711 
4712  aMarkData.SetMultiMarkArea( aRange );
4713  }
4714 
4717 
4718  pDocShell->MakeScenario( nTab, aName, aComment, COL_LIGHTGRAY, nFlags, aMarkData );
4719 }
4720 
4721 void SAL_CALL ScScenariosObj::removeByName( const OUString& aName )
4722 {
4723  SolarMutexGuard aGuard;
4724  SCTAB nIndex;
4725  if ( pDocShell && GetScenarioIndex_Impl( aName, nIndex ) )
4726  pDocShell->GetDocFunc().DeleteTable( nTab+nIndex+1, true );
4727 }
4728 
4729 // XEnumerationAccess
4730 
4731 uno::Reference<container::XEnumeration> SAL_CALL ScScenariosObj::createEnumeration()
4732 {
4733  SolarMutexGuard aGuard;
4734  return new ScIndexEnumeration(this, "com.sun.star.sheet.ScenariosEnumeration");
4735 }
4736 
4737 // XIndexAccess
4738 
4739 sal_Int32 SAL_CALL ScScenariosObj::getCount()
4740 {
4741  SolarMutexGuard aGuard;
4742  SCTAB nCount = 0;
4743  if ( pDocShell )
4744  {
4745  ScDocument& rDoc = pDocShell->GetDocument();
4746  if (!rDoc.IsScenario(nTab))
4747  {
4748  SCTAB nTabCount = rDoc.GetTableCount();
4749  SCTAB nNext = nTab + 1;
4750  while (nNext < nTabCount && rDoc.IsScenario(nNext))
4751  {
4752  ++nCount;
4753  ++nNext;
4754  }
4755  }
4756  }
4757  return nCount;
4758 }
4759 
4760 uno::Any SAL_CALL ScScenariosObj::getByIndex( sal_Int32 nIndex )
4761 {
4762  SolarMutexGuard aGuard;
4763  uno::Reference<sheet::XScenario> xScen(GetObjectByIndex_Impl(nIndex));
4764  if (!xScen.is())
4765  throw lang::IndexOutOfBoundsException();
4766 
4767  return uno::makeAny(xScen);
4768 }
4769 
4771 {
4772  SolarMutexGuard aGuard;
4774 }
4775 
4777 {
4778  SolarMutexGuard aGuard;
4779  return ( getCount() != 0 );
4780 }
4781 
4782 uno::Any SAL_CALL ScScenariosObj::getByName( const OUString& aName )
4783 {
4784  SolarMutexGuard aGuard;
4785  uno::Reference<sheet::XScenario> xScen(GetObjectByName_Impl(aName));
4786  if (!xScen.is())
4787  throw container::NoSuchElementException();
4788 
4789  return uno::makeAny(xScen);
4790 }
4791 
4792 uno::Sequence<OUString> SAL_CALL ScScenariosObj::getElementNames()
4793 {
4794  SolarMutexGuard aGuard;
4795  SCTAB nCount = static_cast<SCTAB>(getCount());
4796  uno::Sequence<OUString> aSeq(nCount);
4797 
4798  if ( pDocShell ) // otherwise Count = 0
4799  {
4800  OUString aTabName;
4801  ScDocument& rDoc = pDocShell->GetDocument();
4802  OUString* pAry = aSeq.getArray();
4803  for (SCTAB i=0; i<nCount; i++)
4804  if (rDoc.GetName( nTab+i+1, aTabName ))
4805  pAry[i] = aTabName;
4806  }
4807 
4808  return aSeq;
4809 }
4810 
4811 sal_Bool SAL_CALL ScScenariosObj::hasByName( const OUString& aName )
4812 {
4813  SolarMutexGuard aGuard;
4814  SCTAB nIndex;
4815  return GetScenarioIndex_Impl( aName, nIndex );
4816 }
4817 
4818 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual css::sheet::GoalResult SAL_CALL seekGoal(const css::table::CellAddress &aFormulaPosition, const css::table::CellAddress &aVariablePosition, const OUString &aGoalValue) override
XGoalSeek.
Definition: docuno.cxx:2500
OUString AsRGBHexString() const
SC_DLLPUBLIC bool IsDocProtected() const
Definition: documen3.cxx:1903
Stores the selection in the ScPrintFuncCache so it is only used for the same selection again...
Definition: pfuncache.hxx:45
virtual void SAL_CALL lockControllers() override
Definition: docuno.cxx:2375
ScPrintSelectionMode GetMode() const
Definition: pfuncache.hxx:61
static Type GetProviderType(const OUString &rServiceName)
Definition: servuno.cxx:374
SC_DLLPUBLIC bool GetPrintArea(SCTAB nTab, SCCOL &rEndCol, SCROW &rEndRow, bool bNotes=true) const
Definition: documen2.cxx:576
#define SC_UNO_IGNORECASE
Definition: unonames.hxx:505
SCTAB nTab
Collection belongs to the sheet.
Definition: docuno.hxx:670
SfxViewFrame * GetViewFrame() const
virtual css::uno::Any SAL_CALL getByIndex(sal_Int32 Index) override
Definition: docuno.cxx:4050
OUString const & getRuntimeUID() const
virtual sal_Int32 SAL_CALL getFormulaCellNumberLimit() override
Definition: docuno.cxx:3462
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
XPropertySet.
Definition: docuno.cxx:4318
virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() override
XEnumerationAccess.
Definition: docuno.cxx:4280
bool GetScenarioIndex_Impl(std::u16string_view rName, SCTAB &rIndex)
Definition: docuno.cxx:4656
bool setGraphicSelection(int nType, int nX, int nY, double fScaleX=1.0, double fScaleY=1.0)
virtual void SAL_CALL disableOpcodeSubsetTest() override
Definition: docuno.cxx:3445
#define SC_POSITIONLEFT
#define SC_UNO_ISADJUSTHEIGHTENABLED
Definition: unonames.hxx:522
virtual css::uno::Type SAL_CALL getElementType() override
XElementAccess.
Definition: docuno.cxx:4304
void SetDigitLanguage(LanguageType)
void setGrabBagItem(const css::uno::Any &rVal)
static void notifyOtherViews(const SfxViewShell *pThisView, int nType, std::string_view rKey, const OString &rPayload)
#define SC_UNO_SPELLONLINE
Definition: unonames.hxx:512
css::uno::Reference< css::uno::XInterface > create(OUString const &aServiceSpecifier, css::uno::Sequence< css::uno::Any > const *arguments)
Definition: docuno.cxx:2951
void UnlockPaint()
Definition: docsh3.cxx:322
virtual void SAL_CALL enableAutomaticDeviceSelection(sal_Bool bForce) override
Definition: docuno.cxx:3330
SfxHintId
bool hasValidSignatures() const
virtual css::uno::Any SAL_CALL getByName(const OUString &aName) override
XNameAccess.
Definition: docuno.cxx:4782
void setOpenCLConfigToDefault()
Definition: calcconfig.cxx:102
void MarkToSimple()
Definition: markdata.cxx:236
virtual void SAL_CALL addChangesListener(const css::uno::Reference< css::util::XChangesListener > &aListener) override
XChangesNotifier.
Definition: docuno.cxx:3134
bool hasValue()
sal_Int32 nIndex
virtual void getCellCursor(tools::JsonWriter &rJsonWriter) override
Definition: docuno.cxx:1031
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
Definition: gridwin.cxx:1489
#define PROP_UNO_CALCASSHOWN
Definition: optuno.hxx:25
ScAddress aStart
Definition: address.hxx:499
ScDocShell * GetDocShell() const
Definition: viewdata.hxx:353
virtual void SAL_CALL lockControllers() override
SC_DLLPUBLIC bool GetDataStart(SCTAB nTab, SCCOL &rStartCol, SCROW &rStartRow) const
Definition: documen2.cxx:644
virtual void SAL_CALL unprotect(const OUString &aPassword) override
Definition: docuno.cxx:2465
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(const OUString &aServiceSpecifier) override
XMultiServiceFactory.
Definition: docuno.cxx:3035
void SetConsolidateDlgData(std::unique_ptr< ScConsolidateParam > pData)
Definition: documen2.cxx:1109
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:42
virtual css::uno::Any SAL_CALL getByIndex(sal_Int32 Index) override
Definition: docuno.cxx:3552
static bool HasValidData(const css::uno::Reference< css::datatransfer::XTransferable > &rTransferable)
SfxPrinter * GetPrinter(bool bCreateIfNotExist=true)
Definition: docsh3.cxx:451
virtual css::uno::Reference< css::sheet::XSpreadsheets > SAL_CALL getSheets() override
XSpreadsheetDocument.
Definition: docuno.cxx:1372
virtual void SAL_CALL enableOpenCL(sal_Bool bEnable) override
Definition: docuno.cxx:3305
bool Unprotect(SCTAB nTab, const OUString &rPassword, bool bApi)
Definition: docfunc.cxx:4027
#define SC_UNONAME_VISFLAG
Definition: unonames.hxx:185
Iterator begin(const o3tl::sorted_vector< sal_Int32 > *i_pPossibleValues=nullptr) const
static bool HitAny(const Point &aPos)
virtual void SAL_CALL removeByIndex(sal_Int32 nIndex, sal_Int32 nCount) override
Definition: docuno.cxx:4015
virtual void completeFunction(const OUString &rFunctionName) override
Definition: docuno.cxx:1187
SC_DLLPUBLIC CRFlags GetColFlags(SCCOL nCol, SCTAB nTab) const
Definition: document.cxx:4359
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:89
void SetAutoControlFocus(bool _bAutoControlFocus)
virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override
Definition: docuno.cxx:4083
virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getLinks() override
XLinkTargetSupplier.
Definition: docuno.cxx:2323
SC_DLLPUBLIC bool DeleteContents(const ScMarkData &rMark, InsertDeleteFlags nFlags, bool bRecord, bool bApi)
Definition: docfunc.cxx:572
rtl::Reference< ScTableColumnObj > GetObjectByIndex_Impl(sal_Int32 nIndex) const
Definition: docuno.cxx:3977
virtual sal_Int32 SAL_CALL getCount() override
XIndexAccess.
Definition: docuno.cxx:3544
virtual void SAL_CALL unlockControllers() override
Definition: docuno.cxx:2383
constexpr auto toTwips(N number, Length from)
static bool MakeRangeFromName(const OUString &rName, const ScDocument &rDoc, SCTAB nCurTab, ScRange &rRange, RutlNameScope eScope=RUTL_NAMES, ScAddress::Details const &rDetails=ScAddress::detailsOOOa1, bool bUseDetailsPos=false)
Definition: rangeutl.cxx:233
virtual sal_Bool SAL_CALL hasByName(const OUString &aName) override
Definition: docuno.cxx:3934
SCROW Row() const
Definition: address.hxx:261