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>
82 
83 #include <cellsuno.hxx>
84 #include <columnspanset.hxx>
85 #include <convuno.hxx>
86 #include <datauno.hxx>
87 #include <docfunc.hxx>
88 #include <docoptio.hxx>
89 #include <docsh.hxx>
90 #include <docuno.hxx>
91 #include <drwlayer.hxx>
92 #include <forbiuno.hxx>
93 #include <formulagroup.hxx>
94 #include <gridwin.hxx>
95 #include <hints.hxx>
96 #include <inputhdl.hxx>
97 #include <inputopt.hxx>
98 #include <interpre.hxx>
99 #include <linkuno.hxx>
100 #include <markdata.hxx>
101 #include <miscuno.hxx>
102 #include <nameuno.hxx>
103 #include <notesuno.hxx>
104 #include <optuno.hxx>
105 #include <pfuncache.hxx>
106 #include <postit.hxx>
107 #include <printfun.hxx>
108 #include <rangeutl.hxx>
109 #include <scmod.hxx>
110 #include <scresid.hxx>
111 #include <servuno.hxx>
112 #include <shapeuno.hxx>
113 #include <sheetevents.hxx>
114 #include <styleuno.hxx>
115 #include <tabvwsh.hxx>
116 #include <targuno.hxx>
117 #include <unonames.hxx>
119 #include <editsh.hxx>
120 #include <drawsh.hxx>
121 #include <drtxtob.hxx>
122 #include <transobj.hxx>
123 #include <chgtrack.hxx>
124 #include <table.hxx>
125 #include <appoptio.hxx>
126 #include <formulaopt.hxx>
127 
128 #include <strings.hrc>
129 
130 using namespace com::sun::star;
131 
132 // #i111553# provides the name of the VBA constant for this document type (e.g. 'ThisExcelDoc' for Calc)
133 #define SC_UNO_VBAGLOBNAME "VBAGlobalConstantName"
134 
135 // no Which-ID here, map only for PropertySetInfo
136 
139 {
140  static const SfxItemPropertyMapEntry aDocOptPropertyMap_Impl[] =
141  {
145  {u"" SC_UNO_BASICLIBRARIES, 0, cppu::UnoType<script::XLibraryContainer>::get(), beans::PropertyAttribute::READONLY, 0},
146  {u"" SC_UNO_DIALOGLIBRARIES, 0, cppu::UnoType<script::XLibraryContainer>::get(), beans::PropertyAttribute::READONLY, 0},
147  {u"" SC_UNO_VBAGLOBNAME, 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0},
156  {u"" SC_UNO_FORBIDDEN, 0, cppu::UnoType<i18n::XForbiddenCharacters>::get(), beans::PropertyAttribute::READONLY, 0},
157  {u"" SC_UNO_HASDRAWPAGES, 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::READONLY, 0},
173  {u"" SC_UNO_RUNTIMEUID, 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0},
174  {u"" SC_UNO_HASVALIDSIGNATURES, 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::READONLY, 0},
178  {u"" SC_UNO_ISRECORDCHANGESPROTECTED,0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::READONLY, 0},
182  {u"" SC_UNO_REFERENCEDEVICE, 0, cppu::UnoType<awt::XDevice>::get(), beans::PropertyAttribute::READONLY, 0},
183  {u"BuildId", 0, ::cppu::UnoType<OUString>::get(), 0, 0},
186  { u"", 0, css::uno::Type(), 0, 0 }
187  };
188  return aDocOptPropertyMap_Impl;
189 }
190 
192 
194 {
195  static const SfxItemPropertyMapEntry aColumnsPropertyMap_Impl[] =
196  {
202  { u"", 0, css::uno::Type(), 0, 0 }
203  };
204  return aColumnsPropertyMap_Impl;
205 }
206 
208 {
209  static const SfxItemPropertyMapEntry aRowsPropertyMap_Impl[] =
210  {
219  // not sorted, not used with SfxItemPropertyMapEntry::GetByName
220  { u"", 0, css::uno::Type(), 0, 0 }
221  };
222  return aRowsPropertyMap_Impl;
223 }
224 
225 using sc::HMMToTwips;
226 using sc::TwipsToHMM;
227 
228 #define SCMODELOBJ_SERVICE "com.sun.star.sheet.SpreadsheetDocument"
229 #define SCDOCSETTINGS_SERVICE "com.sun.star.sheet.SpreadsheetDocumentSettings"
230 #define SCDOC_SERVICE "com.sun.star.document.OfficeDocument"
231 
232 SC_SIMPLE_SERVICE_INFO( ScAnnotationsObj, "ScAnnotationsObj", "com.sun.star.sheet.CellAnnotations" )
233 SC_SIMPLE_SERVICE_INFO( ScDrawPagesObj, "ScDrawPagesObj", "com.sun.star.drawing.DrawPages" )
234 SC_SIMPLE_SERVICE_INFO( ScScenariosObj, "ScScenariosObj", "com.sun.star.sheet.Scenarios" )
235 SC_SIMPLE_SERVICE_INFO( ScSpreadsheetSettingsObj, "ScSpreadsheetSettingsObj", "com.sun.star.sheet.SpreadsheetDocumentSettings" )
236 SC_SIMPLE_SERVICE_INFO( ScTableColumnsObj, "ScTableColumnsObj", "com.sun.star.table.TableColumns" )
237 SC_SIMPLE_SERVICE_INFO( ScTableRowsObj, "ScTableRowsObj", "com.sun.star.table.TableRows" )
238 SC_SIMPLE_SERVICE_INFO( ScTableSheetsObj, "ScTableSheetsObj", "com.sun.star.sheet.Spreadsheets" )
239 
240 class ScPrintUIOptions : public vcl::PrinterOptionsHelper
241 {
242 public:
244  void SetDefaults();
245 };
246 
248 {
249  const ScPrintOptions& rPrintOpt = SC_MOD()->GetPrintOptions();
250  sal_Int32 nContent = rPrintOpt.GetAllSheets() ? 0 : 1;
251  bool bSuppress = rPrintOpt.GetSkipEmpty();
252 
253  sal_Int32 nNumProps= 10, nIdx = 0;
254 
255  m_aUIProperties.resize(nNumProps);
256 
257  // load the writer PrinterOptions into the custom tab
258  m_aUIProperties[nIdx].Name = "OptionsUIFile";
259  m_aUIProperties[nIdx++].Value <<= OUString("modules/scalc/ui/printeroptions.ui");
260 
261  // create Section for spreadsheet (results in an extra tab page in dialog)
262  SvtModuleOptions aOpt;
263  OUString aAppGroupname( ScResId( SCSTR_PRINTOPT_PRODNAME ) );
264  aAppGroupname = aAppGroupname.replaceFirst( "%s", aOpt.GetModuleName( SvtModuleOptions::EModule::CALC ) );
265  m_aUIProperties[nIdx++].Value = setGroupControlOpt("tabcontrol-page2", aAppGroupname, OUString());
266 
267  // show subgroup for pages
268  m_aUIProperties[nIdx++].Value = setSubgroupControlOpt("pages", ScResId( SCSTR_PRINTOPT_PAGES ), OUString());
269 
270  // create a bool option for empty pages
271  m_aUIProperties[nIdx++].Value = setBoolControlOpt("suppressemptypages", ScResId( SCSTR_PRINTOPT_SUPPRESSEMPTY ),
272  ".HelpID:vcl:PrintDialog:IsSuppressEmptyPages:CheckBox",
273  "IsSuppressEmptyPages",
274  bSuppress);
275  // show Subgroup for print content
277  aPrintRangeOpt.maGroupHint = "PrintRange";
278  m_aUIProperties[nIdx++].Value = setSubgroupControlOpt("printrange", ScResId( SCSTR_PRINTOPT_PAGES ),
279  OUString(),
280  aPrintRangeOpt);
281 
282  // create a choice for the content to create
283  uno::Sequence< OUString > aChoices{
284  ScResId( SCSTR_PRINTOPT_ALLSHEETS ),
285  ScResId( SCSTR_PRINTOPT_SELECTEDSHEETS ),
286  ScResId( SCSTR_PRINTOPT_SELECTEDCELLS )};
287  uno::Sequence< OUString > aHelpIds{
288  ".HelpID:vcl:PrintDialog:PrintContent:ListBox"};
289  m_aUIProperties[nIdx++].Value = setChoiceListControlOpt( "printextrabox", OUString(),
290  aHelpIds, "PrintContent",
291  aChoices, nContent );
292 
293  // show Subgroup for print range
294  aPrintRangeOpt.mbInternalOnly = true;
295  m_aUIProperties[nIdx++].Value = setSubgroupControlOpt("fromwhich", ScResId( SCSTR_PRINTOPT_FROMWHICH ),
296  OUString(),
297  aPrintRangeOpt);
298 
299  // create a choice for the range to print
300  OUString aPrintRangeName( "PrintRange" );
301  aChoices.realloc( 2 );
302  aHelpIds.realloc( 2 );
303  uno::Sequence< OUString > aWidgetIds( 2 );
304  aChoices[0] = ScResId( SCSTR_PRINTOPT_PRINTALLPAGES );
305  aHelpIds[0] = ".HelpID:vcl:PrintDialog:PrintRange:RadioButton:0";
306  aWidgetIds[0] = "rbAllPages";
307  aChoices[1] = ScResId( SCSTR_PRINTOPT_PRINTPAGES );
308  aHelpIds[1] = ".HelpID:vcl:PrintDialog:PrintRange:RadioButton:1";
309  aWidgetIds[1] = "rbRangePages";
310  m_aUIProperties[nIdx++].Value = setChoiceRadiosControlOpt(aWidgetIds, OUString(),
311  aHelpIds,
312  aPrintRangeName,
313  aChoices,
314  0 );
315 
316  // create an Edit dependent on "Pages" selected
317  vcl::PrinterOptionsHelper::UIControlOptions aPageRangeOpt( aPrintRangeName, 1, true );
318  m_aUIProperties[nIdx++].Value = setEditControlOpt("pagerange", OUString(),
319  ".HelpID:vcl:PrintDialog:PageRange:Edit",
320  "PageRange", OUString(), aPageRangeOpt);
321 
322  vcl::PrinterOptionsHelper::UIControlOptions aEvenOddOpt(aPrintRangeName, 0, true);
323  m_aUIProperties[ nIdx++ ].Value = setChoiceListControlOpt("evenoddbox",
324  OUString(),
325  uno::Sequence<OUString>(),
326  "EvenOdd",
327  uno::Sequence<OUString>(),
328  0,
329  uno::Sequence< sal_Bool >(),
330  aEvenOddOpt);
331 
332  assert(nIdx == nNumProps);
333 }
334 
336 {
337  // re-initialize the default values from print options
338 
339  const ScPrintOptions& rPrintOpt = SC_MOD()->GetPrintOptions();
340  sal_Int32 nContent = rPrintOpt.GetAllSheets() ? 0 : 1;
341  bool bSuppress = rPrintOpt.GetSkipEmpty();
342 
343  for (beans::PropertyValue & rPropValue : m_aUIProperties)
344  {
345  uno::Sequence<beans::PropertyValue> aUIProp;
346  if ( rPropValue.Value >>= aUIProp )
347  {
348  for (auto& rProp : aUIProp)
349  {
350  OUString aName = rProp.Name;
351  if ( aName == "Property" )
352  {
353  beans::PropertyValue aPropertyValue;
354  if ( rProp.Value >>= aPropertyValue )
355  {
356  if ( aPropertyValue.Name == "PrintContent" )
357  {
358  aPropertyValue.Value <<= nContent;
359  rProp.Value <<= aPropertyValue;
360  }
361  else if ( aPropertyValue.Name == "IsSuppressEmptyPages" )
362  {
363  aPropertyValue.Value <<= bSuppress;
364  rProp.Value <<= aPropertyValue;
365  }
366  }
367  }
368  }
369  rPropValue.Value <<= aUIProp;
370  }
371  }
372 }
373 
375 {
376  if (pDocSh)
377  pDocSh->SetBaseModel( new ScModelObj(pDocSh) );
378 }
379 
381 {
382  ScDocument& rDoc(pDocShell->GetDocument());
383 
384  if(!rDoc.GetDrawLayer())
385  {
386  rDoc.InitDrawLayer();
387  }
388 
389  return *rDoc.GetDrawLayer(); // TTTT should be reference
390 }
391 
393  SfxBaseModel( pDocSh ),
394  aPropSet( lcl_GetDocOptPropertyMap() ),
395  pDocShell( pDocSh ),
396  maChangesListeners( m_aMutex )
397 {
398  // pDocShell may be NULL if this is the base of a ScDocOptionsObj
399  if ( pDocShell )
400  {
401  pDocShell->GetDocument().AddUnoObject(*this); // SfxModel is derived from SfxListener
402  }
403 }
404 
406 {
407  SolarMutexGuard g;
408 
409  if (pDocShell)
411 
412  if (xNumberAgg.is())
413  xNumberAgg->setDelegator(uno::Reference<uno::XInterface>());
414 
415  pPrintFuncCache.reset();
416  pPrinterOptions.reset();
417 }
418 
419 uno::Reference< uno::XAggregation> const & ScModelObj::GetFormatter()
420 {
421  // pDocShell may be NULL if this is the base of a ScDocOptionsObj
422  if ( !xNumberAgg.is() && pDocShell )
423  {
424  // setDelegator changes RefCount, so we'd better hold the reference ourselves
425  // (directly in m_refCount, so we don't delete ourselves with release())
426  osl_atomic_increment( &m_refCount );
427  // we need a reference to SvNumberFormatsSupplierObj during queryInterface,
428  // otherwise it'll be deleted
429  uno::Reference<util::XNumberFormatsSupplier> xFormatter(
431  {
432  xNumberAgg.set(uno::Reference<uno::XAggregation>( xFormatter, uno::UNO_QUERY ));
433  // extra block to force deletion of the temporary before setDelegator
434  }
435 
436  // during setDelegator no additional reference should exist
437  xFormatter = nullptr;
438 
439  if (xNumberAgg.is())
440  xNumberAgg->setDelegator( static_cast<cppu::OWeakObject*>(this) );
441  osl_atomic_decrement( &m_refCount );
442  } // if ( !xNumberAgg.is() )
443  return xNumberAgg;
444 }
445 
447 {
448  if (pDocShell)
449  return &pDocShell->GetDocument();
450  return nullptr;
451 }
452 
454 {
455  return pDocShell;
456 }
457 
459 {
460  if (pDocShell)
462 }
463 
465 {
466  if (pDocShell)
468 }
469 
471 {
472  if (pDocShell)
473  pDocShell->AfterXMLLoading(true);
474 }
475 
477 {
478  if (pDocShell)
479  return pDocShell->GetSheetSaveData();
480  return nullptr;
481 }
482 
484 {
485  if (pDocShell)
486  return pDocShell->GetFormatSaveData();
487  return nullptr;
488 }
489 
490 void ScModelObj::RepaintRange( const ScRange& rRange )
491 {
492  if (pDocShell)
494 }
495 
497 {
498  if (pDocShell)
500 }
501 
503  const Fraction& rZoomY,
504  const SCTAB nTab,
505  const ViewShellDocId& rDocId)
506 {
507  constexpr size_t nMaxIter = 5;
508  size_t nIter = 0;
509  for (SfxViewShell* pViewShell = SfxViewShell::GetFirst();
510  pViewShell && nIter < nMaxIter;
511  (pViewShell = SfxViewShell::GetNext(*pViewShell)), ++nIter)
512  {
513  if (pViewShell->GetDocId() != rDocId)
514  continue;
515 
516  ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
517  if (!pTabViewShell)
518  continue;
519 
520  ScViewData& rData = pTabViewShell->GetViewData();
521  if (rData.GetTabNo() == nTab && rData.GetZoomX() == rZoomX && rData.GetZoomY() == rZoomY)
522  return &rData;
523  }
524 
525  return nullptr;
526 }
527 
529  int nOutputWidth, int nOutputHeight,
530  int nTilePosX, int nTilePosY,
531  tools::Long nTileWidth, tools::Long nTileHeight )
532 {
533  ScTabViewShell* pViewShell = pDocShell->GetBestViewShell(false);
534 
535  // FIXME: Can this happen? What should we do?
536  if (!pViewShell)
537  return;
538 
539  ScViewData* pActiveViewData = &pViewShell->GetViewData();
540  Fraction aFracX(tools::Long(nOutputWidth * TWIPS_PER_PIXEL), nTileWidth);
541  Fraction aFracY(tools::Long(nOutputHeight * TWIPS_PER_PIXEL), nTileHeight);
542 
543  // Try to find a view that matches the tile-zoom requested by iterating over
544  // first few shells. This is to avoid switching of zooms in ScGridWindow::PaintTile
545  // and hence avoid grid-offset recomputation on all shapes which is not cheap.
546  ScViewData* pViewData = lcl_getViewMatchingDocZoomTab(aFracX, aFracY,
547  pActiveViewData->GetTabNo(), pViewShell->GetDocId());
548  if (!pViewData)
549  pViewData = pActiveViewData;
550 
551  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
552 
553  // update the size of the area we are painting
554  // FIXME we want to use only the minimal necessary size, like the
555  // following; but for the moment there is too many problems with that and
556  // interaction with editeng used for the cell editing
557  //Size aTileSize(nOutputWidth, nOutputHeight);
558  //if (pGridWindow->GetOutputSizePixel() != aTileSize)
559  // pGridWindow->SetOutputSizePixel(Size(nOutputWidth, nOutputHeight));
560  // so instead for now, set the viewport size to document size
561  Size aDocSize = getDocumentSize();
562  pGridWindow->SetOutputSizePixel(Size(aDocSize.Width() * pViewData->GetPPTX(), aDocSize.Height() * pViewData->GetPPTY()));
563 
564  pGridWindow->PaintTile( rDevice, nOutputWidth, nOutputHeight,
565  nTilePosX, nTilePosY, nTileWidth, nTileHeight );
566 
567  LokChartHelper::PaintAllChartsOnTile(rDevice, nOutputWidth, nOutputHeight,
568  nTilePosX, nTilePosY, nTileWidth, nTileHeight);
569 }
570 
571 void ScModelObj::setPart( int nPart )
572 {
573  ScViewData* pViewData = ScDocShell::GetViewData();
574  ScTabView* pTabView = dynamic_cast< ScTabView* >( pViewData->GetView() );
575 
576  if (pTabView)
577  pTabView->SelectTabPage(nPart + 1);
578 }
579 
581 {
582  ScDocument& rDoc = pDocShell->GetDocument();
583  return rDoc.GetTableCount();
584 }
585 
587 {
588  ScViewData* pViewData = ScDocShell::GetViewData();
589  return pViewData ? pViewData->GetViewShell()->getPart() : 0;
590 }
591 
592 OUString ScModelObj::getPartInfo( int nPart )
593 {
594  ScViewData* pViewData = ScDocShell::GetViewData();
595  const bool bIsVisible = pViewData->GetDocument().IsVisible(nPart);
596  //FIXME: Implement IsSelected().
597  const bool bIsSelected = false; //pViewData->GetDocument()->IsSelected(nPart);
598 
599  OUString aPartInfo = "{ \"visible\": \"" +
600  OUString::number(static_cast<unsigned int>(bIsVisible)) +
601  "\", \"selected\": \"" +
602  OUString::number(static_cast<unsigned int>(bIsSelected)) +
603  "\" }";
604  return aPartInfo;
605 }
606 
607 OUString ScModelObj::getPartName( int nPart )
608 {
609  OUString sTabName;
610  ScViewData* pViewData = ScDocShell::GetViewData();
611  pViewData->GetDocument().GetName(nPart, sTabName);
612  return sTabName;
613 }
614 
615 OUString ScModelObj::getPartHash( int nPart )
616 {
617  sal_Int64 nHashCode;
618  ScViewData* pViewData = ScDocShell::GetViewData();
619  return (pViewData->GetDocument().GetHashCode(nPart, nHashCode) ? OUString::number(nHashCode) : OUString());
620 }
621 
623 {
624  SolarMutexGuard aGuard;
625 
626  ScTabViewShell* pViewShell = pDocShell->GetBestViewShell(false);
627 
628  // FIXME: Can this happen? What should we do?
629  if (!pViewShell)
630  return VclPtr<vcl::Window>();
631 
632  ScViewData* pViewData = &pViewShell->GetViewData();
633 
634  VclPtr<vcl::Window> pWindow;
635  if (pViewData)
636  {
637  pWindow = pViewData->GetActiveWin();
638 
639  LokChartHelper aChartHelper(pViewData->GetViewShell());
640  vcl::Window* pChartWindow = aChartHelper.GetWindow();
641  if (pChartWindow)
642  pWindow = pChartWindow;
643  }
644 
645  return pWindow;
646 }
647 
649 {
650  Size aSize(10, 10); // minimum size
651 
652  ScViewData* pViewData = ScDocShell::GetViewData();
653  if (!pViewData)
654  return aSize;
655 
656  SCTAB nTab = pViewData->GetTabNo();
657  SCCOL nEndCol = 0;
658  SCROW nEndRow = 0;
659  const ScDocument& rDoc = pDocShell->GetDocument();
660 
661  rDoc.GetTiledRenderingArea(nTab, nEndCol, nEndRow);
662 
663  const ScDocument* pThisDoc = &rDoc;
664  const double fPPTX = pViewData->GetPPTX();
665  const double fPPTY = pViewData->GetPPTY();
666 
667  auto GetColWidthPx = [pThisDoc, fPPTX, nTab](SCCOL nCol) {
668  const sal_uInt16 nSize = pThisDoc->GetColWidth(nCol, nTab);
669  return ScViewData::ToPixel(nSize, fPPTX);
670  };
671 
672  tools::Long nDocWidthPixel = pViewData->GetLOKWidthHelper().computePosition(nEndCol, GetColWidthPx);
673  tools::Long nDocHeightPixel = pThisDoc->GetScaledRowHeight(0, nEndRow, nTab, fPPTY);
674 
675  if (nDocWidthPixel > 0 && nDocHeightPixel > 0)
676  {
677  // convert to twips
678  aSize.setWidth(nDocWidthPixel / fPPTX);
679  aSize.setHeight(nDocHeightPixel / fPPTY);
680  }
681  else
682  {
683  // convert to twips
684  aSize.setWidth(rDoc.GetColWidth(0, nEndCol, nTab));
685  aSize.setHeight(rDoc.GetRowHeight(0, nEndRow, nTab));
686  }
687 
688  return aSize;
689 }
690 
691 
692 void ScModelObj::postKeyEvent(int nType, int nCharCode, int nKeyCode)
693 {
694  SolarMutexGuard aGuard;
695  SfxLokHelper::postKeyEventAsync(getDocWindow(), nType, nCharCode, nKeyCode);
696 }
697 
698 void ScModelObj::postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons, int nModifier)
699 {
700  SolarMutexGuard aGuard;
701 
702  ScTabViewShell* pViewShell = pDocShell->GetBestViewShell(false);
703 
704  // FIXME: Can this happen? What should we do?
705  if (!pViewShell)
706  return;
707 
708  ScViewData* pViewData = &pViewShell->GetViewData();
709 
710  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
711 
712  if (!pGridWindow)
713  return;
714 
715  // check if user hit a chart which is being edited by him
716  ScTabViewShell * pTabViewShell = pViewData->GetViewShell();
717  LokChartHelper aChartHelper(pTabViewShell);
718  if (aChartHelper.postMouseEvent(nType, nX, nY,
719  nCount, nButtons, nModifier,
720  pViewData->GetPPTX(), pViewData->GetPPTY()))
721  return;
722 
723  // check if the user hit a chart which is being edited by someone else
724  // and, if so, skip current mouse event
725  if (nType != LOK_MOUSEEVENT_MOUSEMOVE)
726  {
727  if (LokChartHelper::HitAny(Point(nX, nY)))
728  return;
729  }
730 
731  // Calc operates in pixels...
732  const Point aPos(nX * pViewData->GetPPTX(), nY * pViewData->GetPPTY());
733 
734  LokMouseEventData aMouseEventData(nType, aPos, nCount, MouseEventModifiers::SIMPLECLICK,
735  nButtons, nModifier);
736  aMouseEventData.maLogicPosition = Point(convertTwipToMm100(nX), convertTwipToMm100(nY));
737  SfxLokHelper::postMouseEventAsync(pGridWindow, aMouseEventData);
738 }
739 
740 void ScModelObj::setTextSelection(int nType, int nX, int nY)
741 {
742  SolarMutexGuard aGuard;
743  ScViewData* pViewData = ScDocShell::GetViewData();
744  ScTabViewShell* pViewShell = pViewData->GetViewShell();
745 
746  LokChartHelper aChartHelper(pViewShell);
747  if (aChartHelper.setTextSelection(nType, nX, nY))
748  return;
749 
750  ScInputHandler* pInputHandler = SC_MOD()->GetInputHdl(pViewShell);
751  ScDrawView* pDrawView = pViewData->GetScDrawView();
752 
753  bool bHandled = false;
754 
755  if (pInputHandler && pInputHandler->IsInputMode())
756  {
757  // forwarding to editeng - we are editing the cell content
758  EditView* pTableView = pInputHandler->GetTableView();
759  assert(pTableView);
760 
762 
763  if (pTableView->GetOutputArea().IsInside(aPoint))
764  {
765  switch (nType)
766  {
767  case LOK_SETTEXTSELECTION_START:
768  pTableView->SetCursorLogicPosition(aPoint, /*bPoint=*/false, /*bClearMark=*/false);
769  break;
770  case LOK_SETTEXTSELECTION_END:
771  pTableView->SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/false);
772  break;
773  case LOK_SETTEXTSELECTION_RESET:
774  pTableView->SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/true);
775  break;
776  default:
777  assert(false);
778  break;
779  }
780  bHandled = true;
781  }
782  }
783  else if (pDrawView && pDrawView->IsTextEdit())
784  {
785  // forwarding to editeng - we are editing the text in shape
786  OutlinerView* pOutlinerView = pDrawView->GetTextEditOutlinerView();
787  EditView& rEditView = pOutlinerView->GetEditView();
788 
790  switch (nType)
791  {
792  case LOK_SETTEXTSELECTION_START:
793  rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/false, /*bClearMark=*/false);
794  break;
795  case LOK_SETTEXTSELECTION_END:
796  rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/false);
797  break;
798  case LOK_SETTEXTSELECTION_RESET:
799  rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/true);
800  break;
801  default:
802  assert(false);
803  break;
804  }
805  bHandled = true;
806  }
807 
808  if (!bHandled)
809  {
810  // just update the cell selection
811  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
812  if (!pGridWindow)
813  return;
814 
815  // move the cell selection handles
816  pGridWindow->SetCellSelectionPixel(nType, nX * pViewData->GetPPTX(), nY * pViewData->GetPPTY());
817  }
818 }
819 
820 uno::Reference<datatransfer::XTransferable> ScModelObj::getSelection()
821 {
822  SolarMutexGuard aGuard;
823 
824  TransferableDataHelper aDataHelper;
825  ScViewData* pViewData = ScDocShell::GetViewData();
826  uno::Reference<datatransfer::XTransferable> xTransferable;
827 
828  if ( ScEditShell * pShell = dynamic_cast<ScEditShell*>( pViewData->GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) ) )
829  xTransferable = pShell->GetEditView()->GetTransferable();
830  else if ( nullptr != dynamic_cast<ScDrawTextObjectBar*>( pViewData->GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) ))
831  {
832  ScDrawView* pView = pViewData->GetScDrawView();
833  OutlinerView* pOutView = pView->GetTextEditOutlinerView();
834  if (pOutView)
835  xTransferable = pOutView->GetEditView().GetTransferable();
836  }
837  else if ( ScDrawShell * pDrawShell = dynamic_cast<ScDrawShell*>( pViewData->GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) ) )
838  xTransferable = pDrawShell->GetDrawView()->CopyToTransferable();
839  else
840  {
841  ScTransferObj* pObj = pViewData->GetViewShell()->CopyToTransferable();
842  xTransferable.set( pObj );
843  }
844 
845  if (!xTransferable.is())
846  xTransferable.set( aDataHelper.GetTransferable() );
847 
848  return xTransferable;
849 }
850 
851 void ScModelObj::setGraphicSelection(int nType, int nX, int nY)
852 {
853  SolarMutexGuard aGuard;
854 
855  ScTabViewShell* pViewShell = pDocShell->GetBestViewShell(false);
856 
857  // FIXME: Can this happen? What should we do?
858  if (!pViewShell)
859  return;
860 
861  ScViewData* pViewData = &pViewShell->GetViewData();
862 
863  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
864 
865  double fPPTX = pViewData->GetPPTX();
866  double fPPTY = pViewData->GetPPTY();
867 
868  pViewShell = pViewData->GetViewShell();
869  LokChartHelper aChartHelper(pViewShell);
870  if (aChartHelper.setGraphicSelection(nType, nX, nY, fPPTX, fPPTY))
871  return;
872 
873  int nPixelX = nX * fPPTX;
874  int nPixelY = nY * fPPTY;
875 
876  switch (nType)
877  {
878  case LOK_SETGRAPHICSELECTION_START:
879  {
880  MouseEvent aClickEvent(Point(nPixelX, nPixelY), 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
881  pGridWindow->MouseButtonDown(aClickEvent);
882  MouseEvent aMoveEvent(Point(nPixelX, nPixelY), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
883  pGridWindow->MouseMove(aMoveEvent);
884  }
885  break;
886  case LOK_SETGRAPHICSELECTION_END:
887  {
888  MouseEvent aMoveEvent(Point(nPixelX, nPixelY), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
889  pGridWindow->MouseMove(aMoveEvent);
890  MouseEvent aClickEvent(Point(nPixelX, nPixelY), 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
891  pGridWindow->MouseButtonUp(aClickEvent);
892  }
893  break;
894  default:
895  assert(false);
896  break;
897  }
898 }
899 
901 {
902  SolarMutexGuard aGuard;
903 
904  ScViewData* pViewData = ScDocShell::GetViewData();
905  ScTabViewShell* pViewShell = pViewData->GetViewShell();
906 
907  // deselect the shapes & texts
908  ScDrawView* pDrawView = pViewShell->GetScDrawView();
909  if (pDrawView)
910  {
911  pDrawView->ScEndTextEdit();
912  pDrawView->UnmarkAll();
913  }
914  else
915  pViewShell->Unmark();
916 
917  // and hide the cell and text selection
918  pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, "");
919  SfxLokHelper::notifyOtherViews(pViewShell, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", "");
920 }
921 
922 void ScModelObj::setClipboard(const uno::Reference<datatransfer::clipboard::XClipboard>& xClipboard)
923 {
924  SolarMutexGuard aGuard;
925 
926  ScViewData* pViewData = ScDocShell::GetViewData();
927  if (!pViewData)
928  return;
929 
930  pViewData->GetActiveWin()->SetClipboard(xClipboard);
931 }
932 
934 {
935  SolarMutexGuard aGuard;
936 
937  ScViewData* pViewData = ScDocShell::GetViewData();
938  if (!pViewData)
939  return false;
940 
941 
943  return EditEngine::HasValidData(aDataHelper.GetTransferable());
944 }
945 
946 void ScModelObj::setClientZoom(int nTilePixelWidth_, int nTilePixelHeight_, int nTileTwipWidth_, int nTileTwipHeight_)
947 {
948  ScViewData* pViewData = ScDocShell::GetViewData();
949 
950  if (!pViewData)
951  return;
952 
953  const Fraction newZoomX(nTilePixelWidth_ * TWIPS_PER_PIXEL, nTileTwipWidth_);
954  const Fraction newZoomY(nTilePixelHeight_ * TWIPS_PER_PIXEL, nTileTwipHeight_);
955 
956  if (pViewData->GetZoomX() == newZoomX && pViewData->GetZoomY() == newZoomY)
957  return;
958 
959  pViewData->SetZoom(newZoomX, newZoomY, true);
960 
961  // refresh our view's take on other view's cursors & selections
962  pViewData->GetActiveWin()->updateKitOtherCursors();
963  pViewData->GetActiveWin()->updateOtherKitSelections();
964 
965  if (ScDrawView* pDrawView = pViewData->GetScDrawView())
966  pDrawView->resetGridOffsetsForAllSdrPageViews();
967 }
968 
970 {
971  ScViewData* pViewData = ScDocShell::GetViewData();
972 
973  if (!pViewData)
974  return;
975 
976  ScTabView* pTabView = pViewData->GetView();
977  if (!pTabView)
978  return;
979 
980  pTabView->getRowColumnHeaders(rRectangle, rJsonWriter);
981 }
982 
983 OString ScModelObj::getSheetGeometryData(bool bColumns, bool bRows, bool bSizes, bool bHidden,
984  bool bFiltered, bool bGroups)
985 {
986  ScViewData* pViewData = ScDocShell::GetViewData();
987 
988  if (!pViewData)
989  return "";
990 
991  ScTabView* pTabView = pViewData->GetView();
992  if (!pTabView)
993  return "";
994 
995  return pTabView->getSheetGeometryData(bColumns, bRows, bSizes, bHidden, bFiltered, bGroups);
996 }
997 
999 {
1000  SolarMutexGuard aGuard;
1001 
1002  ScViewData* pViewData = ScDocShell::GetViewData();
1003 
1004  if (!pViewData)
1005  return;
1006 
1007  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
1008  if (!pGridWindow)
1009  return;
1010 
1011  rJsonWriter.put("commandName", ".uno:CellCursor");
1012  rJsonWriter.put("commandValues", pGridWindow->getCellCursor());
1013 }
1014 
1016 {
1017  SolarMutexGuard aGuard;
1018 
1019  ScViewData* pViewData = ScDocShell::GetViewData();
1020  if (!pViewData)
1021  return PointerStyle::Arrow;
1022 
1023  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
1024  if (!pGridWindow)
1025  return PointerStyle::Arrow;
1026 
1027  return pGridWindow->GetPointer();
1028 }
1029 
1031 {
1032  if (pDocShell)
1033  {
1034  if (ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack())
1035  pChangeTrack->GetChangeTrackInfo(rJson);
1036  }
1037 }
1038 
1040 {
1041  ScViewData* pViewData = ScDocShell::GetViewData();
1042  if (!pViewData)
1043  return;
1044 
1045  // set the PgUp/PgDown offset
1046  pViewData->ForcePageUpDownOffset(rRectangle.GetHeight());
1047 
1048  // Store the visible area so that we can use at places like shape insertion
1049  pViewData->setLOKVisibleArea(rRectangle);
1050 
1052  comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
1053  {
1054  ScTabView* pTabView = pViewData->GetView();
1055  if (pTabView)
1056  pTabView->extendTiledAreaIfNeeded();
1057  }
1058 }
1059 
1060 void ScModelObj::setOutlineState(bool bColumn, int nLevel, int nIndex, bool bHidden)
1061 {
1062  ScViewData* pViewData = ScDocShell::GetViewData();
1063 
1064  if (!pViewData)
1065  return;
1066 
1067  ScDBFunc* pFunc = pViewData->GetView();
1068 
1069  if (pFunc)
1070  pFunc->SetOutlineState(bColumn, nLevel, nIndex, bHidden);
1071 }
1072 
1074 {
1075  if (!pDocShell)
1076  return;
1077 
1078  ScDocument& rDoc = pDocShell->GetDocument();
1079  std::vector<sc::NoteEntry> aNotes;
1080  rDoc.GetAllNoteEntries(aNotes);
1081 
1082  auto commentsNode = rJsonWriter.startNode("comments");
1083  for (const sc::NoteEntry& aNote : aNotes)
1084  {
1085  auto commentNode = rJsonWriter.startNode("");
1086 
1087  rJsonWriter.put("id", aNote.mpNote->GetId());
1088  rJsonWriter.put("tab", aNote.maPos.Tab());
1089  rJsonWriter.put("author", aNote.mpNote->GetAuthor());
1090  rJsonWriter.put("dateTime", aNote.mpNote->GetDate());
1091  rJsonWriter.put("text", aNote.mpNote->GetText());
1092 
1093  // Calculating the cell cursor position
1094  ScViewData* pViewData = ScDocShell::GetViewData();
1095  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
1096  if (pGridWindow)
1097  {
1098  SCCOL nX = aNote.maPos.Col();
1099  SCROW nY = aNote.maPos.Row();
1100  Point aScrPos = pViewData->GetScrPos(nX, nY, pViewData->GetActivePart(), true);
1101  tools::Long nSizeXPix;
1102  tools::Long nSizeYPix;
1103  pViewData->GetMergeSizePixel(nX, nY, nSizeXPix, nSizeYPix);
1104 
1105  double fPPTX = pViewData->GetPPTX();
1106  double fPPTY = pViewData->GetPPTY();
1107  tools::Rectangle aRect(Point(aScrPos.getX() / fPPTX, aScrPos.getY() / fPPTY),
1108  Size(nSizeXPix / fPPTX, nSizeYPix / fPPTY));
1109 
1110  rJsonWriter.put("cellPos", aRect.toString());
1111  }
1112  }
1113 }
1114 
1116 {
1117  if (!pDocShell)
1118  return;
1119 
1120  ScDocument& rDoc = pDocShell->GetDocument();
1121  std::vector<sc::NoteEntry> aNotes;
1122  rDoc.GetAllNoteEntries(aNotes);
1123 
1124  auto commentsNode = rJsonWriter.startNode("commentsPos");
1125  for (const sc::NoteEntry& aNote : aNotes)
1126  {
1127  auto commentNode = rJsonWriter.startNode("");
1128 
1129  rJsonWriter.put("id", aNote.mpNote->GetId());
1130  rJsonWriter.put("tab", aNote.maPos.Tab());
1131 
1132  // Calculating the cell cursor position
1133  ScViewData* pViewData = ScDocShell::GetViewData();
1134  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
1135  if (pGridWindow)
1136  {
1137  SCCOL nX = aNote.maPos.Col();
1138  SCROW nY = aNote.maPos.Row();
1139  Point aScrPos = pViewData->GetScrPos(nX, nY, pViewData->GetActivePart(), true);
1140  tools::Long nSizeXPix;
1141  tools::Long nSizeYPix;
1142  pViewData->GetMergeSizePixel(nX, nY, nSizeXPix, nSizeYPix);
1143 
1144  double fPPTX = pViewData->GetPPTX();
1145  double fPPTY = pViewData->GetPPTY();
1146  tools::Rectangle aRect(Point(aScrPos.getX() / fPPTX, aScrPos.getY() / fPPTY),
1147  Size(nSizeXPix / fPPTX, nSizeYPix / fPPTY));
1148 
1149  rJsonWriter.put("cellPos", aRect.toString());
1150  }
1151  }
1152 }
1153 
1154 void ScModelObj::completeFunction(const OUString& rFunctionName)
1155 {
1156  ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1157  if (pHdl)
1158  {
1159  assert(!rFunctionName.isEmpty());
1160  pHdl->LOKPasteFunctionData(rFunctionName);
1161  }
1162 }
1163 
1164 void ScModelObj::initializeForTiledRendering(const css::uno::Sequence<css::beans::PropertyValue>& rArguments)
1165 {
1166  SolarMutexGuard aGuard;
1167 
1168  // disable word autocompletion
1169  ScAppOptions aAppOptions( SC_MOD()->GetAppOptions() );
1170  aAppOptions.SetAutoComplete(false);
1171  SC_MOD()->SetAppOptions(aAppOptions);
1172 
1173  for (const beans::PropertyValue& rValue : rArguments)
1174  {
1175  if (rValue.Name == ".uno:SpellOnline" && rValue.Value.has<bool>())
1176  {
1177  ScDocOptions options = GetDocument()->GetDocOptions();
1178  options.SetAutoSpell(rValue.Value.get<bool>());
1179  GetDocument()->SetDocOptions(options);
1180  }
1181  }
1182 
1183  // show us the text exactly
1184  ScInputOptions aInputOptions(SC_MOD()->GetInputOptions());
1185  aInputOptions.SetTextWysiwyg(true);
1186  aInputOptions.SetReplaceCellsWarn(false);
1187  SC_MOD()->SetInputOptions(aInputOptions);
1189 
1190  // when the "This document may contain formatting or content that cannot
1191  // be saved..." dialog appears, it is auto-cancelled with tiled rendering,
1192  // causing 'Save' being disabled; so let's always save to the original
1193  // format
1195 }
1196 
1198 {
1199  SC_QUERYINTERFACE( sheet::XSpreadsheetDocument )
1200  SC_QUERYINTERFACE( document::XActionLockable )
1201  SC_QUERYINTERFACE( sheet::XCalculatable )
1202  SC_QUERYINTERFACE( util::XProtectable )
1203  SC_QUERYINTERFACE( drawing::XDrawPagesSupplier )
1204  SC_QUERYINTERFACE( sheet::XGoalSeek )
1205  SC_QUERYINTERFACE( sheet::XConsolidatable )
1206  SC_QUERYINTERFACE( sheet::XDocumentAuditing )
1207  SC_QUERYINTERFACE( style::XStyleFamiliesSupplier )
1208  SC_QUERYINTERFACE( view::XRenderable )
1209  SC_QUERYINTERFACE( document::XLinkTargetSupplier )
1210  SC_QUERYINTERFACE( beans::XPropertySet )
1211  SC_QUERYINTERFACE( lang::XMultiServiceFactory )
1212  SC_QUERYINTERFACE( lang::XServiceInfo )
1213  SC_QUERYINTERFACE( util::XChangesNotifier )
1214  SC_QUERYINTERFACE( sheet::opencl::XOpenCLSelection )
1215  SC_QUERYINTERFACE( chart2::XDataProviderAccess )
1216 
1217  uno::Any aRet(SfxBaseModel::queryInterface( rType ));
1218  if ( !aRet.hasValue()
1225  {
1226  GetFormatter();
1227  if ( xNumberAgg.is() )
1228  aRet = xNumberAgg->queryAggregation( rType );
1229  }
1230 
1231  return aRet;
1232 }
1233 
1234 void SAL_CALL ScModelObj::acquire() throw()
1235 {
1237 }
1238 
1239 void SAL_CALL ScModelObj::release() throw()
1240 {
1242 }
1243 
1244 uno::Sequence<uno::Type> SAL_CALL ScModelObj::getTypes()
1245 {
1246  static const uno::Sequence<uno::Type> aTypes = [&]()
1247  {
1248  uno::Sequence<uno::Type> aAggTypes;
1249  if ( GetFormatter().is() )
1250  {
1252  uno::Any aNumProv(xNumberAgg->queryAggregation(rProvType));
1253  if(auto xNumProv
1254  = o3tl::tryAccess<uno::Reference<lang::XTypeProvider>>(aNumProv))
1255  {
1256  aAggTypes = (*xNumProv)->getTypes();
1257  }
1258  }
1261  aAggTypes,
1262  uno::Sequence<uno::Type>
1263  {
1280  } );
1281  }();
1282  return aTypes;
1283 }
1284 
1285 uno::Sequence<sal_Int8> SAL_CALL ScModelObj::getImplementationId()
1286 {
1287  return css::uno::Sequence<sal_Int8>();
1288 }
1289 
1290 void ScModelObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1291 {
1292  // Not interested in reference update hints here
1293 
1294  const SfxHintId nId = rHint.GetId();
1295  if ( nId == SfxHintId::Dying )
1296  {
1297  pDocShell = nullptr; // has become invalid
1298  if (xNumberAgg.is())
1299  {
1300  SvNumberFormatsSupplierObj* pNumFmt =
1301  comphelper::getUnoTunnelImplementation<SvNumberFormatsSupplierObj>(
1302  uno::Reference<util::XNumberFormatsSupplier>(xNumberAgg, uno::UNO_QUERY) );
1303  if ( pNumFmt )
1304  pNumFmt->SetNumberFormatter( nullptr );
1305  }
1306 
1307  pPrintFuncCache.reset(); // must be deleted because it has a pointer to the DocShell
1308  m_pPrintState.reset();
1309  }
1310  else if ( nId == SfxHintId::DataChanged )
1311  {
1312  // cached data for rendering become invalid when contents change
1313  // (if a broadcast is added to SetDrawModified, is has to be tested here, too)
1314 
1315  pPrintFuncCache.reset();
1316  m_pPrintState.reset();
1317 
1318  // handle "OnCalculate" sheet events (search also for VBA event handlers)
1319  if ( pDocShell )
1320  {
1321  ScDocument& rDoc = pDocShell->GetDocument();
1322  if ( rDoc.GetVbaEventProcessor().is() )
1323  {
1324  // If the VBA event processor is set, HasAnyCalcNotification is much faster than HasAnySheetEventScript
1327  }
1328  else
1329  {
1332  }
1333  }
1334  }
1335 
1336  // always call parent - SfxBaseModel might need to handle the same hints again
1337  SfxBaseModel::Notify( rBC, rHint ); // SfxBaseModel is derived from SfxListener
1338 }
1339 
1340 // XSpreadsheetDocument
1341 
1342 uno::Reference<sheet::XSpreadsheets> SAL_CALL ScModelObj::getSheets()
1343 {
1344  SolarMutexGuard aGuard;
1345  if (pDocShell)
1346  return new ScTableSheetsObj(pDocShell);
1347  return nullptr;
1348 }
1349 
1350 css::uno::Reference< ::css::chart2::data::XDataProvider > SAL_CALL ScModelObj::createDataProvider()
1351 {
1352  if (pDocShell)
1353  {
1354  return css::uno::Reference< ::css::chart2::data::XDataProvider > (
1356  }
1357  return nullptr;
1358 }
1359 
1360 // XStyleFamiliesSupplier
1361 
1362 uno::Reference<container::XNameAccess> SAL_CALL ScModelObj::getStyleFamilies()
1363 {
1364  SolarMutexGuard aGuard;
1365  if (pDocShell)
1366  return new ScStyleFamiliesObj(pDocShell);
1367  return nullptr;
1368 }
1369 
1370 // XRenderable
1371 
1372 static OutputDevice* lcl_GetRenderDevice( const uno::Sequence<beans::PropertyValue>& rOptions )
1373 {
1374  OutputDevice* pRet = nullptr;
1375  for (const beans::PropertyValue& rProp : rOptions)
1376  {
1377  const OUString & rPropName = rProp.Name;
1378 
1379  if (rPropName == SC_UNONAME_RENDERDEV)
1380  {
1381  uno::Reference<awt::XDevice> xRenderDevice(rProp.Value, uno::UNO_QUERY);
1382  if ( xRenderDevice.is() )
1383  {
1384  VCLXDevice* pDevice = comphelper::getUnoTunnelImplementation<VCLXDevice>( xRenderDevice );
1385  if ( pDevice )
1386  {
1387  pRet = pDevice->GetOutputDevice().get();
1388  pRet->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
1389  }
1390  }
1391  }
1392  }
1393  return pRet;
1394 }
1395 
1396 static bool lcl_ParseTarget( const OUString& rTarget, ScRange& rTargetRange, tools::Rectangle& rTargetRect,
1397  bool& rIsSheet, ScDocument& rDoc, SCTAB nSourceTab )
1398 {
1399  // test in same order as in SID_CURRENTCELL execute
1400 
1401  ScAddress aAddress;
1402  SCTAB nNameTab;
1403  sal_Int32 nNumeric = 0;
1404 
1405  bool bRangeValid = false;
1406  bool bRectValid = false;
1407 
1408  if ( rTargetRange.Parse( rTarget, rDoc ) & ScRefFlags::VALID )
1409  {
1410  bRangeValid = true; // range reference
1411  }
1412  else if ( aAddress.Parse( rTarget, rDoc ) & ScRefFlags::VALID )
1413  {
1414  rTargetRange = aAddress;
1415  bRangeValid = true; // cell reference
1416  }
1417  else if ( ScRangeUtil::MakeRangeFromName( rTarget, rDoc, nSourceTab, rTargetRange ) ||
1418  ScRangeUtil::MakeRangeFromName( rTarget, rDoc, nSourceTab, rTargetRange, RUTL_DBASE ) )
1419  {
1420  bRangeValid = true; // named range or database range
1421  }
1422  else if ( comphelper::string::isdigitAsciiString(rTarget) &&
1423  ( nNumeric = rTarget.toInt32() ) > 0 && nNumeric <= rDoc.MaxRow()+1 )
1424  {
1425  // row number is always mapped to cell A(row) on the same sheet
1426  rTargetRange = ScAddress( 0, static_cast<SCROW>(nNumeric-1), nSourceTab ); // target row number is 1-based
1427  bRangeValid = true; // row number
1428  }
1429  else if ( rDoc.GetTable( rTarget, nNameTab ) )
1430  {
1431  rTargetRange = ScAddress(0,0,nNameTab);
1432  bRangeValid = true; // sheet name
1433  rIsSheet = true; // needs special handling (first page of the sheet)
1434  }
1435  else
1436  {
1437  // look for named drawing object
1438 
1439  ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
1440  if ( pDrawLayer )
1441  {
1442  SCTAB nTabCount = rDoc.GetTableCount();
1443  for (SCTAB i=0; i<nTabCount && !bRangeValid; i++)
1444  {
1445  SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(i));
1446  OSL_ENSURE(pPage,"Page ?");
1447  if (pPage)
1448  {
1449  SdrObjListIter aIter( pPage, SdrIterMode::DeepWithGroups );
1450  SdrObject* pObject = aIter.Next();
1451  while (pObject && !bRangeValid)
1452  {
1453  if ( ScDrawLayer::GetVisibleName( pObject ) == rTarget )
1454  {
1455  rTargetRect = pObject->GetLogicRect(); // 1/100th mm
1456  rTargetRange = rDoc.GetRange( i, rTargetRect ); // underlying cells
1457  bRangeValid = bRectValid = true; // rectangle is valid
1458  }
1459  pObject = aIter.Next();
1460  }
1461  }
1462  }
1463  }
1464  }
1465  if ( bRangeValid && !bRectValid )
1466  {
1467  // get rectangle for cell range
1468  rTargetRect = rDoc.GetMMRect( rTargetRange.aStart.Col(), rTargetRange.aStart.Row(),
1469  rTargetRange.aEnd.Col(), rTargetRange.aEnd.Row(),
1470  rTargetRange.aStart.Tab() );
1471  }
1472 
1473  return bRangeValid;
1474 }
1475 
1477  const uno::Sequence< beans::PropertyValue >& rOptions,
1478  ScMarkData& rMark,
1479  ScPrintSelectionStatus& rStatus, OUString& rPagesStr,
1480  bool& rbRenderToGraphic ) const
1481 {
1482  OSL_ENSURE( !rMark.IsMarked() && !rMark.IsMultiMarked(), "FillRenderMarkData: MarkData must be empty" );
1483  OSL_ENSURE( pDocShell, "FillRenderMarkData: DocShell must be set" );
1484 
1485  bool bDone = false;
1486 
1487  uno::Reference<frame::XController> xView;
1488 
1489  // defaults when no options are passed: all sheets, include empty pages
1490  bool bSelectedSheetsOnly = false;
1491  bool bSuppressEmptyPages = true;
1492 
1493  bool bHasPrintContent = false;
1494  sal_Int32 nPrintContent = 0; // all sheets / selected sheets / selected cells
1495  sal_Int32 nPrintRange = 0; // all pages / pages
1496  sal_Int32 nEOContent = 0; // even pages / odd pages
1497  OUString aPageRange; // "pages" edit value
1498 
1499  for( const auto& rOption : rOptions )
1500  {
1501  if ( rOption.Name == "IsOnlySelectedSheets" )
1502  {
1503  rOption.Value >>= bSelectedSheetsOnly;
1504  }
1505  else if ( rOption.Name == "IsSuppressEmptyPages" )
1506  {
1507  rOption.Value >>= bSuppressEmptyPages;
1508  }
1509  else if ( rOption.Name == "PageRange" )
1510  {
1511  rOption.Value >>= aPageRange;
1512  }
1513  else if ( rOption.Name == "PrintRange" )
1514  {
1515  rOption.Value >>= nPrintRange;
1516  }
1517  else if ( rOption.Name == "EvenOdd" )
1518  {
1519  rOption.Value >>= nEOContent;
1520  }
1521  else if ( rOption.Name == "PrintContent" )
1522  {
1523  bHasPrintContent = true;
1524  rOption.Value >>= nPrintContent;
1525  }
1526  else if ( rOption.Name == "View" )
1527  {
1528  rOption.Value >>= xView;
1529  }
1530  else if ( rOption.Name == "RenderToGraphic" )
1531  {
1532  rOption.Value >>= rbRenderToGraphic;
1533  }
1534  }
1535 
1536  // "Print Content" selection wins over "Selected Sheets" option
1537  if ( bHasPrintContent )
1538  bSelectedSheetsOnly = ( nPrintContent != 0 );
1539 
1540  uno::Reference<uno::XInterface> xInterface(aSelection, uno::UNO_QUERY);
1541  if ( xInterface.is() )
1542  {
1543  ScCellRangesBase* pSelObj = comphelper::getUnoTunnelImplementation<ScCellRangesBase>( xInterface );
1544  uno::Reference< drawing::XShapes > xShapes( xInterface, uno::UNO_QUERY );
1545  if ( pSelObj && pSelObj->GetDocShell() == pDocShell )
1546  {
1547  bool bSheet = ( comphelper::getUnoTunnelImplementation<ScTableSheetObj>( xInterface ) != nullptr );
1548  bool bCursor = pSelObj->IsCursorOnly();
1549  const ScRangeList& rRanges = pSelObj->GetRangeList();
1550 
1551  rMark.MarkFromRangeList( rRanges, false );
1552  rMark.MarkToSimple();
1553 
1554  if ( rMark.IsMultiMarked() )
1555  {
1556  // #i115266# copy behavior of old printing:
1557  // treat multiple selection like a single selection with the enclosing range
1558  ScRange aMultiMarkArea;
1559  rMark.GetMultiMarkArea( aMultiMarkArea );
1560  rMark.ResetMark();
1561  rMark.SetMarkArea( aMultiMarkArea );
1562  }
1563 
1564  if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
1565  {
1566  // a sheet object is treated like an empty selection: print the used area of the sheet
1567 
1568  if ( bCursor || bSheet ) // nothing selected -> use whole tables
1569  {
1570  rMark.ResetMark(); // doesn't change table selection
1571  rStatus.SetMode( SC_PRINTSEL_CURSOR );
1572  }
1573  else
1574  rStatus.SetMode( SC_PRINTSEL_RANGE );
1575 
1576  rStatus.SetRanges( rRanges );
1577  bDone = true;
1578  }
1579  // multi selection isn't supported
1580  }
1581  else if( xShapes.is() )
1582  {
1583  //print a selected ole object
1584  // multi selection isn't supported yet
1585  uno::Reference< drawing::XShape > xShape( xShapes->getByIndex(0), uno::UNO_QUERY );
1586  SvxShape* pShape = comphelper::getUnoTunnelImplementation<SvxShape>( xShape );
1587  if( pShape )
1588  {
1589  SdrObject *pSdrObj = pShape->GetSdrObject();
1590  if( pDocShell )
1591  {
1592  ScDocument& rDoc = pDocShell->GetDocument();
1593  if( pSdrObj )
1594  {
1595  tools::Rectangle aObjRect = pSdrObj->GetCurrentBoundRect();
1596  SCTAB nCurrentTab = ScDocShell::GetCurTab();
1597  ScRange aRange = rDoc.GetRange( nCurrentTab, aObjRect );
1598  rMark.SetMarkArea( aRange );
1599 
1600  if( rMark.IsMarked() && !rMark.IsMultiMarked() )
1601  {
1603  bDone = true;
1604  }
1605  }
1606  }
1607  }
1608  }
1609  else if ( comphelper::getUnoTunnelImplementation<ScModelObj>( xInterface ) == this )
1610  {
1611  // render the whole document
1612  // -> no selection, all sheets
1613 
1614  SCTAB nTabCount = pDocShell->GetDocument().GetTableCount();
1615  for (SCTAB nTab = 0; nTab < nTabCount; nTab++)
1616  rMark.SelectTable( nTab, true );
1617  rStatus.SetMode( SC_PRINTSEL_DOCUMENT );
1618  bDone = true;
1619  }
1620  // other selection types aren't supported
1621  }
1622 
1623  // restrict to selected sheets if a view is available
1624  uno::Reference<sheet::XSelectedSheetsSupplier> xSelectedSheets(xView, uno::UNO_QUERY);
1625  if (bSelectedSheetsOnly && xSelectedSheets.is())
1626  {
1627  const uno::Sequence<sal_Int32> aSelected = xSelectedSheets->getSelectedSheets();
1628  ScMarkData::MarkedTabsType aSelectedTabs;
1629  SCTAB nMaxTab = pDocShell->GetDocument().GetTableCount() -1;
1630  for (const auto& rSelected : aSelected)
1631  {
1632  SCTAB nSelected = static_cast<SCTAB>(rSelected);
1633  if (ValidTab(nSelected, nMaxTab))
1634  aSelectedTabs.insert(nSelected);
1635  }
1636  rMark.SetSelectedTabs(aSelectedTabs);
1637  }
1638 
1639  ScPrintOptions aNewOptions;
1640  aNewOptions.SetSkipEmpty( bSuppressEmptyPages );
1641  aNewOptions.SetAllSheets( !bSelectedSheetsOnly );
1642  rStatus.SetOptions( aNewOptions );
1643 
1644  // "PrintRange" enables (1) or disables (0) the "PageRange" edit
1645  if ( nPrintRange == 1 )
1646  rPagesStr = aPageRange;
1647  else
1648  rPagesStr.clear();
1649 
1650  return bDone;
1651 }
1652 
1653 sal_Int32 SAL_CALL ScModelObj::getRendererCount(const uno::Any& aSelection,
1654  const uno::Sequence<beans::PropertyValue>& rOptions)
1655 {
1656  SolarMutexGuard aGuard;
1657  if (!pDocShell)
1658  {
1659  throw lang::DisposedException( OUString(),
1660  static_cast< sheet::XSpreadsheetDocument* >(this) );
1661  }
1662 
1663  ScMarkData aMark(GetDocument()->GetSheetLimits());
1664  ScPrintSelectionStatus aStatus;
1665  OUString aPagesStr;
1666  bool bRenderToGraphic = false;
1667  if ( !FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr, bRenderToGraphic ) )
1668  return 0;
1669 
1670  // The same ScPrintFuncCache object in pPrintFuncCache is used as long as
1671  // the same selection is used (aStatus) and the document isn't changed
1672  // (pPrintFuncCache is cleared in Notify handler)
1673 
1674  if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) )
1675  {
1676  pPrintFuncCache.reset(new ScPrintFuncCache( pDocShell, aMark, aStatus ));
1677  }
1678  sal_Int32 nPages = pPrintFuncCache->GetPageCount();
1679 
1680  m_pPrintState.reset();
1681  maValidPages.clear();
1682 
1683  sal_Int32 nContent = 0;
1684  sal_Int32 nEOContent = 0;
1685  bool bSinglePageSheets = false;
1686  for ( const auto& rValue : rOptions)
1687  {
1688  if ( rValue.Name == "PrintRange" )
1689  {
1690  rValue.Value >>= nContent;
1691  }
1692  else if ( rValue.Name == "SinglePageSheets" )
1693  {
1694  rValue.Value >>= bSinglePageSheets;
1695  }
1696  else if ( rValue.Name == "EvenOdd" )
1697  {
1698  rValue.Value >>= nEOContent;
1699  }
1700  }
1701 
1702  if (bSinglePageSheets)
1703  {
1704  return pDocShell->GetDocument().GetTableCount();
1705  }
1706 
1707  bool bIsPrintEvenPages = (nEOContent != 1 && nContent == 0) || nContent != 0;
1708  bool bIsPrintOddPages = (nEOContent != 2 && nContent == 0) || nContent != 0;
1709 
1710  for ( sal_Int32 nPage = 1; nPage <= nPages; nPage++ )
1711  {
1712  if ( (bIsPrintEvenPages && IsOnEvenPage( nPage )) || (bIsPrintOddPages && !IsOnEvenPage( nPage )) )
1713  maValidPages.push_back( nPage );
1714  }
1715 
1716  sal_Int32 nSelectCount = static_cast<sal_Int32>( maValidPages.size() );
1717 
1718  if ( nEOContent == 1 || nEOContent == 2 ) // even pages / odd pages
1719  return nSelectCount;
1720 
1721  if ( !aPagesStr.isEmpty() )
1722  {
1723  StringRangeEnumerator aRangeEnum( aPagesStr, 0, nPages-1 );
1724  nSelectCount = aRangeEnum.size();
1725  }
1726  return (nSelectCount > 0) ? nSelectCount : 1;
1727 }
1728 
1729 static sal_Int32 lcl_GetRendererNum( sal_Int32 nSelRenderer, const OUString& rPagesStr, sal_Int32 nTotalPages )
1730 {
1731  if ( rPagesStr.isEmpty() )
1732  return nSelRenderer;
1733 
1734  StringRangeEnumerator aRangeEnum( rPagesStr, 0, nTotalPages-1 );
1735  StringRangeEnumerator::Iterator aIter = aRangeEnum.begin();
1736  StringRangeEnumerator::Iterator aEnd = aRangeEnum.end();
1737  for ( ; nSelRenderer > 0 && aIter != aEnd; --nSelRenderer )
1738  ++aIter;
1739 
1740  return *aIter; // returns -1 if reached the end
1741 }
1742 
1743 static bool lcl_renderSelectionToGraphic( bool bRenderToGraphic, const ScPrintSelectionStatus& rStatus )
1744 {
1745  return bRenderToGraphic && rStatus.GetMode() == SC_PRINTSEL_RANGE;
1746 }
1747 
1748 uno::Sequence<beans::PropertyValue> SAL_CALL ScModelObj::getRenderer( sal_Int32 nSelRenderer,
1749  const uno::Any& aSelection, const uno::Sequence<beans::PropertyValue>& rOptions )
1750 {
1751  SolarMutexGuard aGuard;
1752  if (!pDocShell)
1753  {
1754  throw lang::DisposedException( OUString(),
1755  static_cast< sheet::XSpreadsheetDocument* >(this) );
1756  }
1757 
1759  ScPrintSelectionStatus aStatus;
1760  OUString aPagesStr;
1761  // #i115266# if FillRenderMarkData fails, keep nTotalPages at 0, but still handle getRenderer(0) below
1762  tools::Long nTotalPages = 0;
1763  bool bRenderToGraphic = false;
1764  bool bSinglePageSheets = false;
1765  if ( FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr, bRenderToGraphic ) )
1766  {
1767  if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) )
1768  {
1769  pPrintFuncCache.reset(new ScPrintFuncCache( pDocShell, aMark, aStatus ));
1770  }
1771  nTotalPages = pPrintFuncCache->GetPageCount();
1772  }
1773 
1774  for ( const auto& rValue : rOptions)
1775  {
1776  if ( rValue.Name == "SinglePageSheets" )
1777  {
1778  rValue.Value >>= bSinglePageSheets;
1779  break;
1780  }
1781  }
1782 
1783  if (bSinglePageSheets)
1784  nTotalPages = pDocShell->GetDocument().GetTableCount();
1785 
1786  sal_Int32 nRenderer = lcl_GetRendererNum( nSelRenderer, aPagesStr, nTotalPages );
1787 
1788  if ( nRenderer < 0 )
1789  {
1790  if ( nSelRenderer != 0 )
1791  throw lang::IllegalArgumentException();
1792 
1793  // getRenderer(0) is used to query the settings, so it must always return something
1794 
1795  awt::Size aPageSize;
1796  if (lcl_renderSelectionToGraphic( bRenderToGraphic, aStatus))
1797  {
1798  assert( aMark.IsMarked());
1799  ScRange aRange;
1800  aMark.GetMarkArea( aRange );
1802  aRange.aStart.Col(), aRange.aStart.Row(),
1803  aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
1804  aPageSize.Width = aMMRect.GetWidth();
1805  aPageSize.Height = aMMRect.GetHeight();
1806  }
1807  else
1808  {
1809  SCTAB const nCurTab = 0;
1810  ScPrintFunc aDefaultFunc( pDocShell, pDocShell->GetPrinter(), nCurTab );
1811  Size aTwips = aDefaultFunc.GetPageSize();
1812  aPageSize.Width = TwipsToHMM( aTwips.Width());
1813  aPageSize.Height = TwipsToHMM( aTwips.Height());
1814  }
1815 
1816  uno::Sequence<beans::PropertyValue> aSequence( comphelper::InitPropertySequence({
1817  { SC_UNONAME_PAGESIZE, uno::Any(aPageSize) }
1818  }));
1819 
1820  if( ! pPrinterOptions )
1821  pPrinterOptions.reset(new ScPrintUIOptions);
1822  else
1823  pPrinterOptions->SetDefaults();
1824  pPrinterOptions->appendPrintUIOptions( aSequence );
1825  return aSequence;
1826 
1827  }
1828 
1829  // printer is used as device (just for page layout), draw view is not needed
1830 
1831  SCTAB nTab;
1832  if (bSinglePageSheets)
1833  nTab = nSelRenderer;
1834  else if ( !maValidPages.empty() )
1835  nTab = pPrintFuncCache->GetTabForPage( maValidPages.at( nRenderer )-1 );
1836  else
1837  nTab = pPrintFuncCache->GetTabForPage( nRenderer );
1838 
1839 
1840  ScRange aRange;
1841  const ScRange* pSelRange = nullptr;
1842  if ( bSinglePageSheets )
1843  {
1844  awt::Size aPageSize;
1845  SCCOL nStartCol;
1846  SCROW nStartRow;
1847  const ScDocument* pDocument = &pDocShell->GetDocument();
1848  pDocument->GetDataStart( nTab, nStartCol, nStartRow );
1849  SCCOL nEndCol;
1850  SCROW nEndRow;
1851  pDocument->GetPrintArea( nTab, nEndCol, nEndRow );
1852 
1853  aRange.aStart = ScAddress(nStartCol, nStartRow, nTab);
1854  aRange.aEnd = ScAddress(nEndCol, nEndRow, nTab);
1855 
1856  table::CellRangeAddress aRangeAddress( nTab,
1857  aRange.aStart.Col(), aRange.aStart.Row(),
1858  aRange.aEnd.Col(), aRange.aEnd.Row() );
1860  aRange.aStart.Col(), aRange.aStart.Row(),
1861  aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
1862 
1863  aPageSize.Width = aMMRect.GetWidth();
1864  aPageSize.Height = aMMRect.GetHeight();
1865 
1866  awt::Size aCalcPageSize ( aMMRect.GetSize().Width(), aMMRect.GetSize().Height() );
1867  awt::Point aCalcPagePos( aMMRect.getX(), aMMRect.getY() );
1868 
1869  uno::Sequence<beans::PropertyValue> aSequence(5);
1870  beans::PropertyValue* pArray = aSequence.getArray();
1871  pArray[0].Name = SC_UNONAME_PAGESIZE;
1872  pArray[0].Value <<= aPageSize;
1873  // #i111158# all positions are relative to the whole page, including non-printable area
1874  pArray[1].Name = SC_UNONAME_INC_NP_AREA;
1875  pArray[1].Value <<= true;
1876  pArray[2].Name = SC_UNONAME_SOURCERANGE;
1877  pArray[2].Value <<= aRangeAddress;
1878  pArray[3].Name = SC_UNONAME_CALCPAGESIZE;
1879  pArray[3].Value <<= aCalcPageSize;
1880  pArray[4].Name = SC_UNONAME_CALCPAGEPOS;
1881  pArray[4].Value <<= aCalcPagePos;
1882 
1883  if( ! pPrinterOptions )
1884  pPrinterOptions.reset(new ScPrintUIOptions);
1885  else
1886  pPrinterOptions->SetDefaults();
1887  pPrinterOptions->appendPrintUIOptions( aSequence );
1888  return aSequence;
1889  }
1890  else if ( aMark.IsMarked() )
1891  {
1892  aMark.GetMarkArea( aRange );
1893  pSelRange = &aRange;
1894  }
1895 
1896  awt::Size aPageSize;
1897  bool bWasCellRange = false;
1898  ScRange aCellRange;
1899  if (lcl_renderSelectionToGraphic( bRenderToGraphic, aStatus))
1900  {
1901  bWasCellRange = true;
1902  aCellRange = aRange;
1904  aRange.aStart.Col(), aRange.aStart.Row(),
1905  aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
1906  aPageSize.Width = aMMRect.GetWidth();
1907  aPageSize.Height = aMMRect.GetHeight();
1908  }
1909  else
1910  {
1911  std::unique_ptr<ScPrintFunc, o3tl::default_delete<ScPrintFunc>> pPrintFunc;
1912  if (m_pPrintState && m_pPrintState->nPrintTab == nTab)
1913  pPrintFunc.reset(new ScPrintFunc(pDocShell, pDocShell->GetPrinter(), *m_pPrintState, &aStatus.GetOptions()));
1914  else
1915  pPrintFunc.reset(new ScPrintFunc(pDocShell, pDocShell->GetPrinter(), nTab,
1916  pPrintFuncCache->GetFirstAttr(nTab), nTotalPages, pSelRange, &aStatus.GetOptions()));
1917  pPrintFunc->SetRenderFlag( true );
1918 
1919  sal_Int32 nContent = 0;
1920  sal_Int32 nEOContent = 0;
1921  for ( const auto& rValue : rOptions)
1922  {
1923  if ( rValue.Name == "PrintRange" )
1924  {
1925  rValue.Value >>= nContent;
1926  }
1927  else if ( rValue.Name == "EvenOdd" )
1928  {
1929  rValue.Value >>= nEOContent;
1930  }
1931  }
1932 
1933  MultiSelection aPage;
1934  aPage.SetTotalRange( Range(0,RANGE_MAX) );
1935 
1936  bool bOddOrEven = (nContent == 0 && nEOContent == 1) || (nContent == 1 && nEOContent == 2); // even pages or odd pages
1937  // tdf#127682 when odd/even allow nRenderer of 0 even when maValidPages is empty
1938  // to allow PrinterController::abortJob to spool an empty page as part of
1939  // its abort procedure
1940  if (bOddOrEven && !maValidPages.empty())
1941  aPage.Select( maValidPages.at(nRenderer) );
1942  else
1943  aPage.Select( nRenderer+1 );
1944 
1945  tools::Long nDisplayStart = pPrintFuncCache->GetDisplayStart( nTab );
1946  tools::Long nTabStart = pPrintFuncCache->GetTabStart( nTab );
1947 
1948  (void)pPrintFunc->DoPrint( aPage, nTabStart, nDisplayStart, false, nullptr );
1949 
1950  bWasCellRange = pPrintFunc->GetLastSourceRange( aCellRange );
1951  Size aTwips = pPrintFunc->GetPageSize();
1952 
1953  if (!m_pPrintState)
1954  {
1955  m_pPrintState.reset(new ScPrintState());
1956  pPrintFunc->GetPrintState(*m_pPrintState, true);
1957  }
1958 
1959  aPageSize.Width = TwipsToHMM( aTwips.Width());
1960  aPageSize.Height = TwipsToHMM( aTwips.Height());
1961  }
1962 
1963  tools::Long nPropCount = bWasCellRange ? 5 : 4;
1964  uno::Sequence<beans::PropertyValue> aSequence(nPropCount);
1965  beans::PropertyValue* pArray = aSequence.getArray();
1966  pArray[0].Name = SC_UNONAME_PAGESIZE;
1967  pArray[0].Value <<= aPageSize;
1968  // #i111158# all positions are relative to the whole page, including non-printable area
1969  pArray[1].Name = SC_UNONAME_INC_NP_AREA;
1970  pArray[1].Value <<= true;
1971  if ( bWasCellRange )
1972  {
1973  table::CellRangeAddress aRangeAddress( nTab,
1974  aCellRange.aStart.Col(), aCellRange.aStart.Row(),
1975  aCellRange.aEnd.Col(), aCellRange.aEnd.Row() );
1977  aCellRange.aStart.Col(), aCellRange.aStart.Row(),
1978  aCellRange.aEnd.Col(), aCellRange.aEnd.Row(), aCellRange.aStart.Tab()));
1979 
1980  awt::Size aCalcPageSize ( aMMRect.GetSize().Width(), aMMRect.GetSize().Height() );
1981  awt::Point aCalcPagePos( aMMRect.getX(), aMMRect.getY() );
1982 
1983  pArray[2].Name = SC_UNONAME_SOURCERANGE;
1984  pArray[2].Value <<= aRangeAddress;
1985  pArray[3].Name = SC_UNONAME_CALCPAGESIZE;
1986  pArray[3].Value <<= aCalcPageSize;
1987  pArray[4].Name = SC_UNONAME_CALCPAGEPOS;
1988  pArray[4].Value <<= aCalcPagePos;
1989  }
1990 
1991  if( ! pPrinterOptions )
1992  pPrinterOptions.reset(new ScPrintUIOptions);
1993  else
1994  pPrinterOptions->SetDefaults();
1995  pPrinterOptions->appendPrintUIOptions( aSequence );
1996  return aSequence;
1997 }
1998 
1999 void SAL_CALL ScModelObj::render( sal_Int32 nSelRenderer, const uno::Any& aSelection,
2000  const uno::Sequence<beans::PropertyValue>& rOptions )
2001 {
2002  SolarMutexGuard aGuard;
2003  if (!pDocShell)
2004  {
2005  throw lang::DisposedException( OUString(),
2006  static_cast< sheet::XSpreadsheetDocument* >(this) );
2007  }
2008 
2010  ScPrintSelectionStatus aStatus;
2011  OUString aPagesStr;
2012  bool bRenderToGraphic = false;
2013  bool bSinglePageSheets = false;
2014  if ( !FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr, bRenderToGraphic ) )
2015  throw lang::IllegalArgumentException();
2016 
2017  if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) )
2018  {
2019  pPrintFuncCache.reset(new ScPrintFuncCache( pDocShell, aMark, aStatus ));
2020  }
2021  tools::Long nTotalPages = pPrintFuncCache->GetPageCount();
2022 
2023  for ( const auto& rValue : rOptions)
2024  {
2025  if ( rValue.Name == "SinglePageSheets" )
2026  {
2027  rValue.Value >>= bSinglePageSheets;
2028  break;
2029  }
2030  }
2031 
2032  if (bSinglePageSheets)
2033  nTotalPages = pDocShell->GetDocument().GetTableCount();
2034 
2035  sal_Int32 nRenderer = lcl_GetRendererNum( nSelRenderer, aPagesStr, nTotalPages );
2036  if ( nRenderer < 0 )
2037  throw lang::IllegalArgumentException();
2038 
2039  OutputDevice* pDev = lcl_GetRenderDevice( rOptions );
2040  if ( !pDev )
2041  throw lang::IllegalArgumentException();
2042 
2043  ScDocument& rDoc = pDocShell->GetDocument();
2044 
2045  ScRange aRange;
2046  const ScRange* pSelRange = nullptr;
2047  if ( bSinglePageSheets )
2048  {
2049  awt::Size aPageSize;
2050  SCCOL nStartCol;
2051  SCROW nStartRow;
2052  rDoc.GetDataStart( nSelRenderer, nStartCol, nStartRow );
2053  SCCOL nEndCol;
2054  SCROW nEndRow;
2055  rDoc.GetPrintArea( nSelRenderer, nEndCol, nEndRow );
2056 
2057  aRange.aStart = ScAddress(nStartCol, nStartRow, nSelRenderer);
2058  aRange.aEnd = ScAddress(nEndCol, nEndRow, nSelRenderer);
2059 
2061  aRange.aStart.Col(), aRange.aStart.Row(),
2062  aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
2063 
2064  aPageSize.Width = aMMRect.GetWidth();
2065  aPageSize.Height = aMMRect.GetHeight();
2066 
2067  //Set visible tab
2068  SCTAB nVisTab = rDoc.GetVisibleTab();
2069  if (nVisTab != nSelRenderer)
2070  {
2071  nVisTab = nSelRenderer;
2072  rDoc.SetVisibleTab(nVisTab);
2073  }
2074 
2075  pDocShell->DoDraw(pDev, Point(0,0), Size(aPageSize.Width, aPageSize.Height), JobSetup());
2076 
2077  return;
2078  }
2079  else if ( aMark.IsMarked() )
2080  {
2081  aMark.GetMarkArea( aRange );
2082  pSelRange = &aRange;
2083  }
2084 
2085  if (lcl_renderSelectionToGraphic( bRenderToGraphic, aStatus))
2086  {
2087  // Similar to as in and when calling ScTransferObj::PaintToDev()
2088 
2089  tools::Rectangle aBound( Point(), pDev->GetOutputSize());
2090 
2091  ScViewData aViewData(rDoc);
2092 
2093  aViewData.SetTabNo( aRange.aStart.Tab() );
2094  aViewData.SetScreen( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row() );
2095 
2096  const double nPrintFactor = 1.0; /* XXX: currently (2017-08-28) is not evaluated */
2097  // The bMetaFile argument maybe could be
2098  // pDev->GetConnectMetaFile() != nullptr
2099  // but for some yet unknown reason does not draw cell content if true.
2100  ScPrintFunc::DrawToDev( rDoc, pDev, nPrintFactor, aBound, &aViewData, false /*bMetaFile*/ );
2101 
2102  return;
2103  }
2104 
2105  struct DrawViewKeeper
2106  {
2107  std::unique_ptr<FmFormView> mpDrawView;
2108  DrawViewKeeper() {}
2109  ~DrawViewKeeper()
2110  {
2111  if (mpDrawView)
2112  {
2113  mpDrawView->HideSdrPage();
2114  mpDrawView.reset();
2115  }
2116  }
2117  } aDrawViewKeeper;
2118 
2119  SCTAB nTab;
2120  if ( !maValidPages.empty() )
2121  nTab = pPrintFuncCache->GetTabForPage( maValidPages.at( nRenderer )-1 );
2122  else
2123  nTab = pPrintFuncCache->GetTabForPage( nRenderer );
2124 
2125  ScDrawLayer* pModel = rDoc.GetDrawLayer();
2126 
2127  if( pModel )
2128  {
2129  aDrawViewKeeper.mpDrawView.reset( new FmFormView(
2130  *pModel,
2131  pDev) );
2132  aDrawViewKeeper.mpDrawView->ShowSdrPage(aDrawViewKeeper.mpDrawView->GetModel()->GetPage(nTab));
2133  aDrawViewKeeper.mpDrawView->SetPrintPreview();
2134  }
2135 
2136  // to increase performance, ScPrintState might be used here for subsequent
2137  // pages of the same sheet
2138 
2139 
2140  std::unique_ptr<ScPrintFunc, o3tl::default_delete<ScPrintFunc>> pPrintFunc;
2141  if (m_pPrintState && m_pPrintState->nPrintTab == nTab
2142  && ! pSelRange) // tdf#120161 use selection to set required printed area
2143  pPrintFunc.reset(new ScPrintFunc(pDev, pDocShell, *m_pPrintState, &aStatus.GetOptions()));
2144  else
2145  pPrintFunc.reset(new ScPrintFunc(pDev, pDocShell, nTab, pPrintFuncCache->GetFirstAttr(nTab), nTotalPages, pSelRange, &aStatus.GetOptions()));
2146 
2147  pPrintFunc->SetDrawView( aDrawViewKeeper.mpDrawView.get() );
2148  pPrintFunc->SetRenderFlag( true );
2149  if( aStatus.GetMode() == SC_PRINTSEL_RANGE_EXCLUSIVELY_OLE_AND_DRAW_OBJECTS )
2150  pPrintFunc->SetExclusivelyDrawOleAndDrawObjects();
2151 
2152  sal_Int32 nContent = 0;
2153  sal_Int32 nEOContent = 0;
2154  for ( const auto& rValue : rOptions)
2155  {
2156  if ( rValue.Name == "PrintRange" )
2157  {
2158  rValue.Value >>= nContent;
2159  }
2160  else if ( rValue.Name == "EvenOdd" )
2161  {
2162  rValue.Value >>= nEOContent;
2163  }
2164  }
2165 
2166  MultiSelection aPage;
2167  aPage.SetTotalRange( Range(0,RANGE_MAX) );
2168 
2169  bool bOddOrEven = (nContent == 0 && nEOContent == 1) || (nContent == 0 && nEOContent == 2); // even pages or odd pages
2170  // tdf#127682 when odd/even allow nRenderer of 0 even when maValidPages is empty
2171  // to allow PrinterController::abortJob to spool an empty page as part of
2172  // its abort procedure
2173  if (bOddOrEven && !maValidPages.empty())
2174  aPage.Select( maValidPages.at( nRenderer ) );
2175  else
2176  aPage.Select( nRenderer+1 );
2177 
2178  tools::Long nDisplayStart = pPrintFuncCache->GetDisplayStart( nTab );
2179  tools::Long nTabStart = pPrintFuncCache->GetTabStart( nTab );
2180 
2181  vcl::PDFExtOutDevData* pPDFData = dynamic_cast< vcl::PDFExtOutDevData* >(pDev->GetExtOutDevData() );
2182  if ( nRenderer == nTabStart )
2183  {
2184  // first page of a sheet: add outline item for the sheet name
2185 
2186  if ( pPDFData && pPDFData->GetIsExportBookmarks() )
2187  {
2188  // the sheet starts at the top of the page
2189  tools::Rectangle aArea( pDev->PixelToLogic( tools::Rectangle( 0,0,0,0 ) ) );
2190  sal_Int32 nDestID = pPDFData->CreateDest( aArea );
2191  OUString aTabName;
2192  rDoc.GetName( nTab, aTabName );
2193  // top-level
2194  pPDFData->CreateOutlineItem( -1/*nParent*/, aTabName, nDestID );
2195  }
2196  // #i56629# add the named destination stuff
2197  if( pPDFData && pPDFData->GetIsExportNamedDestinations() )
2198  {
2199  tools::Rectangle aArea( pDev->PixelToLogic( tools::Rectangle( 0,0,0,0 ) ) );
2200  OUString aTabName;
2201  rDoc.GetName( nTab, aTabName );
2202  //need the PDF page number here
2203  pPDFData->CreateNamedDest( aTabName, aArea );
2204  }
2205  }
2206 
2207  (void)pPrintFunc->DoPrint( aPage, nTabStart, nDisplayStart, true, nullptr );
2208 
2209  if (!m_pPrintState)
2210  {
2211  m_pPrintState.reset(new ScPrintState());
2212  pPrintFunc->GetPrintState(*m_pPrintState, true);
2213  }
2214 
2215  // resolve the hyperlinks for PDF export
2216 
2217  if ( !pPDFData || pPDFData->GetBookmarks().empty() )
2218  return;
2219 
2220  // iterate over the hyperlinks that were output for this page
2221 
2222  std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFData->GetBookmarks();
2223  for ( const auto& rBookmark : rBookmarks )
2224  {
2225  OUString aBookmark = rBookmark.aBookmark;
2226  if ( aBookmark.toChar() == '#' )
2227  {
2228  // try to resolve internal link
2229 
2230  OUString aTarget( aBookmark.copy( 1 ) );
2231 
2232  ScRange aTargetRange;
2233  tools::Rectangle aTargetRect; // 1/100th mm
2234  bool bIsSheet = false;
2235  bool bValid = lcl_ParseTarget( aTarget, aTargetRange, aTargetRect, bIsSheet, rDoc, nTab );
2236 
2237  if ( bValid )
2238  {
2239  sal_Int32 nPage = -1;
2240  tools::Rectangle aArea;
2241  if ( bIsSheet )
2242  {
2243  // Get first page for sheet (if nothing from that sheet is printed,
2244  // this page can show a different sheet)
2245  nPage = pPrintFuncCache->GetTabStart( aTargetRange.aStart.Tab() );
2246  aArea = pDev->PixelToLogic( tools::Rectangle( 0,0,0,0 ) );
2247  }
2248  else
2249  {
2250  pPrintFuncCache->InitLocations( aMark, pDev ); // does nothing if already initialized
2251 
2252  ScPrintPageLocation aLocation;
2253  if ( pPrintFuncCache->FindLocation( aTargetRange.aStart, aLocation ) )
2254  {
2255  nPage = aLocation.nPage;
2256 
2257  // get the rectangle of the page's cell range in 1/100th mm
2258  ScRange aLocRange = aLocation.aCellRange;
2259  tools::Rectangle aLocationMM = rDoc.GetMMRect(
2260  aLocRange.aStart.Col(), aLocRange.aStart.Row(),
2261  aLocRange.aEnd.Col(), aLocRange.aEnd.Row(),
2262  aLocRange.aStart.Tab() );
2263  tools::Rectangle aLocationPixel = aLocation.aRectangle;
2264 
2265  // Scale and move the target rectangle from aLocationMM to aLocationPixel,
2266  // to get the target rectangle in pixels.
2267  assert(aLocationPixel.GetWidth() != 0 && aLocationPixel.GetHeight() != 0);
2268 
2269  Fraction aScaleX( aLocationPixel.GetWidth(), aLocationMM.GetWidth() );
2270  Fraction aScaleY( aLocationPixel.GetHeight(), aLocationMM.GetHeight() );
2271 
2272  tools::Long nX1 = aLocationPixel.Left() + static_cast<tools::Long>( Fraction( aTargetRect.Left() - aLocationMM.Left(), 1 ) * aScaleX );
2273  tools::Long nX2 = aLocationPixel.Left() + static_cast<tools::Long>( Fraction( aTargetRect.Right() - aLocationMM.Left(), 1 ) * aScaleX );
2274  tools::Long nY1 = aLocationPixel.Top() + static_cast<tools::Long>( Fraction( aTargetRect.Top() - aLocationMM.Top(), 1 ) * aScaleY );
2275  tools::Long nY2 = aLocationPixel.Top() + static_cast<tools::Long>( Fraction( aTargetRect.Bottom() - aLocationMM.Top(), 1 ) * aScaleY );
2276 
2277  if ( nX1 > aLocationPixel.Right() ) nX1 = aLocationPixel.Right();
2278  if ( nX2 > aLocationPixel.Right() ) nX2 = aLocationPixel.Right();
2279  if ( nY1 > aLocationPixel.Bottom() ) nY1 = aLocationPixel.Bottom();
2280  if ( nY2 > aLocationPixel.Bottom() ) nY2 = aLocationPixel.Bottom();
2281 
2282  // The link target area is interpreted using the device's MapMode at
2283  // the time of the CreateDest call, so PixelToLogic can be used here,
2284  // regardless of the MapMode that is actually selected.
2285  aArea = pDev->PixelToLogic( tools::Rectangle( nX1, nY1, nX2, nY2 ) );
2286  }
2287  }
2288 
2289  if ( nPage >= 0 )
2290  pPDFData->SetLinkDest( rBookmark.nLinkId, pPDFData->CreateDest( aArea, nPage ) );
2291  }
2292  }
2293  else
2294  {
2295  // external link, use as-is
2296  pPDFData->SetLinkURL( rBookmark.nLinkId, aBookmark );
2297  }
2298  }
2299  rBookmarks.clear();
2300 }
2301 
2302 // XLinkTargetSupplier
2303 
2304 uno::Reference<container::XNameAccess> SAL_CALL ScModelObj::getLinks()
2305 {
2306  SolarMutexGuard aGuard;
2307  if (pDocShell)
2308  return new ScLinkTargetTypesObj(pDocShell);
2309  return nullptr;
2310 }
2311 
2312 // XActionLockable
2313 
2315 {
2316  SolarMutexGuard aGuard;
2317  bool bLocked = false;
2318  if (pDocShell)
2319  bLocked = ( pDocShell->GetLockCount() != 0 );
2320  return bLocked;
2321 }
2322 
2324 {
2325  SolarMutexGuard aGuard;
2326  if (pDocShell)
2328 }
2329 
2331 {
2332  SolarMutexGuard aGuard;
2333  if (pDocShell)
2335 }
2336 
2337 void SAL_CALL ScModelObj::setActionLocks( sal_Int16 nLock )
2338 {
2339  SolarMutexGuard aGuard;
2340  if (pDocShell)
2341  pDocShell->SetLockCount(nLock);
2342 }
2343 
2344 sal_Int16 SAL_CALL ScModelObj::resetActionLocks()
2345 {
2346  SolarMutexGuard aGuard;
2347  sal_uInt16 nRet = 0;
2348  if (pDocShell)
2349  {
2350  nRet = pDocShell->GetLockCount();
2351  pDocShell->SetLockCount(0);
2352  }
2353  return nRet;
2354 }
2355 
2357 {
2358  SolarMutexGuard aGuard;
2360  if (pDocShell)
2361  pDocShell->LockPaint();
2362 }
2363 
2365 {
2366  SolarMutexGuard aGuard;
2367  if (hasControllersLocked())
2368  {
2370  if (pDocShell)
2372  }
2373 }
2374 
2375 // XCalculate
2376 
2377 void SAL_CALL ScModelObj::calculate()
2378 {
2379  SolarMutexGuard aGuard;
2380  if (pDocShell)
2381  {
2382  comphelper::ProfileZone aZone("calculate");
2383  pDocShell->DoRecalc(true);
2384  }
2385  else
2386  {
2387  OSL_FAIL("no DocShell");
2388  }
2389 }
2390 
2392 {
2393  SolarMutexGuard aGuard;
2394  if (pDocShell)
2395  {
2396  comphelper::ProfileZone aZone("calculateAll");
2398  }
2399  else
2400  {
2401  OSL_FAIL("no DocShell");
2402  }
2403 }
2404 
2406 {
2407  SolarMutexGuard aGuard;
2408  if (pDocShell)
2409  return pDocShell->GetDocument().GetAutoCalc();
2410 
2411  OSL_FAIL("no DocShell");
2412  return false;
2413 }
2414 
2416 {
2417  bool bEnabled(bEnabledIn);
2418  SolarMutexGuard aGuard;
2419  if (pDocShell)
2420  {
2421  ScDocument& rDoc = pDocShell->GetDocument();
2422  if ( rDoc.GetAutoCalc() != bEnabled )
2423  {
2424  rDoc.SetAutoCalc( bEnabled );
2426  }
2427  }
2428  else
2429  {
2430  OSL_FAIL("no DocShell");
2431  }
2432 }
2433 
2434 // XProtectable
2435 
2436 void SAL_CALL ScModelObj::protect( const OUString& aPassword )
2437 {
2438  SolarMutexGuard aGuard;
2439  // #i108245# if already protected, don't change anything
2441  {
2442  pDocShell->GetDocFunc().Protect( TABLEID_DOC, aPassword );
2443  }
2444 }
2445 
2446 void SAL_CALL ScModelObj::unprotect( const OUString& aPassword )
2447 {
2448  SolarMutexGuard aGuard;
2449  if (pDocShell)
2450  {
2451  bool bDone = pDocShell->GetDocFunc().Unprotect( TABLEID_DOC, aPassword, true );
2452  if (!bDone)
2453  throw lang::IllegalArgumentException();
2454  }
2455 }
2456 
2458 {
2459  SolarMutexGuard aGuard;
2460  if (pDocShell)
2461  return pDocShell->GetDocument().IsDocProtected();
2462 
2463  OSL_FAIL("no DocShell");
2464  return false;
2465 }
2466 
2467 // XDrawPagesSupplier
2468 
2469 uno::Reference<drawing::XDrawPages> SAL_CALL ScModelObj::getDrawPages()
2470 {
2471  SolarMutexGuard aGuard;
2472  if (pDocShell)
2473  return new ScDrawPagesObj(pDocShell);
2474 
2475  OSL_FAIL("no DocShell");
2476  return nullptr;
2477 }
2478 
2479 // XGoalSeek
2480 
2481 sheet::GoalResult SAL_CALL ScModelObj::seekGoal(
2482  const table::CellAddress& aFormulaPosition,
2483  const table::CellAddress& aVariablePosition,
2484  const OUString& aGoalValue )
2485 {
2486  SolarMutexGuard aGuard;
2487  sheet::GoalResult aResult;
2488  aResult.Divergence = DBL_MAX; // not found
2489  if (pDocShell)
2490  {
2492  ScDocument& rDoc = pDocShell->GetDocument();
2493  double fValue = 0.0;
2494  bool bFound = rDoc.Solver(
2495  static_cast<SCCOL>(aFormulaPosition.Column), static_cast<SCROW>(aFormulaPosition.Row), aFormulaPosition.Sheet,
2496  static_cast<SCCOL>(aVariablePosition.Column), static_cast<SCROW>(aVariablePosition.Row), aVariablePosition.Sheet,
2497  aGoalValue, fValue );
2498  aResult.Result = fValue;
2499  if (bFound)
2500  aResult.Divergence = 0.0;
2501  }
2502  return aResult;
2503 }
2504 
2505 // XConsolidatable
2506 
2507 uno::Reference<sheet::XConsolidationDescriptor> SAL_CALL ScModelObj::createConsolidationDescriptor(
2508  sal_Bool bEmpty )
2509 {
2510  SolarMutexGuard aGuard;
2512  if ( pDocShell && !bEmpty )
2513  {
2514  ScDocument& rDoc = pDocShell->GetDocument();
2515  const ScConsolidateParam* pParam = rDoc.GetConsolidateDlgData();
2516  if (pParam)
2517  pNew->SetParam( *pParam );
2518  }
2519  return pNew;
2520 }
2521 
2523  const uno::Reference<sheet::XConsolidationDescriptor>& xDescriptor )
2524 {
2525  SolarMutexGuard aGuard;
2526  // in theory, this could also be a different object, so use only
2527  // public XConsolidationDescriptor interface to copy the data into
2528  // ScConsolidationDescriptor object
2530 
2532  xImpl->setFunction( xDescriptor->getFunction() );
2533  xImpl->setSources( xDescriptor->getSources() );
2534  xImpl->setStartOutputPosition( xDescriptor->getStartOutputPosition() );
2535  xImpl->setUseColumnHeaders( xDescriptor->getUseColumnHeaders() );
2536  xImpl->setUseRowHeaders( xDescriptor->getUseRowHeaders() );
2537  xImpl->setInsertLinks( xDescriptor->getInsertLinks() );
2538 
2539  if (pDocShell)
2540  {
2541  const ScConsolidateParam& rParam = xImpl->GetParam();
2542  pDocShell->DoConsolidate( rParam );
2543  pDocShell->GetDocument().SetConsolidateDlgData( std::unique_ptr<ScConsolidateParam>(new ScConsolidateParam(rParam)) );
2544  }
2545 }
2546 
2547 // XDocumentAuditing
2548 
2550 {
2551  SolarMutexGuard aGuard;
2552  if (pDocShell)
2554 }
2555 
2556 // XViewDataSupplier
2557 uno::Reference< container::XIndexAccess > SAL_CALL ScModelObj::getViewData( )
2558 {
2559  uno::Reference < container::XIndexAccess > xRet( SfxBaseModel::getViewData() );
2560 
2561  if( !xRet.is() )
2562  {
2563  SolarMutexGuard aGuard;
2564  if (pDocShell && pDocShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED)
2565  {
2566  uno::Reference < container::XIndexContainer > xCont = document::IndexedPropertyValues::create( ::comphelper::getProcessComponentContext() );
2567  xRet.set( xCont, uno::UNO_QUERY_THROW );
2568 
2569  uno::Sequence< beans::PropertyValue > aSeq;
2570  aSeq.realloc(3);
2571  OUString sName;
2573  OUString sOUName(sName);
2574  aSeq[0].Name = SC_ACTIVETABLE;
2575  aSeq[0].Value <<= sOUName;
2576  SCCOL nPosLeft = pDocShell->GetDocument().GetPosLeft();
2577  aSeq[1].Name = SC_POSITIONLEFT;
2578  aSeq[1].Value <<= nPosLeft;
2579  SCROW nPosTop = pDocShell->GetDocument().GetPosTop();
2580  aSeq[2].Name = SC_POSITIONTOP;
2581  aSeq[2].Value <<= nPosTop;
2582  xCont->insertByIndex( 0, uno::makeAny( aSeq ) );
2583  }
2584  }
2585 
2586  return xRet;
2587 }
2588 
2589 // XPropertySet (Doc-Options)
2591 
2592 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScModelObj::getPropertySetInfo()
2593 {
2594  SolarMutexGuard aGuard;
2595  static uno::Reference<beans::XPropertySetInfo> aRef(
2597  return aRef;
2598 }
2599 
2601  const OUString& aPropertyName, const uno::Any& aValue )
2602 {
2603  SolarMutexGuard aGuard;
2604 
2605  if (!pDocShell)
2606  return;
2607 
2608  ScDocument& rDoc = pDocShell->GetDocument();
2609  const ScDocOptions& rOldOpt = rDoc.GetDocOptions();
2610  ScDocOptions aNewOpt = rOldOpt;
2611  // Don't recalculate while loading XML, when the formula text is stored
2612  // Recalculation after loading is handled separately.
2613  bool bHardRecalc = !rDoc.IsImportingXML();
2614 
2615  bool bOpt = ScDocOptionsHelper::setPropertyValue( aNewOpt, aPropSet.getPropertyMap(), aPropertyName, aValue );
2616  if (bOpt)
2617  {
2618  // done...
2619  if ( aPropertyName == SC_UNO_IGNORECASE ||
2620  aPropertyName == SC_UNONAME_REGEXP ||
2621  aPropertyName == SC_UNONAME_WILDCARDS ||
2622  aPropertyName == SC_UNO_LOOKUPLABELS )
2623  bHardRecalc = false;
2624  }
2625  else if ( aPropertyName == SC_UNONAME_CLOCAL )
2626  {
2627  lang::Locale aLocale;
2628  if ( aValue >>= aLocale )
2629  {
2630  LanguageType eLatin, eCjk, eCtl;
2631  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2632  eLatin = ScUnoConversion::GetLanguage(aLocale);
2633  rDoc.SetLanguage( eLatin, eCjk, eCtl );
2634  }
2635  }
2636  else if ( aPropertyName == SC_UNO_CODENAME )
2637  {
2638  OUString sCodeName;
2639  if ( aValue >>= sCodeName )
2640  rDoc.SetCodeName( sCodeName );
2641  }
2642  else if ( aPropertyName == SC_UNO_CJK_CLOCAL )
2643  {
2644  lang::Locale aLocale;
2645  if ( aValue >>= aLocale )
2646  {
2647  LanguageType eLatin, eCjk, eCtl;
2648  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2649  eCjk = ScUnoConversion::GetLanguage(aLocale);
2650  rDoc.SetLanguage( eLatin, eCjk, eCtl );
2651  }
2652  }
2653  else if ( aPropertyName == SC_UNO_CTL_CLOCAL )
2654  {
2655  lang::Locale aLocale;
2656  if ( aValue >>= aLocale )
2657  {
2658  LanguageType eLatin, eCjk, eCtl;
2659  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2660  eCtl = ScUnoConversion::GetLanguage(aLocale);
2661  rDoc.SetLanguage( eLatin, eCjk, eCtl );
2662  }
2663  }
2664  else if ( aPropertyName == SC_UNO_APPLYFMDES )
2665  {
2666  // model is created if not there
2667  ScDrawLayer* pModel = pDocShell->MakeDrawLayer();
2669 
2670  SfxBindings* pBindings = pDocShell->GetViewBindings();
2671  if (pBindings)
2672  pBindings->Invalidate( SID_FM_OPEN_READONLY );
2673  }
2674  else if ( aPropertyName == SC_UNO_AUTOCONTFOC )
2675  {
2676  // model is created if not there
2677  ScDrawLayer* pModel = pDocShell->MakeDrawLayer();
2679 
2680  SfxBindings* pBindings = pDocShell->GetViewBindings();
2681  if (pBindings)
2682  pBindings->Invalidate( SID_FM_AUTOCONTROLFOCUS );
2683  }
2684  else if ( aPropertyName == SC_UNO_ISLOADED )
2685  {
2687  }
2688  else if ( aPropertyName == SC_UNO_ISUNDOENABLED )
2689  {
2690  bool bUndoEnabled = ScUnoHelpFunctions::GetBoolFromAny( aValue );
2691  rDoc.EnableUndo( bUndoEnabled );
2693  bUndoEnabled
2694  ? officecfg::Office::Common::Undo::Steps::get() : 0);
2695  }
2696  else if ( aPropertyName == SC_UNO_RECORDCHANGES )
2697  {
2698  bool bRecordChangesEnabled = ScUnoHelpFunctions::GetBoolFromAny( aValue );
2699 
2700  bool bChangeAllowed = true;
2701  if (!bRecordChangesEnabled)
2702  bChangeAllowed = !pDocShell->HasChangeRecordProtection();
2703 
2704  if (bChangeAllowed)
2705  pDocShell->SetChangeRecording(bRecordChangesEnabled);
2706  }
2707  else if ( aPropertyName == SC_UNO_ISADJUSTHEIGHTENABLED )
2708  {
2709  if( ScUnoHelpFunctions::GetBoolFromAny( aValue ) )
2710  rDoc.UnlockAdjustHeight();
2711  else
2712  rDoc.LockAdjustHeight();
2713  }
2714  else if ( aPropertyName == SC_UNO_ISEXECUTELINKENABLED )
2715  {
2717  }
2718  else if ( aPropertyName == SC_UNO_ISCHANGEREADONLYENABLED )
2719  {
2721  }
2722  else if ( aPropertyName == "BuildId" )
2723  {
2724  aValue >>= maBuildId;
2725  }
2726  else if ( aPropertyName == "SavedObject" ) // set from chart after saving
2727  {
2728  OUString aObjName;
2729  aValue >>= aObjName;
2730  if ( !aObjName.isEmpty() )
2731  rDoc.RestoreChartListener( aObjName );
2732  }
2733  else if ( aPropertyName == SC_UNO_INTEROPGRABBAG )
2734  {
2735  setGrabBagItem(aValue);
2736  }
2737 
2738  if ( aNewOpt != rOldOpt )
2739  {
2740  rDoc.SetDocOptions( aNewOpt );
2742  if ( bHardRecalc )
2745  }
2746 }
2747 
2748 uno::Any SAL_CALL ScModelObj::getPropertyValue( const OUString& aPropertyName )
2749 {
2750  SolarMutexGuard aGuard;
2751  uno::Any aRet;
2752 
2753  if (pDocShell)
2754  {
2755  ScDocument& rDoc = pDocShell->GetDocument();
2756  const ScDocOptions& rOpt = rDoc.GetDocOptions();
2757  aRet = ScDocOptionsHelper::getPropertyValue( rOpt, aPropSet.getPropertyMap(), aPropertyName );
2758  if ( aRet.hasValue() )
2759  {
2760  // done...
2761  }
2762  else if ( aPropertyName == SC_UNONAME_CLOCAL )
2763  {
2764  LanguageType eLatin, eCjk, eCtl;
2765  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2766 
2767  lang::Locale aLocale;
2768  ScUnoConversion::FillLocale( aLocale, eLatin );
2769  aRet <<= aLocale;
2770  }
2771  else if ( aPropertyName == SC_UNO_CODENAME )
2772  {
2773  aRet <<= rDoc.GetCodeName();
2774  }
2775 
2776  else if ( aPropertyName == SC_UNO_CJK_CLOCAL )
2777  {
2778  LanguageType eLatin, eCjk, eCtl;
2779  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2780 
2781  lang::Locale aLocale;
2782  ScUnoConversion::FillLocale( aLocale, eCjk );
2783  aRet <<= aLocale;
2784  }
2785  else if ( aPropertyName == SC_UNO_CTL_CLOCAL )
2786  {
2787  LanguageType eLatin, eCjk, eCtl;
2788  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2789 
2790  lang::Locale aLocale;
2791  ScUnoConversion::FillLocale( aLocale, eCtl );
2792  aRet <<= aLocale;
2793  }
2794  else if ( aPropertyName == SC_UNO_NAMEDRANGES )
2795  {
2796  aRet <<= uno::Reference<sheet::XNamedRanges>(new ScGlobalNamedRangesObj( pDocShell ));
2797  }
2798  else if ( aPropertyName == SC_UNO_DATABASERNG )
2799  {
2800  aRet <<= uno::Reference<sheet::XDatabaseRanges>(new ScDatabaseRangesObj( pDocShell ));
2801  }
2802  else if ( aPropertyName == SC_UNO_UNNAMEDDBRNG )
2803  {
2804  aRet <<= uno::Reference<sheet::XUnnamedDatabaseRanges>(new ScUnnamedDatabaseRangesObj(pDocShell));
2805  }
2806  else if ( aPropertyName == SC_UNO_COLLABELRNG )
2807  {
2808  aRet <<= uno::Reference<sheet::XLabelRanges>(new ScLabelRangesObj( pDocShell, true ));
2809  }
2810  else if ( aPropertyName == SC_UNO_ROWLABELRNG )
2811  {
2812  aRet <<= uno::Reference<sheet::XLabelRanges>(new ScLabelRangesObj( pDocShell, false ));
2813  }
2814  else if ( aPropertyName == SC_UNO_AREALINKS )
2815  {
2816  aRet <<= uno::Reference<sheet::XAreaLinks>(new ScAreaLinksObj( pDocShell ));
2817  }
2818  else if ( aPropertyName == SC_UNO_DDELINKS )
2819  {
2820  aRet <<= uno::Reference<container::XNameAccess>(new ScDDELinksObj( pDocShell ));
2821  }
2822  else if ( aPropertyName == SC_UNO_EXTERNALDOCLINKS )
2823  {
2824  aRet <<= uno::Reference<sheet::XExternalDocLinks>(new ScExternalDocLinksObj(pDocShell));
2825  }
2826  else if ( aPropertyName == SC_UNO_SHEETLINKS )
2827  {
2828  aRet <<= uno::Reference<container::XNameAccess>(new ScSheetLinksObj( pDocShell ));
2829  }
2830  else if ( aPropertyName == SC_UNO_APPLYFMDES )
2831  {
2832  // default for no model is TRUE
2833  ScDrawLayer* pModel = rDoc.GetDrawLayer();
2834  bool bOpenInDesign = pModel == nullptr || pModel->GetOpenInDesignMode();
2835  aRet <<= bOpenInDesign;
2836  }
2837  else if ( aPropertyName == SC_UNO_AUTOCONTFOC )
2838  {
2839  // default for no model is FALSE
2840  ScDrawLayer* pModel = rDoc.GetDrawLayer();
2841  bool bAutoControlFocus = pModel && pModel->GetAutoControlFocus();
2842  aRet <<= bAutoControlFocus;
2843  }
2844  else if ( aPropertyName == SC_UNO_FORBIDDEN )
2845  {
2846  aRet <<= uno::Reference<i18n::XForbiddenCharacters>(new ScForbiddenCharsObj( pDocShell ));
2847  }
2848  else if ( aPropertyName == SC_UNO_HASDRAWPAGES )
2849  {
2850  aRet <<= (pDocShell->GetDocument().GetDrawLayer() != nullptr);
2851  }
2852  else if ( aPropertyName == SC_UNO_BASICLIBRARIES )
2853  {
2854  aRet <<= pDocShell->GetBasicContainer();
2855  }
2856  else if ( aPropertyName == SC_UNO_DIALOGLIBRARIES )
2857  {
2858  aRet <<= pDocShell->GetDialogContainer();
2859  }
2860  else if ( aPropertyName == SC_UNO_VBAGLOBNAME )
2861  {
2862  /* #i111553# This property provides the name of the constant that
2863  will be used to store this model in the global Basic manager.
2864  That constant will be equivalent to 'ThisComponent' but for
2865  each application, so e.g. a 'ThisExcelDoc' and a 'ThisWordDoc'
2866  constant can co-exist, as required by VBA. */
2867  aRet <<= OUString( "ThisExcelDoc" );
2868  }
2869  else if ( aPropertyName == SC_UNO_RUNTIMEUID )
2870  {
2871  aRet <<= getRuntimeUID();
2872  }
2873  else if ( aPropertyName == SC_UNO_HASVALIDSIGNATURES )
2874  {
2875  aRet <<= hasValidSignatures();
2876  }
2877  else if ( aPropertyName == SC_UNO_ISLOADED )
2878  {
2879  aRet <<= !pDocShell->IsEmpty();
2880  }
2881  else if ( aPropertyName == SC_UNO_ISUNDOENABLED )
2882  {
2883  aRet <<= rDoc.IsUndoEnabled();
2884  }
2885  else if ( aPropertyName == SC_UNO_RECORDCHANGES )
2886  {
2887  aRet <<= pDocShell->IsChangeRecording();
2888  }
2889  else if ( aPropertyName == SC_UNO_ISRECORDCHANGESPROTECTED )
2890  {
2892  }
2893  else if ( aPropertyName == SC_UNO_ISADJUSTHEIGHTENABLED )
2894  {
2895  aRet <<= !( rDoc.IsAdjustHeightLocked() );
2896  }
2897  else if ( aPropertyName == SC_UNO_ISEXECUTELINKENABLED )
2898  {
2899  aRet <<= rDoc.IsExecuteLinkEnabled();
2900  }
2901  else if ( aPropertyName == SC_UNO_ISCHANGEREADONLYENABLED )
2902  {
2903  aRet <<= rDoc.IsChangeReadOnlyEnabled();
2904  }
2905  else if ( aPropertyName == SC_UNO_REFERENCEDEVICE )
2906  {
2907  VCLXDevice* pXDev = new VCLXDevice();
2908  pXDev->SetOutputDevice( rDoc.GetRefDevice() );
2909  aRet <<= uno::Reference< awt::XDevice >( pXDev );
2910  }
2911  else if ( aPropertyName == "BuildId" )
2912  {
2913  aRet <<= maBuildId;
2914  }
2915  else if ( aPropertyName == "InternalDocument" )
2916  {
2917  aRet <<= (pDocShell->GetCreateMode() == SfxObjectCreateMode::INTERNAL);
2918  }
2919  else if ( aPropertyName == SC_UNO_INTEROPGRABBAG )
2920  {
2921  getGrabBagItem(aRet);
2922  }
2923  }
2924 
2925  return aRet;
2926 }
2927 
2929 
2930 // XMultiServiceFactory
2931 
2932 css::uno::Reference<css::uno::XInterface> ScModelObj::create(
2933  OUString const & aServiceSpecifier,
2934  css::uno::Sequence<css::uno::Any> const * arguments)
2935 {
2937 
2938  uno::Reference<uno::XInterface> xRet;
2940  if ( nType != ServiceType::INVALID )
2941  {
2942  // drawing layer tables must be kept as long as the model is alive
2943  // return stored instance if already set
2944  switch ( nType )
2945  {
2946  case ServiceType::GRADTAB: xRet.set(xDrawGradTab); break;
2947  case ServiceType::HATCHTAB: xRet.set(xDrawHatchTab); break;
2948  case ServiceType::BITMAPTAB: xRet.set(xDrawBitmapTab); break;
2949  case ServiceType::TRGRADTAB: xRet.set(xDrawTrGradTab); break;
2950  case ServiceType::MARKERTAB: xRet.set(xDrawMarkerTab); break;
2951  case ServiceType::DASHTAB: xRet.set(xDrawDashTab); break;
2952  case ServiceType::CHDATAPROV: xRet.set(xChartDataProv); break;
2953  case ServiceType::VBAOBJECTPROVIDER: xRet.set(xObjProvider); break;
2954  default: break;
2955  }
2956 
2957  // #i64497# If a chart is in a temporary document during clipboard paste,
2958  // there should be no data provider, so that own data is used
2959  bool bCreate =
2960  ( nType != ServiceType::CHDATAPROV ||
2961  ( pDocShell->GetCreateMode() != SfxObjectCreateMode::INTERNAL ));
2962  // this should never happen, i.e. the temporary document should never be
2963  // loaded, because this unlinks the data
2964  assert(bCreate);
2965 
2966  if ( !xRet.is() && bCreate )
2967  {
2968  xRet.set(ScServiceProvider::MakeInstance( nType, pDocShell ));
2969 
2970  // store created instance
2971  switch ( nType )
2972  {
2973  case ServiceType::GRADTAB: xDrawGradTab.set(xRet); break;
2974  case ServiceType::HATCHTAB: xDrawHatchTab.set(xRet); break;
2975  case ServiceType::BITMAPTAB: xDrawBitmapTab.set(xRet); break;
2976  case ServiceType::TRGRADTAB: xDrawTrGradTab.set(xRet); break;
2977  case ServiceType::MARKERTAB: xDrawMarkerTab.set(xRet); break;
2978  case ServiceType::DASHTAB: xDrawDashTab.set(xRet); break;
2979  case ServiceType::CHDATAPROV: xChartDataProv.set(xRet); break;
2980  case ServiceType::VBAOBJECTPROVIDER: xObjProvider.set(xRet); break;
2981  default: break;
2982  }
2983  }
2984  }
2985  else
2986  {
2987  // we offload everything we don't know to SvxFmMSFactory,
2988  // it'll throw exception if this isn't okay ...
2989 
2990  try
2991  {
2992  xRet = arguments == nullptr
2993  ? SvxFmMSFactory::createInstance(aServiceSpecifier)
2995  aServiceSpecifier, *arguments);
2996  // extra block to force deletion of the temporary before ScShapeObj ctor (setDelegator)
2997  }
2998  catch ( lang::ServiceNotRegisteredException & )
2999  {
3000  }
3001 
3002  // if the drawing factory created a shape, a ScShapeObj has to be used
3003  // to support own properties like ImageMap:
3004 
3005  uno::Reference<drawing::XShape> xShape( xRet, uno::UNO_QUERY );
3006  if ( xShape.is() )
3007  {
3008  xRet.clear(); // for aggregation, xShape must be the object's only ref
3009  new ScShapeObj( xShape ); // aggregates object and modifies xShape
3010  xRet.set(xShape);
3011  }
3012  }
3013  return xRet;
3014 }
3015 
3016 uno::Reference<uno::XInterface> SAL_CALL ScModelObj::createInstance(
3017  const OUString& aServiceSpecifier )
3018 {
3019  SolarMutexGuard aGuard;
3020  return create(aServiceSpecifier, nullptr);
3021 }
3022 
3023 uno::Reference<uno::XInterface> SAL_CALL ScModelObj::createInstanceWithArguments(
3024  const OUString& ServiceSpecifier,
3025  const uno::Sequence<uno::Any>& aArgs )
3026 {
3028 
3029  SolarMutexGuard aGuard;
3030  uno::Reference<uno::XInterface> xInt(create(ServiceSpecifier, &aArgs));
3031 
3032  if ( aArgs.hasElements() )
3033  {
3034  // used only for cell value binding so far - it can be initialized after creating
3035 
3036  uno::Reference<lang::XInitialization> xInit( xInt, uno::UNO_QUERY );
3037  if ( xInit.is() )
3038  xInit->initialize( aArgs );
3039  }
3040 
3041  return xInt;
3042 }
3043 
3044 uno::Sequence<OUString> SAL_CALL ScModelObj::getAvailableServiceNames()
3045 {
3046  SolarMutexGuard aGuard;
3047 
3050 }
3051 
3052 // XServiceInfo
3054 {
3055  return "ScModelObj";
3056  /* // Matching the .component information:
3057  return OUString( "com.sun.star.comp.Calc.SpreadsheetDocument" );
3058  */
3059 }
3060 
3061 sal_Bool SAL_CALL ScModelObj::supportsService( const OUString& rServiceName )
3062 {
3063  return cppu::supportsService(this, rServiceName);
3064 }
3065 
3066 uno::Sequence<OUString> SAL_CALL ScModelObj::getSupportedServiceNames()
3067 {
3069 }
3070 
3071 // XUnoTunnel
3072 
3073 sal_Int64 SAL_CALL ScModelObj::getSomething(
3074  const uno::Sequence<sal_Int8 >& rId )
3075 {
3076  if ( isUnoTunnelId<ScModelObj>(rId) )
3077  {
3078  return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
3079  }
3080 
3081  if ( isUnoTunnelId<SfxObjectShell>(rId) )
3082  {
3083  return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(pDocShell ));
3084  }
3085 
3086  // aggregated number formats supplier has XUnoTunnel, too
3087  // interface from aggregated object must be obtained via queryAggregation
3088 
3089  sal_Int64 nRet = SfxBaseModel::getSomething( rId );
3090  if ( nRet )
3091  return nRet;
3092 
3093  if ( GetFormatter().is() )
3094  {
3095  const uno::Type& rTunnelType = cppu::UnoType<lang::XUnoTunnel>::get();
3096  uno::Any aNumTunnel(xNumberAgg->queryAggregation(rTunnelType));
3097  if(auto xTunnelAgg = o3tl::tryAccess<uno::Reference<lang::XUnoTunnel>>(
3098  aNumTunnel))
3099  {
3100  return (*xTunnelAgg)->getSomething( rId );
3101  }
3102  }
3103 
3104  return 0;
3105 }
3106 
3107 namespace
3108 {
3109  class theScModelObjUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theScModelObjUnoTunnelId> {};
3110 }
3111 
3112 const uno::Sequence<sal_Int8>& ScModelObj::getUnoTunnelId()
3113 {
3114  return theScModelObjUnoTunnelId::get().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  uno::Reference<table::XCellRange> xSheet(static_cast<ScCellRangeObj*>(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  uno::Reference<table::XCellRange> xSheet(static_cast<ScCellRangeObj*>(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>(HMMToTwips(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>(TwipsToHMM(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>(HMMToTwips(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>(HMMToTwips(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>(HMMToTwips(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>(TwipsToHMM(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:2481
SC_DLLPUBLIC bool IsDocProtected() const
Definition: documen3.cxx:1878
Stores the selection in the ScPrintFuncCache so it is only used for the same selection again...
Definition: pfuncache.hxx:46
virtual void SAL_CALL lockControllers() override
Definition: docuno.cxx:2356
ScPrintSelectionMode GetMode() const
Definition: pfuncache.hxx:62
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:572
#define SC_UNO_IGNORECASE
Definition: unonames.hxx:502
SCTAB nTab
Collection belongs to the sheet.
Definition: docuno.hxx:671
virtual void SAL_CALL acquire() override
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:228
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
void SetAutoComplete(bool bNew)
Definition: appoptio.hxx:54
#define SC_POSITIONLEFT
#define SC_UNO_ISADJUSTHEIGHTENABLED
Definition: unonames.hxx:519
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:509
css::uno::Reference< css::uno::XInterface > create(OUString const &aServiceSpecifier, css::uno::Sequence< css::uno::Any > const *arguments)
Definition: docuno.cxx:2932
void UnlockPaint()
Definition: docsh3.cxx:319
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:998
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
Definition: gridwin.cxx:1398
#define PROP_UNO_CALCASSHOWN
Definition: optuno.hxx:26
ScAddress aStart
Definition: address.hxx:500
virtual void SAL_CALL lockControllers() override
SC_DLLPUBLIC bool GetDataStart(SCTAB nTab, SCCOL &rStartCol, SCROW &rStartRow) const
Definition: documen2.cxx:640
virtual void SAL_CALL unprotect(const OUString &aPassword) override
Definition: docuno.cxx:2446
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(const OUString &aServiceSpecifier) override
XMultiServiceFactory.
Definition: docuno.cxx:3016
void SetConsolidateDlgData(std::unique_ptr< ScConsolidateParam > pData)
Definition: documen2.cxx:1103
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:43
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)
virtual const tools::Rectangle & GetCurrentBoundRect() const
SfxPrinter * GetPrinter(bool bCreateIfNotExist=true)
Definition: docsh3.cxx:449
virtual css::uno::Reference< css::sheet::XSpreadsheets > SAL_CALL getSheets() override
XSpreadsheetDocument.
Definition: docuno.cxx:1342
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:4020
#define SC_UNONAME_VISFLAG
Definition: unonames.hxx:186
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:1154
SC_DLLPUBLIC CRFlags GetColFlags(SCCOL nCol, SCTAB nTab) const
Definition: document.cxx:4326
virtual void SAL_CALL release() override
Definition: docuno.cxx:1239
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:2304
SC_DLLPUBLIC bool DeleteContents(const ScMarkData &rMark, InsertDeleteFlags nFlags, bool bRecord, bool bApi)
Definition: docfunc.cxx:568
virtual sal_Int32 SAL_CALL getCount() override
XIndexAccess.
Definition: docuno.cxx:3529
virtual void SAL_CALL unlockControllers() override
Definition: docuno.cxx:2364
osl::Mutex m_aMutex
ScTableRowObj * GetObjectByIndex_Impl(sal_Int32 nIndex) const
Definition: docuno.cxx:4219
virtual sal_Bool SAL_CALL hasByName(const OUString &aName) override
Definition: docuno.cxx:3919
SCROW Row() const
Definition: address.hxx:262
ScDocShell * GetDocShell() const
Definition: cellsuno.hxx:242
void setWidth(tools::Long nWidth)
ScInterpreterContext & GetThreadedContext() const
Definition: document.hxx:609
#define SC_UNO_ITERENABLED
Definition: unonames.hxx:504
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:3023
ServiceType
#define SC_ACTIVETABLE
virtual void setTextSelection(int nType, int nX, int nY) override
Definition: docuno.cxx:740
virtual css::uno::Reference< css::container::XIndexAccess > SAL_CALL getViewData() override