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