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