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().getStr());
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
1242void ScModelObj::initializeForTiledRendering(const css::uno::Sequence<css::beans::PropertyValue>& rArguments)
1243{
1244 SolarMutexGuard aGuard;
1245
1246 // enable word autocompletion
1247 ScAppOptions aAppOptions(SC_MOD()->GetAppOptions());
1248 aAppOptions.SetAutoComplete(true);
1249 SC_MOD()->SetAppOptions(aAppOptions);
1250
1251 for (const beans::PropertyValue& rValue : rArguments)
1252 {
1253 if (rValue.Name == ".uno:SpellOnline" && rValue.Value.has<bool>())
1254 {
1255 ScDocOptions options = GetDocument()->GetDocOptions();
1256 options.SetAutoSpell(rValue.Value.get<bool>());
1257 GetDocument()->SetDocOptions(options);
1258 }
1259 }
1260
1261 // show us the text exactly
1262 ScInputOptions aInputOptions(SC_MOD()->GetInputOptions());
1263 aInputOptions.SetTextWysiwyg(true);
1264 aInputOptions.SetReplaceCellsWarn(false);
1265 SC_MOD()->SetInputOptions(aInputOptions);
1267
1268 // when the "This document may contain formatting or content that cannot
1269 // be saved..." dialog appears, it is auto-cancelled with tiled rendering,
1270 // causing 'Save' being disabled; so let's always save to the original
1271 // format
1273 officecfg::Office::Common::Save::Document::WarnAlienFormat::set(false, xChanges);
1274 xChanges->commit();
1275}
1276
1278{
1279 SC_QUERYINTERFACE( sheet::XSpreadsheetDocument )
1280 SC_QUERYINTERFACE( document::XActionLockable )
1281 SC_QUERYINTERFACE( sheet::XCalculatable )
1282 SC_QUERYINTERFACE( util::XProtectable )
1283 SC_QUERYINTERFACE( drawing::XDrawPagesSupplier )
1284 SC_QUERYINTERFACE( sheet::XGoalSeek )
1285 SC_QUERYINTERFACE( sheet::XConsolidatable )
1286 SC_QUERYINTERFACE( sheet::XDocumentAuditing )
1287 SC_QUERYINTERFACE( style::XStyleFamiliesSupplier )
1288 SC_QUERYINTERFACE( view::XRenderable )
1289 SC_QUERYINTERFACE( document::XLinkTargetSupplier )
1290 SC_QUERYINTERFACE( beans::XPropertySet )
1291 SC_QUERYINTERFACE( lang::XMultiServiceFactory )
1292 SC_QUERYINTERFACE( lang::XServiceInfo )
1293 SC_QUERYINTERFACE( util::XChangesNotifier )
1294 SC_QUERYINTERFACE( sheet::opencl::XOpenCLSelection )
1295 SC_QUERYINTERFACE( chart2::XDataProviderAccess )
1296
1298 if ( !aRet.hasValue()
1305 {
1306 GetFormatter();
1307 if ( xNumberAgg.is() )
1308 aRet = xNumberAgg->queryAggregation( rType );
1309 }
1310
1311 return aRet;
1312}
1313
1314void SAL_CALL ScModelObj::acquire() noexcept
1315{
1317}
1318
1319void SAL_CALL ScModelObj::release() noexcept
1320{
1322}
1323
1324uno::Sequence<uno::Type> SAL_CALL ScModelObj::getTypes()
1325{
1326 static const uno::Sequence<uno::Type> aTypes = [&]()
1327 {
1328 uno::Sequence<uno::Type> aAggTypes;
1329 if ( GetFormatter().is() )
1330 {
1332 uno::Any aNumProv(xNumberAgg->queryAggregation(rProvType));
1333 if(auto xNumProv
1334 = o3tl::tryAccess<uno::Reference<lang::XTypeProvider>>(aNumProv))
1335 {
1336 aAggTypes = (*xNumProv)->getTypes();
1337 }
1338 }
1341 aAggTypes,
1342 uno::Sequence<uno::Type>
1343 {
1360 } );
1361 }();
1362 return aTypes;
1363}
1364
1365uno::Sequence<sal_Int8> SAL_CALL ScModelObj::getImplementationId()
1366{
1367 return css::uno::Sequence<sal_Int8>();
1368}
1369
1371{
1372 // Not interested in reference update hints here
1373
1374 const SfxHintId nId = rHint.GetId();
1375 if ( nId == SfxHintId::Dying )
1376 {
1377 pDocShell = nullptr; // has become invalid
1378 if (xNumberAgg.is())
1379 {
1381 comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(
1382 uno::Reference<util::XNumberFormatsSupplier>(xNumberAgg, uno::UNO_QUERY) );
1383 if ( pNumFmt )
1384 pNumFmt->SetNumberFormatter( nullptr );
1385 }
1386
1387 pPrintFuncCache.reset(); // must be deleted because it has a pointer to the DocShell
1388 m_pPrintState.reset();
1389 }
1390 else if ( nId == SfxHintId::DataChanged )
1391 {
1392 // cached data for rendering become invalid when contents change
1393 // (if a broadcast is added to SetDrawModified, is has to be tested here, too)
1394
1395 pPrintFuncCache.reset();
1396 m_pPrintState.reset();
1397
1398 // handle "OnCalculate" sheet events (search also for VBA event handlers)
1399 if ( pDocShell )
1400 {
1401 ScDocument& rDoc = pDocShell->GetDocument();
1402 if ( rDoc.GetVbaEventProcessor().is() )
1403 {
1404 // If the VBA event processor is set, HasAnyCalcNotification is much faster than HasAnySheetEventScript
1407 }
1408 else
1409 {
1412 }
1413 }
1414 }
1415
1416 // always call parent - SfxBaseModel might need to handle the same hints again
1417 SfxBaseModel::Notify( rBC, rHint ); // SfxBaseModel is derived from SfxListener
1418}
1419
1420// XSpreadsheetDocument
1421
1422uno::Reference<sheet::XSpreadsheets> SAL_CALL ScModelObj::getSheets()
1423{
1424 SolarMutexGuard aGuard;
1425 if (pDocShell)
1426 return new ScTableSheetsObj(pDocShell);
1427 return nullptr;
1428}
1429
1430css::uno::Reference< ::css::chart2::data::XDataProvider > SAL_CALL ScModelObj::createDataProvider()
1431{
1432 if (pDocShell)
1433 {
1434 return css::uno::Reference< ::css::chart2::data::XDataProvider > (
1436 }
1437 return nullptr;
1438}
1439
1440// XStyleFamiliesSupplier
1441
1442uno::Reference<container::XNameAccess> SAL_CALL ScModelObj::getStyleFamilies()
1443{
1444 SolarMutexGuard aGuard;
1445 if (pDocShell)
1446 return new ScStyleFamiliesObj(pDocShell);
1447 return nullptr;
1448}
1449
1450// XRenderable
1451
1452static OutputDevice* lcl_GetRenderDevice( const uno::Sequence<beans::PropertyValue>& rOptions )
1453{
1454 OutputDevice* pRet = nullptr;
1455 for (const beans::PropertyValue& rProp : rOptions)
1456 {
1457 const OUString & rPropName = rProp.Name;
1458
1459 if (rPropName == SC_UNONAME_RENDERDEV)
1460 {
1461 uno::Reference<awt::XDevice> xRenderDevice(rProp.Value, uno::UNO_QUERY);
1462 if ( xRenderDevice.is() )
1463 {
1464 VCLXDevice* pDevice = dynamic_cast<VCLXDevice*>( xRenderDevice.get() );
1465 if ( pDevice )
1466 {
1467 pRet = pDevice->GetOutputDevice().get();
1468 pRet->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
1469 }
1470 }
1471 }
1472 }
1473 return pRet;
1474}
1475
1476static bool lcl_ParseTarget( const OUString& rTarget, ScRange& rTargetRange, tools::Rectangle& rTargetRect,
1477 bool& rIsSheet, ScDocument& rDoc, SCTAB nSourceTab )
1478{
1479 // test in same order as in SID_CURRENTCELL execute
1480
1481 ScAddress aAddress;
1482 SCTAB nNameTab;
1483 sal_Int32 nNumeric = 0;
1484
1485 bool bRangeValid = false;
1486 bool bRectValid = false;
1487
1488 if ( rTargetRange.Parse( rTarget, rDoc ) & ScRefFlags::VALID )
1489 {
1490 bRangeValid = true; // range reference
1491 }
1492 else if ( aAddress.Parse( rTarget, rDoc ) & ScRefFlags::VALID )
1493 {
1494 rTargetRange = aAddress;
1495 bRangeValid = true; // cell reference
1496 }
1497 else if ( ScRangeUtil::MakeRangeFromName( rTarget, rDoc, nSourceTab, rTargetRange ) ||
1498 ScRangeUtil::MakeRangeFromName( rTarget, rDoc, nSourceTab, rTargetRange, RUTL_DBASE ) )
1499 {
1500 bRangeValid = true; // named range or database range
1501 }
1503 ( nNumeric = rTarget.toInt32() ) > 0 && nNumeric <= rDoc.MaxRow()+1 )
1504 {
1505 // row number is always mapped to cell A(row) on the same sheet
1506 rTargetRange = ScAddress( 0, static_cast<SCROW>(nNumeric-1), nSourceTab ); // target row number is 1-based
1507 bRangeValid = true; // row number
1508 }
1509 else if ( rDoc.GetTable( rTarget, nNameTab ) )
1510 {
1511 rTargetRange = ScAddress(0,0,nNameTab);
1512 bRangeValid = true; // sheet name
1513 rIsSheet = true; // needs special handling (first page of the sheet)
1514 }
1515 else
1516 {
1517 // look for named drawing object
1518
1519 ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
1520 if ( pDrawLayer )
1521 {
1522 SCTAB nTabCount = rDoc.GetTableCount();
1523 for (SCTAB i=0; i<nTabCount && !bRangeValid; i++)
1524 {
1525 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(i));
1526 OSL_ENSURE(pPage,"Page ?");
1527 if (pPage)
1528 {
1529 SdrObjListIter aIter( pPage, SdrIterMode::DeepWithGroups );
1530 SdrObject* pObject = aIter.Next();
1531 while (pObject && !bRangeValid)
1532 {
1534 {
1535 rTargetRect = pObject->GetLogicRect(); // 1/100th mm
1536 rTargetRange = rDoc.GetRange( i, rTargetRect ); // underlying cells
1537 bRangeValid = bRectValid = true; // rectangle is valid
1538 }
1539 pObject = aIter.Next();
1540 }
1541 }
1542 }
1543 }
1544 }
1545 if ( bRangeValid && !bRectValid )
1546 {
1547 // get rectangle for cell range
1548 rTargetRect = rDoc.GetMMRect( rTargetRange.aStart.Col(), rTargetRange.aStart.Row(),
1549 rTargetRange.aEnd.Col(), rTargetRange.aEnd.Row(),
1550 rTargetRange.aStart.Tab() );
1551 }
1552
1553 return bRangeValid;
1554}
1555
1557 const uno::Sequence< beans::PropertyValue >& rOptions,
1558 ScMarkData& rMark,
1559 ScPrintSelectionStatus& rStatus, OUString& rPagesStr,
1560 bool& rbRenderToGraphic ) const
1561{
1562 OSL_ENSURE( !rMark.IsMarked() && !rMark.IsMultiMarked(), "FillRenderMarkData: MarkData must be empty" );
1563 OSL_ENSURE( pDocShell, "FillRenderMarkData: DocShell must be set" );
1564
1565 bool bDone = false;
1566
1567 uno::Reference<frame::XController> xView;
1568
1569 // defaults when no options are passed: all sheets, include empty pages
1570 bool bSelectedSheetsOnly = false;
1571 bool bSuppressEmptyPages = true;
1572
1573 bool bHasPrintContent = false;
1574 sal_Int32 nPrintContent = 0; // all sheets / selected sheets / selected cells
1575 sal_Int32 nPrintRange = 0; // all pages / pages
1576 sal_Int32 nEOContent = 0; // even pages / odd pages
1577 OUString aPageRange; // "pages" edit value
1578
1579 for( const auto& rOption : rOptions )
1580 {
1581 if ( rOption.Name == "IsOnlySelectedSheets" )
1582 {
1583 rOption.Value >>= bSelectedSheetsOnly;
1584 }
1585 else if ( rOption.Name == "IsSuppressEmptyPages" )
1586 {
1587 rOption.Value >>= bSuppressEmptyPages;
1588 }
1589 else if ( rOption.Name == "PageRange" )
1590 {
1591 rOption.Value >>= aPageRange;
1592 }
1593 else if ( rOption.Name == "PrintRange" )
1594 {
1595 rOption.Value >>= nPrintRange;
1596 }
1597 else if ( rOption.Name == "EvenOdd" )
1598 {
1599 rOption.Value >>= nEOContent;
1600 }
1601 else if ( rOption.Name == "PrintContent" )
1602 {
1603 bHasPrintContent = true;
1604 rOption.Value >>= nPrintContent;
1605 }
1606 else if ( rOption.Name == "View" )
1607 {
1608 rOption.Value >>= xView;
1609 }
1610 else if ( rOption.Name == "RenderToGraphic" )
1611 {
1612 rOption.Value >>= rbRenderToGraphic;
1613 }
1614 }
1615
1616 // "Print Content" selection wins over "Selected Sheets" option
1617 if ( bHasPrintContent )
1618 bSelectedSheetsOnly = ( nPrintContent != 0 );
1619
1620 uno::Reference<uno::XInterface> xInterface(aSelection, uno::UNO_QUERY);
1621 if ( xInterface.is() )
1622 {
1623 ScCellRangesBase* pSelObj = dynamic_cast<ScCellRangesBase*>( xInterface.get() );
1624 uno::Reference< drawing::XShapes > xShapes( xInterface, uno::UNO_QUERY );
1625 if ( pSelObj && pSelObj->GetDocShell() == pDocShell )
1626 {
1627 bool bSheet = ( dynamic_cast<ScTableSheetObj*>( pSelObj ) != nullptr );
1628 bool bCursor = pSelObj->IsCursorOnly();
1629 const ScRangeList& rRanges = pSelObj->GetRangeList();
1630
1631 rMark.MarkFromRangeList( rRanges, false );
1632 rMark.MarkToSimple();
1633
1634 if ( rMark.IsMultiMarked() )
1635 {
1636 // #i115266# copy behavior of old printing:
1637 // treat multiple selection like a single selection with the enclosing range
1638 const ScRange& aMultiMarkArea = rMark.GetMultiMarkArea();
1639 rMark.ResetMark();
1640 rMark.SetMarkArea( aMultiMarkArea );
1641 }
1642
1643 if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
1644 {
1645 // a sheet object is treated like an empty selection: print the used area of the sheet
1646
1647 if ( bCursor || bSheet ) // nothing selected -> use whole tables
1648 {
1649 rMark.ResetMark(); // doesn't change table selection
1651 }
1652 else
1654
1655 rStatus.SetRanges( rRanges );
1656 bDone = true;
1657 }
1658 // multi selection isn't supported
1659 }
1660 else if( xShapes.is() )
1661 {
1662 //print a selected ole object
1663 // multi selection isn't supported yet
1664 uno::Reference< drawing::XShape > xShape( xShapes->getByIndex(0), uno::UNO_QUERY );
1665 SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape );
1666 if( pSdrObj && pDocShell )
1667 {
1668 ScDocument& rDoc = pDocShell->GetDocument();
1669 tools::Rectangle aObjRect = pSdrObj->GetCurrentBoundRect();
1670 SCTAB nCurrentTab = ScDocShell::GetCurTab();
1671 ScRange aRange = rDoc.GetRange( nCurrentTab, aObjRect );
1672 rMark.SetMarkArea( aRange );
1673
1674 if( rMark.IsMarked() && !rMark.IsMultiMarked() )
1675 {
1677 bDone = true;
1678 }
1679 }
1680 }
1681 else if ( comphelper::getFromUnoTunnel<ScModelObj>( xInterface ) == this )
1682 {
1683 // render the whole document
1684 // -> no selection, all sheets
1685
1686 SCTAB nTabCount = pDocShell->GetDocument().GetTableCount();
1687 for (SCTAB nTab = 0; nTab < nTabCount; nTab++)
1688 rMark.SelectTable( nTab, true );
1690 bDone = true;
1691 }
1692 // other selection types aren't supported
1693 }
1694
1695 // restrict to selected sheets if a view is available
1696 uno::Reference<sheet::XSelectedSheetsSupplier> xSelectedSheets(xView, uno::UNO_QUERY);
1697 if (bSelectedSheetsOnly && pDocShell && xSelectedSheets.is())
1698 {
1699 const uno::Sequence<sal_Int32> aSelected = xSelectedSheets->getSelectedSheets();
1700 ScMarkData::MarkedTabsType aSelectedTabs;
1701 SCTAB nMaxTab = pDocShell->GetDocument().GetTableCount() -1;
1702 for (const auto& rSelected : aSelected)
1703 {
1704 SCTAB nSelected = static_cast<SCTAB>(rSelected);
1705 if (ValidTab(nSelected, nMaxTab))
1706 aSelectedTabs.insert(nSelected);
1707 }
1708 rMark.SetSelectedTabs(aSelectedTabs);
1709 }
1710
1711 ScPrintOptions aNewOptions;
1712 aNewOptions.SetSkipEmpty( bSuppressEmptyPages );
1713 aNewOptions.SetAllSheets( !bSelectedSheetsOnly );
1714 rStatus.SetOptions( aNewOptions );
1715
1716 // "PrintRange" enables (1) or disables (0) the "PageRange" edit
1717 if ( nPrintRange == 1 )
1718 rPagesStr = aPageRange;
1719 else
1720 rPagesStr.clear();
1721
1722 return bDone;
1723}
1724
1725sal_Int32 SAL_CALL ScModelObj::getRendererCount(const uno::Any& aSelection,
1726 const uno::Sequence<beans::PropertyValue>& rOptions)
1727{
1728 SolarMutexGuard aGuard;
1729 if (!pDocShell)
1730 {
1731 throw lang::DisposedException( OUString(),
1732 static_cast< sheet::XSpreadsheetDocument* >(this) );
1733 }
1734
1735 ScMarkData aMark(GetDocument()->GetSheetLimits());
1736 ScPrintSelectionStatus aStatus;
1737 OUString aPagesStr;
1738 bool bRenderToGraphic = false;
1739 if ( !FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr, bRenderToGraphic ) )
1740 return 0;
1741
1742 // The same ScPrintFuncCache object in pPrintFuncCache is used as long as
1743 // the same selection is used (aStatus) and the document isn't changed
1744 // (pPrintFuncCache is cleared in Notify handler)
1745
1746 if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) )
1747 {
1748 pPrintFuncCache.reset(new ScPrintFuncCache( pDocShell, aMark, aStatus ));
1749 }
1750 sal_Int32 nPages = pPrintFuncCache->GetPageCount();
1751
1752 m_pPrintState.reset();
1753 maValidPages.clear();
1754
1755 sal_Int32 nContent = 0;
1756 sal_Int32 nEOContent = 0;
1757 bool bSinglePageSheets = false;
1758 for ( const auto& rValue : rOptions)
1759 {
1760 if ( rValue.Name == "PrintRange" )
1761 {
1762 rValue.Value >>= nContent;
1763 }
1764 else if ( rValue.Name == "SinglePageSheets" )
1765 {
1766 rValue.Value >>= bSinglePageSheets;
1767 }
1768 else if ( rValue.Name == "EvenOdd" )
1769 {
1770 rValue.Value >>= nEOContent;
1771 }
1772 }
1773
1774 if (bSinglePageSheets)
1775 {
1777 }
1778
1779 bool bIsPrintEvenPages = (nEOContent != 1 && nContent == 0) || nContent != 0;
1780 bool bIsPrintOddPages = (nEOContent != 2 && nContent == 0) || nContent != 0;
1781
1782 for ( sal_Int32 nPage = 1; nPage <= nPages; nPage++ )
1783 {
1784 if ( (bIsPrintEvenPages && IsOnEvenPage( nPage )) || (bIsPrintOddPages && !IsOnEvenPage( nPage )) )
1785 maValidPages.push_back( nPage );
1786 }
1787
1788 sal_Int32 nSelectCount = static_cast<sal_Int32>( maValidPages.size() );
1789
1790 if ( nEOContent == 1 || nEOContent == 2 ) // even pages / odd pages
1791 return nSelectCount;
1792
1793 if ( !aPagesStr.isEmpty() )
1794 {
1795 StringRangeEnumerator aRangeEnum( aPagesStr, 0, nPages-1 );
1796 nSelectCount = aRangeEnum.size();
1797 }
1798 return (nSelectCount > 0) ? nSelectCount : 1;
1799}
1800
1801static sal_Int32 lcl_GetRendererNum( sal_Int32 nSelRenderer, std::u16string_view rPagesStr, sal_Int32 nTotalPages )
1802{
1803 if ( rPagesStr.empty() )
1804 return nSelRenderer;
1805
1806 StringRangeEnumerator aRangeEnum( rPagesStr, 0, nTotalPages-1 );
1807 StringRangeEnumerator::Iterator aIter = aRangeEnum.begin();
1808 StringRangeEnumerator::Iterator aEnd = aRangeEnum.end();
1809 for ( ; nSelRenderer > 0 && aIter != aEnd; --nSelRenderer )
1810 ++aIter;
1811
1812 return *aIter; // returns -1 if reached the end
1813}
1814
1815static bool lcl_renderSelectionToGraphic( bool bRenderToGraphic, const ScPrintSelectionStatus& rStatus )
1816{
1817 return bRenderToGraphic && rStatus.GetMode() == ScPrintSelectionMode::Range;
1818}
1819
1820uno::Sequence<beans::PropertyValue> SAL_CALL ScModelObj::getRenderer( sal_Int32 nSelRenderer,
1821 const uno::Any& aSelection, const uno::Sequence<beans::PropertyValue>& rOptions )
1822{
1823 SolarMutexGuard aGuard;
1824 if (!pDocShell)
1825 {
1826 throw lang::DisposedException( OUString(),
1827 static_cast< sheet::XSpreadsheetDocument* >(this) );
1828 }
1829
1831 ScPrintSelectionStatus aStatus;
1832 OUString aPagesStr;
1833 // #i115266# if FillRenderMarkData fails, keep nTotalPages at 0, but still handle getRenderer(0) below
1834 tools::Long nTotalPages = 0;
1835 bool bRenderToGraphic = false;
1836 bool bSinglePageSheets = false;
1837 if ( FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr, bRenderToGraphic ) )
1838 {
1839 if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) )
1840 {
1841 pPrintFuncCache.reset(new ScPrintFuncCache( pDocShell, aMark, aStatus ));
1842 }
1843 nTotalPages = pPrintFuncCache->GetPageCount();
1844 }
1845
1846 for ( const auto& rValue : rOptions)
1847 {
1848 if ( rValue.Name == "SinglePageSheets" )
1849 {
1850 rValue.Value >>= bSinglePageSheets;
1851 break;
1852 }
1853 }
1854
1855 if (bSinglePageSheets)
1856 nTotalPages = pDocShell->GetDocument().GetTableCount();
1857
1858 sal_Int32 nRenderer = lcl_GetRendererNum( nSelRenderer, aPagesStr, nTotalPages );
1859
1860 if ( nRenderer < 0 )
1861 {
1862 if ( nSelRenderer != 0 )
1863 throw lang::IllegalArgumentException();
1864
1865 // getRenderer(0) is used to query the settings, so it must always return something
1866
1867 awt::Size aPageSize;
1868 if (lcl_renderSelectionToGraphic( bRenderToGraphic, aStatus))
1869 {
1870 assert( aMark.IsMarked());
1871 const ScRange& aRange = aMark.GetMarkArea();
1873 aRange.aStart.Col(), aRange.aStart.Row(),
1874 aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
1875 aPageSize.Width = aMMRect.GetWidth();
1876 aPageSize.Height = aMMRect.GetHeight();
1877 }
1878 else
1879 {
1880 SCTAB const nCurTab = 0;
1881 ScPrintFunc aDefaultFunc( pDocShell, pDocShell->GetPrinter(), nCurTab );
1882 Size aTwips = aDefaultFunc.GetPageSize();
1883 aPageSize.Width = convertTwipToMm100(aTwips.Width());
1884 aPageSize.Height = convertTwipToMm100(aTwips.Height());
1885 }
1886
1887 uno::Sequence<beans::PropertyValue> aSequence( comphelper::InitPropertySequence({
1888 { SC_UNONAME_PAGESIZE, uno::Any(aPageSize) }
1889 }));
1890
1891 if( ! pPrinterOptions )
1893 else
1894 pPrinterOptions->SetDefaults();
1895 pPrinterOptions->appendPrintUIOptions( aSequence );
1896 return aSequence;
1897
1898 }
1899
1900 // printer is used as device (just for page layout), draw view is not needed
1901
1902 SCTAB nTab;
1903 if (bSinglePageSheets)
1904 nTab = nSelRenderer;
1905 else if ( !maValidPages.empty() )
1906 nTab = pPrintFuncCache->GetTabForPage( maValidPages.at( nRenderer )-1 );
1907 else
1908 nTab = pPrintFuncCache->GetTabForPage( nRenderer );
1909
1910
1911 ScRange aRange;
1912 const ScRange* pSelRange = nullptr;
1913 if ( bSinglePageSheets )
1914 {
1915 SCCOL nStartCol;
1916 SCROW nStartRow;
1917 const ScDocument* pDocument = &pDocShell->GetDocument();
1918 pDocument->GetDataStart( nTab, nStartCol, nStartRow );
1919 SCCOL nEndCol;
1920 SCROW nEndRow;
1921 pDocument->GetPrintArea( nTab, nEndCol, nEndRow );
1922
1923 aRange.aStart = ScAddress(nStartCol, nStartRow, nTab);
1924 aRange.aEnd = ScAddress(nEndCol, nEndRow, nTab);
1925
1926 table::CellRangeAddress aRangeAddress( nTab,
1927 aRange.aStart.Col(), aRange.aStart.Row(),
1928 aRange.aEnd.Col(), aRange.aEnd.Row() );
1930 aRange.aStart.Col(), aRange.aStart.Row(),
1931 aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
1932
1933 const awt::Size aPageSize(aMMRect.GetWidth(), aMMRect.GetHeight());
1934 const awt::Point aCalcPagePos(aMMRect.Left(), aMMRect.Top());
1935
1936 uno::Sequence<beans::PropertyValue> aSequence
1937 {
1939 // #i111158# all positions are relative to the whole page, including non-printable area
1942 comphelper::makePropertyValue(SC_UNONAME_CALCPAGESIZE, aPageSize), // TODO aPageSize too ?
1944 };
1945
1946 if( ! pPrinterOptions )
1948 else
1949 pPrinterOptions->SetDefaults();
1950 pPrinterOptions->appendPrintUIOptions( aSequence );
1951 return aSequence;
1952 }
1953 else if ( aMark.IsMarked() )
1954 {
1955 aRange = aMark.GetMarkArea();
1956 pSelRange = &aRange;
1957 }
1958
1959 awt::Size aPageSize;
1960 bool bWasCellRange = false;
1961 ScRange aCellRange;
1962 if (lcl_renderSelectionToGraphic( bRenderToGraphic, aStatus))
1963 {
1964 bWasCellRange = true;
1965 aCellRange = aRange;
1967 aRange.aStart.Col(), aRange.aStart.Row(),
1968 aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
1969 aPageSize.Width = aMMRect.GetWidth();
1970 aPageSize.Height = aMMRect.GetHeight();
1971 }
1972 else
1973 {
1974 std::unique_ptr<ScPrintFunc, o3tl::default_delete<ScPrintFunc>> pPrintFunc;
1975 if (m_pPrintState && m_pPrintState->nPrintTab == nTab)
1976 pPrintFunc.reset(new ScPrintFunc(pDocShell, pDocShell->GetPrinter(), *m_pPrintState, &aStatus.GetOptions()));
1977 else
1978 pPrintFunc.reset(new ScPrintFunc(pDocShell, pDocShell->GetPrinter(), nTab,
1979 pPrintFuncCache->GetFirstAttr(nTab), nTotalPages, pSelRange, &aStatus.GetOptions()));
1980 pPrintFunc->SetRenderFlag( true );
1981
1982 sal_Int32 nContent = 0;
1983 sal_Int32 nEOContent = 0;
1984 for ( const auto& rValue : rOptions)
1985 {
1986 if ( rValue.Name == "PrintRange" )
1987 {
1988 rValue.Value >>= nContent;
1989 }
1990 else if ( rValue.Name == "EvenOdd" )
1991 {
1992 rValue.Value >>= nEOContent;
1993 }
1994 }
1995
1996 MultiSelection aPage;
1997 aPage.SetTotalRange( Range(0,RANGE_MAX) );
1998
1999 bool bOddOrEven = (nContent == 0 && nEOContent == 1) || (nContent == 1 && nEOContent == 2); // even pages or odd pages
2000 // tdf#127682 when odd/even allow nRenderer of 0 even when maValidPages is empty
2001 // to allow PrinterController::abortJob to spool an empty page as part of
2002 // its abort procedure
2003 if (bOddOrEven && !maValidPages.empty())
2004 aPage.Select( maValidPages.at(nRenderer) );
2005 else
2006 aPage.Select( nRenderer+1 );
2007
2008 tools::Long nDisplayStart = pPrintFuncCache->GetDisplayStart( nTab );
2009 tools::Long nTabStart = pPrintFuncCache->GetTabStart( nTab );
2010
2011 (void)pPrintFunc->DoPrint( aPage, nTabStart, nDisplayStart, false, nullptr );
2012
2013 bWasCellRange = pPrintFunc->GetLastSourceRange( aCellRange );
2014 Size aTwips = pPrintFunc->GetPageSize();
2015
2016 if (!m_pPrintState)
2017 {
2018 m_pPrintState.reset(new ScPrintState());
2019 pPrintFunc->GetPrintState(*m_pPrintState, true);
2020 }
2021
2022 aPageSize.Width = convertTwipToMm100(aTwips.Width());
2023 aPageSize.Height = convertTwipToMm100(aTwips.Height());
2024 }
2025
2026 tools::Long nPropCount = bWasCellRange ? 5 : 4;
2027 uno::Sequence<beans::PropertyValue> aSequence(nPropCount);
2028 beans::PropertyValue* pArray = aSequence.getArray();
2029 pArray[0].Name = SC_UNONAME_PAGESIZE;
2030 pArray[0].Value <<= aPageSize;
2031 // #i111158# all positions are relative to the whole page, including non-printable area
2032 pArray[1].Name = SC_UNONAME_INC_NP_AREA;
2033 pArray[1].Value <<= true;
2034 if ( bWasCellRange )
2035 {
2036 table::CellRangeAddress aRangeAddress( nTab,
2037 aCellRange.aStart.Col(), aCellRange.aStart.Row(),
2038 aCellRange.aEnd.Col(), aCellRange.aEnd.Row() );
2040 aCellRange.aStart.Col(), aCellRange.aStart.Row(),
2041 aCellRange.aEnd.Col(), aCellRange.aEnd.Row(), aCellRange.aStart.Tab()));
2042
2043 const awt::Size aCalcPageSize(aMMRect.GetWidth(), aMMRect.GetHeight());
2044 const awt::Point aCalcPagePos(aMMRect.Left(), aMMRect.Top());
2045
2046 pArray[2].Name = SC_UNONAME_SOURCERANGE;
2047 pArray[2].Value <<= aRangeAddress;
2048 pArray[3].Name = SC_UNONAME_CALCPAGESIZE;
2049 pArray[3].Value <<= aCalcPageSize;
2050 pArray[4].Name = SC_UNONAME_CALCPAGEPOS;
2051 pArray[4].Value <<= aCalcPagePos;
2052 }
2053
2054 if( ! pPrinterOptions )
2056 else
2057 pPrinterOptions->SetDefaults();
2058 pPrinterOptions->appendPrintUIOptions( aSequence );
2059 return aSequence;
2060}
2061
2062void SAL_CALL ScModelObj::render( sal_Int32 nSelRenderer, const uno::Any& aSelection,
2063 const uno::Sequence<beans::PropertyValue>& rOptions )
2064{
2065 SolarMutexGuard aGuard;
2066 if (!pDocShell)
2067 {
2068 throw lang::DisposedException( OUString(),
2069 static_cast< sheet::XSpreadsheetDocument* >(this) );
2070 }
2071
2073 ScPrintSelectionStatus aStatus;
2074 OUString aPagesStr;
2075 bool bRenderToGraphic = false;
2076 bool bSinglePageSheets = false;
2077 if ( !FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr, bRenderToGraphic ) )
2078 throw lang::IllegalArgumentException();
2079
2080 if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) )
2081 {
2082 pPrintFuncCache.reset(new ScPrintFuncCache( pDocShell, aMark, aStatus ));
2083 }
2084 tools::Long nTotalPages = pPrintFuncCache->GetPageCount();
2085
2086 for ( const auto& rValue : rOptions)
2087 {
2088 if ( rValue.Name == "SinglePageSheets" )
2089 {
2090 rValue.Value >>= bSinglePageSheets;
2091 break;
2092 }
2093 }
2094
2095 if (bSinglePageSheets)
2096 nTotalPages = pDocShell->GetDocument().GetTableCount();
2097
2098 sal_Int32 nRenderer = lcl_GetRendererNum( nSelRenderer, aPagesStr, nTotalPages );
2099 if ( nRenderer < 0 )
2100 throw lang::IllegalArgumentException();
2101
2102 OutputDevice* pDev = lcl_GetRenderDevice( rOptions );
2103 if ( !pDev )
2104 throw lang::IllegalArgumentException();
2105
2106 ScDocument& rDoc = pDocShell->GetDocument();
2107
2108 ScRange aRange;
2109 const ScRange* pSelRange = nullptr;
2110 if ( bSinglePageSheets )
2111 {
2112 awt::Size aPageSize;
2113 SCCOL nStartCol;
2114 SCROW nStartRow;
2115 rDoc.GetDataStart( nSelRenderer, nStartCol, nStartRow );
2116 SCCOL nEndCol;
2117 SCROW nEndRow;
2118 rDoc.GetPrintArea( nSelRenderer, nEndCol, nEndRow );
2119
2120 aRange.aStart = ScAddress(nStartCol, nStartRow, nSelRenderer);
2121 aRange.aEnd = ScAddress(nEndCol, nEndRow, nSelRenderer);
2122
2124 aRange.aStart.Col(), aRange.aStart.Row(),
2125 aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
2126
2127 aPageSize.Width = aMMRect.GetWidth();
2128 aPageSize.Height = aMMRect.GetHeight();
2129
2130 //Set visible tab
2131 SCTAB nVisTab = rDoc.GetVisibleTab();
2132 if (nVisTab != nSelRenderer)
2133 {
2134 nVisTab = nSelRenderer;
2135 rDoc.SetVisibleTab(nVisTab);
2136 }
2137
2138 pDocShell->DoDraw(pDev, Point(0,0), Size(aPageSize.Width, aPageSize.Height), JobSetup());
2139
2140 return;
2141 }
2142 else if ( aMark.IsMarked() )
2143 {
2144 aRange = aMark.GetMarkArea();
2145 pSelRange = &aRange;
2146 }
2147
2148 if (lcl_renderSelectionToGraphic( bRenderToGraphic, aStatus))
2149 {
2150 // Similar to as in and when calling ScTransferObj::PaintToDev()
2151
2152 tools::Rectangle aBound( Point(), pDev->GetOutputSize());
2153
2154 ScViewData aViewData(rDoc);
2155
2156 aViewData.SetTabNo( aRange.aStart.Tab() );
2157 aViewData.SetScreen( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row() );
2158
2159 const double nPrintFactor = 1.0; /* XXX: currently (2017-08-28) is not evaluated */
2160 // The bMetaFile argument maybe could be
2161 // pDev->GetConnectMetaFile() != nullptr
2162 // but for some yet unknown reason does not draw cell content if true.
2163 ScPrintFunc::DrawToDev( rDoc, pDev, nPrintFactor, aBound, &aViewData, false /*bMetaFile*/ );
2164
2165 return;
2166 }
2167
2168 struct DrawViewKeeper
2169 {
2170 std::unique_ptr<FmFormView> mpDrawView;
2171 DrawViewKeeper() {}
2172 ~DrawViewKeeper()
2173 {
2174 if (mpDrawView)
2175 {
2176 mpDrawView->HideSdrPage();
2177 mpDrawView.reset();
2178 }
2179 }
2180 } aDrawViewKeeper;
2181
2182 SCTAB nTab;
2183 if ( !maValidPages.empty() )
2184 nTab = pPrintFuncCache->GetTabForPage( maValidPages.at( nRenderer )-1 );
2185 else
2186 nTab = pPrintFuncCache->GetTabForPage( nRenderer );
2187
2188 ScDrawLayer* pModel = rDoc.GetDrawLayer();
2189
2190 if( pModel )
2191 {
2192 aDrawViewKeeper.mpDrawView.reset( new FmFormView(
2193 *pModel,
2194 pDev) );
2195 aDrawViewKeeper.mpDrawView->ShowSdrPage(aDrawViewKeeper.mpDrawView->GetModel()->GetPage(nTab));
2196 aDrawViewKeeper.mpDrawView->SetPrintPreview();
2197 }
2198
2199 // to increase performance, ScPrintState might be used here for subsequent
2200 // pages of the same sheet
2201
2202
2203 std::unique_ptr<ScPrintFunc, o3tl::default_delete<ScPrintFunc>> pPrintFunc;
2204 if (m_pPrintState && m_pPrintState->nPrintTab == nTab
2205 && ! pSelRange) // tdf#120161 use selection to set required printed area
2206 pPrintFunc.reset(new ScPrintFunc(pDev, pDocShell, *m_pPrintState, &aStatus.GetOptions()));
2207 else
2208 pPrintFunc.reset(new ScPrintFunc(pDev, pDocShell, nTab, pPrintFuncCache->GetFirstAttr(nTab), nTotalPages, pSelRange, &aStatus.GetOptions()));
2209
2210 pPrintFunc->SetDrawView( aDrawViewKeeper.mpDrawView.get() );
2211 pPrintFunc->SetRenderFlag( true );
2213 pPrintFunc->SetExclusivelyDrawOleAndDrawObjects();
2214
2215 sal_Int32 nContent = 0;
2216 sal_Int32 nEOContent = 0;
2217 for ( const auto& rValue : rOptions)
2218 {
2219 if ( rValue.Name == "PrintRange" )
2220 {
2221 rValue.Value >>= nContent;
2222 }
2223 else if ( rValue.Name == "EvenOdd" )
2224 {
2225 rValue.Value >>= nEOContent;
2226 }
2227 }
2228
2229 MultiSelection aPage;
2230 aPage.SetTotalRange( Range(0,RANGE_MAX) );
2231
2232 bool bOddOrEven = (nContent == 0 && nEOContent == 1) || (nContent == 0 && nEOContent == 2); // even pages or odd pages
2233 // tdf#127682 when odd/even allow nRenderer of 0 even when maValidPages is empty
2234 // to allow PrinterController::abortJob to spool an empty page as part of
2235 // its abort procedure
2236 if (bOddOrEven && !maValidPages.empty())
2237 aPage.Select( maValidPages.at( nRenderer ) );
2238 else
2239 aPage.Select( nRenderer+1 );
2240
2241 tools::Long nDisplayStart = pPrintFuncCache->GetDisplayStart( nTab );
2242 tools::Long nTabStart = pPrintFuncCache->GetTabStart( nTab );
2243
2244 vcl::PDFExtOutDevData* pPDFData = dynamic_cast< vcl::PDFExtOutDevData* >(pDev->GetExtOutDevData() );
2245 if ( nRenderer == nTabStart )
2246 {
2247 if (pPDFData)
2248 {
2249 css::lang::Locale const docLocale(Application::GetSettings().GetLanguageTag().getLocale());
2250 pPDFData->SetDocumentLocale(docLocale);
2251 }
2252
2253 // first page of a sheet: add outline item for the sheet name
2254
2255 if ( pPDFData && pPDFData->GetIsExportBookmarks() )
2256 {
2257 // the sheet starts at the top of the page
2258 tools::Rectangle aArea( pDev->PixelToLogic( tools::Rectangle( 0,0,0,0 ) ) );
2259 sal_Int32 nDestID = pPDFData->CreateDest( aArea );
2260 OUString aTabName;
2261 rDoc.GetName( nTab, aTabName );
2262 // top-level
2263 pPDFData->CreateOutlineItem( -1/*nParent*/, aTabName, nDestID );
2264 }
2265 // #i56629# add the named destination stuff
2266 if( pPDFData && pPDFData->GetIsExportNamedDestinations() )
2267 {
2268 tools::Rectangle aArea( pDev->PixelToLogic( tools::Rectangle( 0,0,0,0 ) ) );
2269 OUString aTabName;
2270 rDoc.GetName( nTab, aTabName );
2271 //need the PDF page number here
2272 pPDFData->CreateNamedDest( aTabName, aArea );
2273 }
2274 }
2275
2276 (void)pPrintFunc->DoPrint( aPage, nTabStart, nDisplayStart, true, nullptr );
2277
2278 if (!m_pPrintState)
2279 {
2280 m_pPrintState.reset(new ScPrintState());
2281 pPrintFunc->GetPrintState(*m_pPrintState, true);
2282 }
2283
2284 // resolve the hyperlinks for PDF export
2285
2286 if ( !pPDFData || pPDFData->GetBookmarks().empty() )
2287 return;
2288
2289 // iterate over the hyperlinks that were output for this page
2290
2291 std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFData->GetBookmarks();
2292 for ( const auto& rBookmark : rBookmarks )
2293 {
2294 OUString aBookmark = rBookmark.aBookmark;
2295 if ( aBookmark.toChar() == '#' )
2296 {
2297 // try to resolve internal link
2298
2299 OUString aTarget( aBookmark.copy( 1 ) );
2300
2301 ScRange aTargetRange;
2302 tools::Rectangle aTargetRect; // 1/100th mm
2303 bool bIsSheet = false;
2304 bool bValid = lcl_ParseTarget( aTarget, aTargetRange, aTargetRect, bIsSheet, rDoc, nTab );
2305
2306 if ( bValid )
2307 {
2308 sal_Int32 nPage = -1;
2309 tools::Rectangle aArea;
2310 if ( bIsSheet )
2311 {
2312 // Get first page for sheet (if nothing from that sheet is printed,
2313 // this page can show a different sheet)
2314 nPage = pPrintFuncCache->GetTabStart( aTargetRange.aStart.Tab() );
2315 aArea = pDev->PixelToLogic( tools::Rectangle( 0,0,0,0 ) );
2316 }
2317 else
2318 {
2319 pPrintFuncCache->InitLocations( aMark, pDev ); // does nothing if already initialized
2320
2321 ScPrintPageLocation aLocation;
2322 if ( pPrintFuncCache->FindLocation( aTargetRange.aStart, aLocation ) )
2323 {
2324 nPage = aLocation.nPage;
2325
2326 // get the rectangle of the page's cell range in 1/100th mm
2327 ScRange aLocRange = aLocation.aCellRange;
2328 tools::Rectangle aLocationMM = rDoc.GetMMRect(
2329 aLocRange.aStart.Col(), aLocRange.aStart.Row(),
2330 aLocRange.aEnd.Col(), aLocRange.aEnd.Row(),
2331 aLocRange.aStart.Tab() );
2332 tools::Rectangle aLocationPixel = aLocation.aRectangle;
2333
2334 // Scale and move the target rectangle from aLocationMM to aLocationPixel,
2335 // to get the target rectangle in pixels.
2336 assert(aLocationPixel.GetWidth() != 0 && aLocationPixel.GetHeight() != 0);
2337
2338 Fraction aScaleX( aLocationPixel.GetWidth(), aLocationMM.GetWidth() );
2339 Fraction aScaleY( aLocationPixel.GetHeight(), aLocationMM.GetHeight() );
2340
2341 tools::Long nX1 = aLocationPixel.Left() + static_cast<tools::Long>( Fraction( aTargetRect.Left() - aLocationMM.Left(), 1 ) * aScaleX );
2342 tools::Long nX2 = aLocationPixel.Left() + static_cast<tools::Long>( Fraction( aTargetRect.Right() - aLocationMM.Left(), 1 ) * aScaleX );
2343 tools::Long nY1 = aLocationPixel.Top() + static_cast<tools::Long>( Fraction( aTargetRect.Top() - aLocationMM.Top(), 1 ) * aScaleY );
2344 tools::Long nY2 = aLocationPixel.Top() + static_cast<tools::Long>( Fraction( aTargetRect.Bottom() - aLocationMM.Top(), 1 ) * aScaleY );
2345
2346 if ( nX1 > aLocationPixel.Right() ) nX1 = aLocationPixel.Right();
2347 if ( nX2 > aLocationPixel.Right() ) nX2 = aLocationPixel.Right();
2348 if ( nY1 > aLocationPixel.Bottom() ) nY1 = aLocationPixel.Bottom();
2349 if ( nY2 > aLocationPixel.Bottom() ) nY2 = aLocationPixel.Bottom();
2350
2351 // The link target area is interpreted using the device's MapMode at
2352 // the time of the CreateDest call, so PixelToLogic can be used here,
2353 // regardless of the MapMode that is actually selected.
2354 aArea = pDev->PixelToLogic( tools::Rectangle( nX1, nY1, nX2, nY2 ) );
2355 }
2356 }
2357
2358 if ( nPage >= 0 )
2359 pPDFData->SetLinkDest( rBookmark.nLinkId, pPDFData->CreateDest( aArea, nPage ) );
2360 }
2361 }
2362 else
2363 {
2364 // external link, use as-is
2365 pPDFData->SetLinkURL( rBookmark.nLinkId, aBookmark );
2366 }
2367 }
2368 rBookmarks.clear();
2369}
2370
2371// XLinkTargetSupplier
2372
2373uno::Reference<container::XNameAccess> SAL_CALL ScModelObj::getLinks()
2374{
2375 SolarMutexGuard aGuard;
2376 if (pDocShell)
2377 return new ScLinkTargetTypesObj(pDocShell);
2378 return nullptr;
2379}
2380
2381// XActionLockable
2382
2384{
2385 SolarMutexGuard aGuard;
2386 bool bLocked = false;
2387 if (pDocShell)
2388 bLocked = ( pDocShell->GetLockCount() != 0 );
2389 return bLocked;
2390}
2391
2393{
2394 SolarMutexGuard aGuard;
2395 if (pDocShell)
2397}
2398
2400{
2401 SolarMutexGuard aGuard;
2402 if (pDocShell)
2404}
2405
2406void SAL_CALL ScModelObj::setActionLocks( sal_Int16 nLock )
2407{
2408 SolarMutexGuard aGuard;
2409 if (pDocShell)
2410 pDocShell->SetLockCount(nLock);
2411}
2412
2414{
2415 SolarMutexGuard aGuard;
2416 sal_uInt16 nRet = 0;
2417 if (pDocShell)
2418 {
2419 nRet = pDocShell->GetLockCount();
2421 }
2422 return nRet;
2423}
2424
2426{
2427 SolarMutexGuard aGuard;
2429 if (pDocShell)
2431}
2432
2434{
2435 SolarMutexGuard aGuard;
2437 {
2439 if (pDocShell)
2441 }
2442}
2443
2444// XCalculate
2445
2447{
2448 SolarMutexGuard aGuard;
2449 if (pDocShell)
2450 {
2451 comphelper::ProfileZone aZone("calculate");
2452 pDocShell->DoRecalc(true);
2453 }
2454 else
2455 {
2456 OSL_FAIL("no DocShell");
2457 }
2458}
2459
2461{
2462 SolarMutexGuard aGuard;
2463 if (pDocShell)
2464 {
2465 comphelper::ProfileZone aZone("calculateAll");
2467 }
2468 else
2469 {
2470 OSL_FAIL("no DocShell");
2471 }
2472}
2473
2475{
2476 SolarMutexGuard aGuard;
2477 if (pDocShell)
2478 return pDocShell->GetDocument().GetAutoCalc();
2479
2480 OSL_FAIL("no DocShell");
2481 return false;
2482}
2483
2485{
2486 bool bEnabled(bEnabledIn);
2487 SolarMutexGuard aGuard;
2488 if (pDocShell)
2489 {
2490 ScDocument& rDoc = pDocShell->GetDocument();
2491 if ( rDoc.GetAutoCalc() != bEnabled )
2492 {
2493 rDoc.SetAutoCalc( bEnabled );
2495 }
2496 }
2497 else
2498 {
2499 OSL_FAIL("no DocShell");
2500 }
2501}
2502
2503// XProtectable
2504
2505void SAL_CALL ScModelObj::protect( const OUString& aPassword )
2506{
2507 SolarMutexGuard aGuard;
2508 // #i108245# if already protected, don't change anything
2510 {
2511 pDocShell->GetDocFunc().Protect( TABLEID_DOC, aPassword );
2512 }
2513}
2514
2515void SAL_CALL ScModelObj::unprotect( const OUString& aPassword )
2516{
2517 SolarMutexGuard aGuard;
2518 if (pDocShell)
2519 {
2520 bool bDone = pDocShell->GetDocFunc().Unprotect( TABLEID_DOC, aPassword, true );
2521 if (!bDone)
2522 throw lang::IllegalArgumentException();
2523 }
2524}
2525
2527{
2528 SolarMutexGuard aGuard;
2529 if (pDocShell)
2531
2532 OSL_FAIL("no DocShell");
2533 return false;
2534}
2535
2536// XDrawPagesSupplier
2537
2538uno::Reference<drawing::XDrawPages> SAL_CALL ScModelObj::getDrawPages()
2539{
2540 SolarMutexGuard aGuard;
2541 if (pDocShell)
2542 return new ScDrawPagesObj(pDocShell);
2543
2544 OSL_FAIL("no DocShell");
2545 return nullptr;
2546}
2547
2548// XGoalSeek
2549
2550sheet::GoalResult SAL_CALL ScModelObj::seekGoal(
2551 const table::CellAddress& aFormulaPosition,
2552 const table::CellAddress& aVariablePosition,
2553 const OUString& aGoalValue )
2554{
2555 SolarMutexGuard aGuard;
2556 sheet::GoalResult aResult;
2557 aResult.Divergence = DBL_MAX; // not found
2558 if (pDocShell)
2559 {
2561 ScDocument& rDoc = pDocShell->GetDocument();
2562 double fValue = 0.0;
2563 bool bFound = rDoc.Solver(
2564 static_cast<SCCOL>(aFormulaPosition.Column), static_cast<SCROW>(aFormulaPosition.Row), aFormulaPosition.Sheet,
2565 static_cast<SCCOL>(aVariablePosition.Column), static_cast<SCROW>(aVariablePosition.Row), aVariablePosition.Sheet,
2566 aGoalValue, fValue );
2567 aResult.Result = fValue;
2568 if (bFound)
2569 aResult.Divergence = 0.0;
2570 }
2571 return aResult;
2572}
2573
2574// XConsolidatable
2575
2576uno::Reference<sheet::XConsolidationDescriptor> SAL_CALL ScModelObj::createConsolidationDescriptor(
2577 sal_Bool bEmpty )
2578{
2579 SolarMutexGuard aGuard;
2581 if ( pDocShell && !bEmpty )
2582 {
2583 ScDocument& rDoc = pDocShell->GetDocument();
2584 const ScConsolidateParam* pParam = rDoc.GetConsolidateDlgData();
2585 if (pParam)
2586 pNew->SetParam( *pParam );
2587 }
2588 return pNew;
2589}
2590
2592 const uno::Reference<sheet::XConsolidationDescriptor>& xDescriptor )
2593{
2594 SolarMutexGuard aGuard;
2595 // in theory, this could also be a different object, so use only
2596 // public XConsolidationDescriptor interface to copy the data into
2597 // ScConsolidationDescriptor object
2599
2601 xImpl->setFunction( xDescriptor->getFunction() );
2602 xImpl->setSources( xDescriptor->getSources() );
2603 xImpl->setStartOutputPosition( xDescriptor->getStartOutputPosition() );
2604 xImpl->setUseColumnHeaders( xDescriptor->getUseColumnHeaders() );
2605 xImpl->setUseRowHeaders( xDescriptor->getUseRowHeaders() );
2606 xImpl->setInsertLinks( xDescriptor->getInsertLinks() );
2607
2608 if (pDocShell)
2609 {
2610 const ScConsolidateParam& rParam = xImpl->GetParam();
2611 pDocShell->DoConsolidate( rParam );
2612 pDocShell->GetDocument().SetConsolidateDlgData( std::unique_ptr<ScConsolidateParam>(new ScConsolidateParam(rParam)) );
2613 }
2614}
2615
2616// XDocumentAuditing
2617
2619{
2620 SolarMutexGuard aGuard;
2621 if (pDocShell)
2623}
2624
2625// XViewDataSupplier
2626uno::Reference< container::XIndexAccess > SAL_CALL ScModelObj::getViewData( )
2627{
2628 uno::Reference < container::XIndexAccess > xRet( SfxBaseModel::getViewData() );
2629
2630 if( !xRet.is() )
2631 {
2632 SolarMutexGuard aGuard;
2633 if (pDocShell && pDocShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED)
2634 {
2636 xRet = xCont;
2637
2638 OUString sName;
2640 SCCOL nPosLeft = pDocShell->GetDocument().GetPosLeft();
2641 SCROW nPosTop = pDocShell->GetDocument().GetPosTop();
2642 uno::Sequence< beans::PropertyValue > aSeq{
2646 };
2647 xCont->insertByIndex( 0, uno::Any( aSeq ) );
2648 }
2649 }
2650
2651 return xRet;
2652}
2653
2654// XPropertySet (Doc-Options)
2656
2657uno::Reference<beans::XPropertySetInfo> SAL_CALL ScModelObj::getPropertySetInfo()
2658{
2659 SolarMutexGuard aGuard;
2660 static uno::Reference<beans::XPropertySetInfo> aRef(
2662 return aRef;
2663}
2664
2666 const OUString& aPropertyName, const uno::Any& aValue )
2667{
2668 SolarMutexGuard aGuard;
2669
2670 if (!pDocShell)
2671 return;
2672
2673 ScDocument& rDoc = pDocShell->GetDocument();
2674 const ScDocOptions& rOldOpt = rDoc.GetDocOptions();
2675 ScDocOptions aNewOpt = rOldOpt;
2676 // Don't recalculate while loading XML, when the formula text is stored
2677 // Recalculation after loading is handled separately.
2678 bool bHardRecalc = !rDoc.IsImportingXML();
2679
2680 bool bOpt = ScDocOptionsHelper::setPropertyValue( aNewOpt, aPropSet.getPropertyMap(), aPropertyName, aValue );
2681 if (bOpt)
2682 {
2683 // done...
2684 if ( aPropertyName == SC_UNO_IGNORECASE ||
2685 aPropertyName == SC_UNONAME_REGEXP ||
2686 aPropertyName == SC_UNONAME_WILDCARDS ||
2687 aPropertyName == SC_UNO_LOOKUPLABELS )
2688 bHardRecalc = false;
2689 }
2690 else if ( aPropertyName == SC_UNONAME_CLOCAL )
2691 {
2692 lang::Locale aLocale;
2693 if ( aValue >>= aLocale )
2694 {
2695 LanguageType eLatin, eCjk, eCtl;
2696 rDoc.GetLanguage( eLatin, eCjk, eCtl );
2697 eLatin = ScUnoConversion::GetLanguage(aLocale);
2698 rDoc.SetLanguage( eLatin, eCjk, eCtl );
2699 }
2700 }
2701 else if ( aPropertyName == SC_UNO_CODENAME )
2702 {
2703 OUString sCodeName;
2704 if ( aValue >>= sCodeName )
2705 rDoc.SetCodeName( sCodeName );
2706 }
2707 else if ( aPropertyName == SC_UNO_CJK_CLOCAL )
2708 {
2709 lang::Locale aLocale;
2710 if ( aValue >>= aLocale )
2711 {
2712 LanguageType eLatin, eCjk, eCtl;
2713 rDoc.GetLanguage( eLatin, eCjk, eCtl );
2714 eCjk = ScUnoConversion::GetLanguage(aLocale);
2715 rDoc.SetLanguage( eLatin, eCjk, eCtl );
2716 }
2717 }
2718 else if ( aPropertyName == SC_UNO_CTL_CLOCAL )
2719 {
2720 lang::Locale aLocale;
2721 if ( aValue >>= aLocale )
2722 {
2723 LanguageType eLatin, eCjk, eCtl;
2724 rDoc.GetLanguage( eLatin, eCjk, eCtl );
2725 eCtl = ScUnoConversion::GetLanguage(aLocale);
2726 rDoc.SetLanguage( eLatin, eCjk, eCtl );
2727 }
2728 }
2729 else if ( aPropertyName == SC_UNO_APPLYFMDES )
2730 {
2731 // model is created if not there
2732 ScDrawLayer* pModel = pDocShell->MakeDrawLayer();
2734
2735 SfxBindings* pBindings = pDocShell->GetViewBindings();
2736 if (pBindings)
2737 pBindings->Invalidate( SID_FM_OPEN_READONLY );
2738 }
2739 else if ( aPropertyName == SC_UNO_AUTOCONTFOC )
2740 {
2741 // model is created if not there
2742 ScDrawLayer* pModel = pDocShell->MakeDrawLayer();
2744
2745 SfxBindings* pBindings = pDocShell->GetViewBindings();
2746 if (pBindings)
2747 pBindings->Invalidate( SID_FM_AUTOCONTROLFOCUS );
2748 }
2749 else if ( aPropertyName == SC_UNO_ISLOADED )
2750 {
2752 }
2753 else if ( aPropertyName == SC_UNO_ISUNDOENABLED )
2754 {
2755 bool bUndoEnabled = ScUnoHelpFunctions::GetBoolFromAny( aValue );
2756 rDoc.EnableUndo( bUndoEnabled );
2758 bUndoEnabled
2759 ? officecfg::Office::Common::Undo::Steps::get() : 0);
2760 }
2761 else if ( aPropertyName == SC_UNO_RECORDCHANGES )
2762 {
2763 bool bRecordChangesEnabled = ScUnoHelpFunctions::GetBoolFromAny( aValue );
2764
2765 bool bChangeAllowed = true;
2766 if (!bRecordChangesEnabled)
2767 bChangeAllowed = !pDocShell->HasChangeRecordProtection();
2768
2769 if (bChangeAllowed)
2770 pDocShell->SetChangeRecording(bRecordChangesEnabled);
2771 }
2772 else if ( aPropertyName == SC_UNO_ISADJUSTHEIGHTENABLED )
2773 {
2775 rDoc.UnlockAdjustHeight();
2776 else
2777 rDoc.LockAdjustHeight();
2778 }
2779 else if ( aPropertyName == SC_UNO_ISEXECUTELINKENABLED )
2780 {
2782 }
2783 else if ( aPropertyName == SC_UNO_ISCHANGEREADONLYENABLED )
2784 {
2786 }
2787 else if ( aPropertyName == "BuildId" )
2788 {
2789 aValue >>= maBuildId;
2790 }
2791 else if ( aPropertyName == "SavedObject" ) // set from chart after saving
2792 {
2793 OUString aObjName;
2794 aValue >>= aObjName;
2795 if ( !aObjName.isEmpty() )
2796 rDoc.RestoreChartListener( aObjName );
2797 }
2798 else if ( aPropertyName == SC_UNO_INTEROPGRABBAG )
2799 {
2800 setGrabBagItem(aValue);
2801 }
2802
2803 if ( aNewOpt != rOldOpt )
2804 {
2805 rDoc.SetDocOptions( aNewOpt );
2807 if ( bHardRecalc )
2810 }
2811}
2812
2813uno::Any SAL_CALL ScModelObj::getPropertyValue( const OUString& aPropertyName )
2814{
2815 SolarMutexGuard aGuard;
2816 uno::Any aRet;
2817
2818 if (pDocShell)
2819 {
2820 ScDocument& rDoc = pDocShell->GetDocument();
2821 const ScDocOptions& rOpt = rDoc.GetDocOptions();
2822 aRet = ScDocOptionsHelper::getPropertyValue( rOpt, aPropSet.getPropertyMap(), aPropertyName );
2823 if ( aRet.hasValue() )
2824 {
2825 // done...
2826 }
2827 else if ( aPropertyName == SC_UNONAME_CLOCAL )
2828 {
2829 LanguageType eLatin, eCjk, eCtl;
2830 rDoc.GetLanguage( eLatin, eCjk, eCtl );
2831
2832 lang::Locale aLocale;
2833 ScUnoConversion::FillLocale( aLocale, eLatin );
2834 aRet <<= aLocale;
2835 }
2836 else if ( aPropertyName == SC_UNO_CODENAME )
2837 {
2838 aRet <<= rDoc.GetCodeName();
2839 }
2840
2841 else if ( aPropertyName == SC_UNO_CJK_CLOCAL )
2842 {
2843 LanguageType eLatin, eCjk, eCtl;
2844 rDoc.GetLanguage( eLatin, eCjk, eCtl );
2845
2846 lang::Locale aLocale;
2847 ScUnoConversion::FillLocale( aLocale, eCjk );
2848 aRet <<= aLocale;
2849 }
2850 else if ( aPropertyName == SC_UNO_CTL_CLOCAL )
2851 {
2852 LanguageType eLatin, eCjk, eCtl;
2853 rDoc.GetLanguage( eLatin, eCjk, eCtl );
2854
2855 lang::Locale aLocale;
2856 ScUnoConversion::FillLocale( aLocale, eCtl );
2857 aRet <<= aLocale;
2858 }
2859 else if ( aPropertyName == SC_UNO_NAMEDRANGES )
2860 {
2861 aRet <<= uno::Reference<sheet::XNamedRanges>(new ScGlobalNamedRangesObj( pDocShell ));
2862 }
2863 else if ( aPropertyName == SC_UNO_DATABASERNG )
2864 {
2865 aRet <<= uno::Reference<sheet::XDatabaseRanges>(new ScDatabaseRangesObj( pDocShell ));
2866 }
2867 else if ( aPropertyName == SC_UNO_UNNAMEDDBRNG )
2868 {
2869 aRet <<= uno::Reference<sheet::XUnnamedDatabaseRanges>(new ScUnnamedDatabaseRangesObj(pDocShell));
2870 }
2871 else if ( aPropertyName == SC_UNO_COLLABELRNG )
2872 {
2873 aRet <<= uno::Reference<sheet::XLabelRanges>(new ScLabelRangesObj( pDocShell, true ));
2874 }
2875 else if ( aPropertyName == SC_UNO_ROWLABELRNG )
2876 {
2877 aRet <<= uno::Reference<sheet::XLabelRanges>(new ScLabelRangesObj( pDocShell, false ));
2878 }
2879 else if ( aPropertyName == SC_UNO_AREALINKS )
2880 {
2881 aRet <<= uno::Reference<sheet::XAreaLinks>(new ScAreaLinksObj( pDocShell ));
2882 }
2883 else if ( aPropertyName == SC_UNO_DDELINKS )
2884 {
2885 aRet <<= uno::Reference<container::XNameAccess>(new ScDDELinksObj( pDocShell ));
2886 }
2887 else if ( aPropertyName == SC_UNO_EXTERNALDOCLINKS )
2888 {
2889 aRet <<= uno::Reference<sheet::XExternalDocLinks>(new ScExternalDocLinksObj(pDocShell));
2890 }
2891 else if ( aPropertyName == SC_UNO_SHEETLINKS )
2892 {
2893 aRet <<= uno::Reference<container::XNameAccess>(new ScSheetLinksObj( pDocShell ));
2894 }
2895 else if ( aPropertyName == SC_UNO_APPLYFMDES )
2896 {
2897 // default for no model is TRUE
2898 ScDrawLayer* pModel = rDoc.GetDrawLayer();
2899 bool bOpenInDesign = pModel == nullptr || pModel->GetOpenInDesignMode();
2900 aRet <<= bOpenInDesign;
2901 }
2902 else if ( aPropertyName == SC_UNO_AUTOCONTFOC )
2903 {
2904 // default for no model is FALSE
2905 ScDrawLayer* pModel = rDoc.GetDrawLayer();
2906 bool bAutoControlFocus = pModel && pModel->GetAutoControlFocus();
2907 aRet <<= bAutoControlFocus;
2908 }
2909 else if ( aPropertyName == SC_UNO_FORBIDDEN )
2910 {
2911 aRet <<= uno::Reference<i18n::XForbiddenCharacters>(new ScForbiddenCharsObj( pDocShell ));
2912 }
2913 else if ( aPropertyName == SC_UNO_HASDRAWPAGES )
2914 {
2915 aRet <<= (pDocShell->GetDocument().GetDrawLayer() != nullptr);
2916 }
2917 else if ( aPropertyName == SC_UNO_BASICLIBRARIES )
2918 {
2919 aRet <<= pDocShell->GetBasicContainer();
2920 }
2921 else if ( aPropertyName == SC_UNO_DIALOGLIBRARIES )
2922 {
2923 aRet <<= pDocShell->GetDialogContainer();
2924 }
2925 else if ( aPropertyName == SC_UNO_VBAGLOBNAME )
2926 {
2927 /* #i111553# This property provides the name of the constant that
2928 will be used to store this model in the global Basic manager.
2929 That constant will be equivalent to 'ThisComponent' but for
2930 each application, so e.g. a 'ThisExcelDoc' and a 'ThisWordDoc'
2931 constant can co-exist, as required by VBA. */
2932 aRet <<= OUString( "ThisExcelDoc" );
2933 }
2934 else if ( aPropertyName == SC_UNO_RUNTIMEUID )
2935 {
2936 aRet <<= getRuntimeUID();
2937 }
2938 else if ( aPropertyName == SC_UNO_HASVALIDSIGNATURES )
2939 {
2940 aRet <<= hasValidSignatures();
2941 }
2942 else if ( aPropertyName == SC_UNO_ISLOADED )
2943 {
2944 aRet <<= !pDocShell->IsEmpty();
2945 }
2946 else if ( aPropertyName == SC_UNO_ISUNDOENABLED )
2947 {
2948 aRet <<= rDoc.IsUndoEnabled();
2949 }
2950 else if ( aPropertyName == SC_UNO_RECORDCHANGES )
2951 {
2952 aRet <<= pDocShell->IsChangeRecording();
2953 }
2954 else if ( aPropertyName == SC_UNO_ISRECORDCHANGESPROTECTED )
2955 {
2957 }
2958 else if ( aPropertyName == SC_UNO_ISADJUSTHEIGHTENABLED )
2959 {
2960 aRet <<= !( rDoc.IsAdjustHeightLocked() );
2961 }
2962 else if ( aPropertyName == SC_UNO_ISEXECUTELINKENABLED )
2963 {
2964 aRet <<= rDoc.IsExecuteLinkEnabled();
2965 }
2966 else if ( aPropertyName == SC_UNO_ISCHANGEREADONLYENABLED )
2967 {
2968 aRet <<= rDoc.IsChangeReadOnlyEnabled();
2969 }
2970 else if ( aPropertyName == SC_UNO_REFERENCEDEVICE )
2971 {
2973 pXDev->SetOutputDevice( rDoc.GetRefDevice() );
2974 aRet <<= uno::Reference< awt::XDevice >( pXDev );
2975 }
2976 else if ( aPropertyName == "BuildId" )
2977 {
2978 aRet <<= maBuildId;
2979 }
2980 else if ( aPropertyName == "InternalDocument" )
2981 {
2982 aRet <<= (pDocShell->GetCreateMode() == SfxObjectCreateMode::INTERNAL);
2983 }
2984 else if ( aPropertyName == SC_UNO_INTEROPGRABBAG )
2985 {
2986 getGrabBagItem(aRet);
2987 }
2988 }
2989
2990 return aRet;
2991}
2992
2994
2995// XMultiServiceFactory
2996
2997css::uno::Reference<css::uno::XInterface> ScModelObj::create(
2998 OUString const & aServiceSpecifier,
2999 css::uno::Sequence<css::uno::Any> const * arguments)
3000{
3001 using ServiceType = ScServiceProvider::Type;
3002
3003 uno::Reference<uno::XInterface> xRet;
3004 ServiceType nType = ScServiceProvider::GetProviderType(aServiceSpecifier);
3005 if ( nType != ServiceType::INVALID )
3006 {
3007 // drawing layer tables must be kept as long as the model is alive
3008 // return stored instance if already set
3009 switch ( nType )
3010 {
3011 case ServiceType::GRADTAB: xRet.set(xDrawGradTab); break;
3012 case ServiceType::HATCHTAB: xRet.set(xDrawHatchTab); break;
3013 case ServiceType::BITMAPTAB: xRet.set(xDrawBitmapTab); break;
3014 case ServiceType::TRGRADTAB: xRet.set(xDrawTrGradTab); break;
3015 case ServiceType::MARKERTAB: xRet.set(xDrawMarkerTab); break;
3016 case ServiceType::DASHTAB: xRet.set(xDrawDashTab); break;
3017 case ServiceType::CHDATAPROV: xRet.set(xChartDataProv); break;
3018 case ServiceType::VBAOBJECTPROVIDER: xRet.set(xObjProvider); break;
3019 default: break;
3020 }
3021
3022 // #i64497# If a chart is in a temporary document during clipboard paste,
3023 // there should be no data provider, so that own data is used
3024 bool bCreate =
3025 ( nType != ServiceType::CHDATAPROV ||
3026 ( pDocShell->GetCreateMode() != SfxObjectCreateMode::INTERNAL ));
3027 // this should never happen, i.e. the temporary document should never be
3028 // loaded, because this unlinks the data
3029 assert(bCreate);
3030
3031 if ( !xRet.is() && bCreate )
3032 {
3033 xRet.set(ScServiceProvider::MakeInstance( nType, pDocShell ));
3034
3035 // store created instance
3036 switch ( nType )
3037 {
3038 case ServiceType::GRADTAB: xDrawGradTab.set(xRet); break;
3039 case ServiceType::HATCHTAB: xDrawHatchTab.set(xRet); break;
3040 case ServiceType::BITMAPTAB: xDrawBitmapTab.set(xRet); break;
3041 case ServiceType::TRGRADTAB: xDrawTrGradTab.set(xRet); break;
3042 case ServiceType::MARKERTAB: xDrawMarkerTab.set(xRet); break;
3043 case ServiceType::DASHTAB: xDrawDashTab.set(xRet); break;
3044 case ServiceType::CHDATAPROV: xChartDataProv.set(xRet); break;
3045 case ServiceType::VBAOBJECTPROVIDER: xObjProvider.set(xRet); break;
3046 default: break;
3047 }
3048 }
3049 }
3050 else
3051 {
3052 // we offload everything we don't know to SvxFmMSFactory,
3053 // it'll throw exception if this isn't okay ...
3054
3055 try
3056 {
3057 xRet = arguments == nullptr
3058 ? SvxFmMSFactory::createInstance(aServiceSpecifier)
3060 aServiceSpecifier, *arguments);
3061 // extra block to force deletion of the temporary before ScShapeObj ctor (setDelegator)
3062 }
3063 catch ( lang::ServiceNotRegisteredException & )
3064 {
3065 }
3066
3067 // if the drawing factory created a shape, a ScShapeObj has to be used
3068 // to support own properties like ImageMap:
3069
3070 uno::Reference<drawing::XShape> xShape( xRet, uno::UNO_QUERY );
3071 if ( xShape.is() )
3072 {
3073 xRet.clear(); // for aggregation, xShape must be the object's only ref
3074 new ScShapeObj( xShape ); // aggregates object and modifies xShape
3075 xRet.set(xShape);
3076 }
3077 }
3078 return xRet;
3079}
3080
3081uno::Reference<uno::XInterface> SAL_CALL ScModelObj::createInstance(
3082 const OUString& aServiceSpecifier )
3083{
3084 SolarMutexGuard aGuard;
3085 return create(aServiceSpecifier, nullptr);
3086}
3087
3088uno::Reference<uno::XInterface> SAL_CALL ScModelObj::createInstanceWithArguments(
3089 const OUString& ServiceSpecifier,
3090 const uno::Sequence<uno::Any>& aArgs )
3091{
3093
3094 SolarMutexGuard aGuard;
3095 uno::Reference<uno::XInterface> xInt(create(ServiceSpecifier, &aArgs));
3096
3097 if ( aArgs.hasElements() )
3098 {
3099 // used only for cell value binding so far - it can be initialized after creating
3100
3101 uno::Reference<lang::XInitialization> xInit( xInt, uno::UNO_QUERY );
3102 if ( xInit.is() )
3103 xInit->initialize( aArgs );
3104 }
3105
3106 return xInt;
3107}
3108
3109uno::Sequence<OUString> SAL_CALL ScModelObj::getAvailableServiceNames()
3110{
3111 SolarMutexGuard aGuard;
3112
3115}
3116
3117// XServiceInfo
3119{
3120 return "ScModelObj";
3121 /* // Matching the .component information:
3122 return OUString( "com.sun.star.comp.Calc.SpreadsheetDocument" );
3123 */
3124}
3125
3126sal_Bool SAL_CALL ScModelObj::supportsService( const OUString& rServiceName )
3127{
3128 return cppu::supportsService(this, rServiceName);
3129}
3130
3131uno::Sequence<OUString> SAL_CALL ScModelObj::getSupportedServiceNames()
3132{
3134}
3135
3136// XUnoTunnel
3137
3138sal_Int64 SAL_CALL ScModelObj::getSomething(
3139 const uno::Sequence<sal_Int8 >& rId )
3140{
3141 if ( comphelper::isUnoTunnelId<ScModelObj>(rId) )
3142 {
3143 return comphelper::getSomething_cast(this);
3144 }
3145
3146 if ( comphelper::isUnoTunnelId<SfxObjectShell>(rId) )
3147 {
3149 }
3150
3151 // aggregated number formats supplier has XUnoTunnel, too
3152 // interface from aggregated object must be obtained via queryAggregation
3153
3154 sal_Int64 nRet = SfxBaseModel::getSomething( rId );
3155 if ( nRet )
3156 return nRet;
3157
3158 if ( GetFormatter().is() )
3159 {
3160 const uno::Type& rTunnelType = cppu::UnoType<lang::XUnoTunnel>::get();
3161 uno::Any aNumTunnel(xNumberAgg->queryAggregation(rTunnelType));
3162 if(auto xTunnelAgg = o3tl::tryAccess<uno::Reference<lang::XUnoTunnel>>(
3163 aNumTunnel))
3164 {
3165 return (*xTunnelAgg)->getSomething( rId );
3166 }
3167 }
3168
3169 return 0;
3170}
3171
3172const uno::Sequence<sal_Int8>& ScModelObj::getUnoTunnelId()
3173{
3174 static const comphelper::UnoIdInit theScModelObjUnoTunnelId;
3175 return theScModelObjUnoTunnelId.getSeq();
3176}
3177
3178// XChangesNotifier
3179
3180void ScModelObj::addChangesListener( const uno::Reference< util::XChangesListener >& aListener )
3181{
3182 SolarMutexGuard aGuard;
3183 maChangesListeners.addInterface( aListener );
3184}
3185
3186void ScModelObj::removeChangesListener( const uno::Reference< util::XChangesListener >& aListener )
3187{
3188 SolarMutexGuard aGuard;
3190}
3191
3193{
3194 if ( maChangesListeners.getLength() > 0 )
3195 return true;
3196
3197 // "change" event set in any sheet?
3199}
3200
3201namespace
3202{
3203
3204void lcl_dataAreaInvalidation(ScDocument& rDocument, ScModelObj* pModel,
3205 const ScRangeList& rRanges,
3206 bool bInvalidateDataArea, bool bExtendDataArea)
3207{
3208 size_t nRangeCount = rRanges.size();
3209
3210 for ( size_t nIndex = 0; nIndex < nRangeCount; ++nIndex )
3211 {
3212 ScRange const & rRange = rRanges[ nIndex ];
3213 ScAddress const & rEnd = rRange.aEnd;
3214 SCTAB nTab = rEnd.Tab();
3215
3216 bool bAreaExtended = false;
3217
3218 if (bExtendDataArea)
3219 {
3220 const Size aCurrentDataArea = pModel->getDataArea( nTab );
3221
3222 SCCOL nLastCol = aCurrentDataArea.Width();
3223 SCROW nLastRow = aCurrentDataArea.Height();
3224
3225 bAreaExtended = rEnd.Col() > nLastCol || rEnd.Row() > nLastRow;
3226 }
3227
3228 bool bInvalidate = bAreaExtended || bInvalidateDataArea;
3229 if ( bInvalidate )
3230 {
3231 ScTable* pTab = rDocument.FetchTable( nTab );
3232 if ( pTab )
3233 pTab->InvalidateCellArea();
3234
3237 }
3238 }
3239}
3240
3241};
3242
3243void ScModelObj::NotifyChanges( const OUString& rOperation, const ScRangeList& rRanges,
3244 const uno::Sequence< beans::PropertyValue >& rProperties )
3245{
3246 OUString aOperation = rOperation;
3247 bool bIsDataAreaInvalidateType = aOperation == "data-area-invalidate";
3248 bool bIsDataAreaExtendType = aOperation == "data-area-extend";
3249
3250 bool bInvalidateDataArea = bIsDataAreaInvalidateType
3252 bool bExtendDataArea = bIsDataAreaExtendType || aOperation == "cell-change";
3253
3254 if ( pDocShell )
3255 {
3256 ScDocument& rDocument = pDocShell->GetDocument();
3257 lcl_dataAreaInvalidation(rDocument, this, rRanges, bInvalidateDataArea, bExtendDataArea);
3258
3259 // check if we were called only to update data area
3260 if (bIsDataAreaInvalidateType || bIsDataAreaExtendType)
3261 return;
3262
3263 // backward-compatibility Operation conversion
3264 // FIXME: make sure it can be passed
3265 if (rOperation == "delete-content" || rOperation == "undo"
3266 || rOperation == "redo" || rOperation == "paste")
3267 aOperation = "cell-change";
3268 }
3269
3270 if ( pDocShell && HasChangesListeners() )
3271 {
3272 util::ChangesEvent aEvent;
3273 aEvent.Source.set( static_cast< cppu::OWeakObject* >( this ) );
3274 aEvent.Base <<= aEvent.Source;
3275
3276 size_t nRangeCount = rRanges.size();
3277 aEvent.Changes.realloc( static_cast< sal_Int32 >( nRangeCount ) );
3278 auto pChanges = aEvent.Changes.getArray();
3279 for ( size_t nIndex = 0; nIndex < nRangeCount; ++nIndex )
3280 {
3281 uno::Reference< table::XCellRange > xRangeObj;
3282
3283 ScRange const & rRange = rRanges[ nIndex ];
3284 if ( rRange.aStart == rRange.aEnd )
3285 {
3286 xRangeObj.set( new ScCellObj( pDocShell, rRange.aStart ) );
3287 }
3288 else
3289 {
3290 xRangeObj.set( new ScCellRangeObj( pDocShell, rRange ) );
3291 }
3292
3293 util::ElementChange& rChange = pChanges[ static_cast< sal_Int32 >( nIndex ) ];
3294 rChange.Accessor <<= aOperation;
3295 rChange.Element <<= rProperties;
3296 rChange.ReplacedElement <<= xRangeObj;
3297 }
3298
3300 while ( aIter.hasMoreElements() )
3301 {
3302 try
3303 {
3304 aIter.next()->changesOccurred( aEvent );
3305 }
3306 catch( uno::Exception& )
3307 {
3308 }
3309 }
3310 }
3311
3312 // handle sheet events
3314 if ( !(aOperation == "cell-change" && pDocShell) )
3315 return;
3316
3318 aMarkData.MarkFromRangeList( rRanges, false );
3319 ScDocument& rDoc = pDocShell->GetDocument();
3320 SCTAB nTabCount = rDoc.GetTableCount();
3321 for (const SCTAB& nTab : aMarkData)
3322 {
3323 if (nTab >= nTabCount)
3324 break;
3325 const ScSheetEvents* pEvents = rDoc.GetSheetEvents(nTab);
3326 if (pEvents)
3327 {
3328 const OUString* pScript = pEvents->GetScript(ScSheetEventId::CHANGE);
3329 if (pScript)
3330 {
3331 ScRangeList aTabRanges; // collect ranges on this sheet
3332 size_t nRangeCount = rRanges.size();
3333 for ( size_t nIndex = 0; nIndex < nRangeCount; ++nIndex )
3334 {
3335 ScRange const & rRange = rRanges[ nIndex ];
3336 if ( rRange.aStart.Tab() == nTab )
3337 aTabRanges.push_back( rRange );
3338 }
3339 size_t nTabRangeCount = aTabRanges.size();
3340 if ( nTabRangeCount > 0 )
3341 {
3342 uno::Reference<uno::XInterface> xTarget;
3343 if ( nTabRangeCount == 1 )
3344 {
3345 ScRange const & rRange = aTabRanges[ 0 ];
3346 if ( rRange.aStart == rRange.aEnd )
3347 xTarget.set( static_cast<cppu::OWeakObject*>( new ScCellObj( pDocShell, rRange.aStart ) ) );
3348 else
3349 xTarget.set( static_cast<cppu::OWeakObject*>( new ScCellRangeObj( pDocShell, rRange ) ) );
3350 }
3351 else
3352 xTarget.set( static_cast<cppu::OWeakObject*>( new ScCellRangesObj( pDocShell, aTabRanges ) ) );
3353
3354 uno::Sequence<uno::Any> aParams{ uno::Any(xTarget) };
3355
3356 uno::Any aRet;
3357 uno::Sequence<sal_Int16> aOutArgsIndex;
3358 uno::Sequence<uno::Any> aOutArgs;
3359
3360 /*ErrCode eRet =*/ pDocShell->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs );
3361 }
3362 }
3363 }
3364 }
3365}
3366
3368{
3369 if (!pDocShell)
3370 return;
3371
3372 ScDocument& rDoc = pDocShell->GetDocument();
3373 // don't call events before the document is visible
3374 // (might also set a flag on SfxEventHintId::LoadFinished and only disable while loading)
3375 if ( rDoc.IsDocVisible() )
3376 {
3377 SCTAB nTabCount = rDoc.GetTableCount();
3378 for (SCTAB nTab = 0; nTab < nTabCount; nTab++)
3379 {
3380 if (rDoc.HasCalcNotification(nTab))
3381 {
3382 if (const ScSheetEvents* pEvents = rDoc.GetSheetEvents( nTab ))
3383 {
3384 if (const OUString* pScript = pEvents->GetScript(ScSheetEventId::CALCULATE))
3385 {
3386 uno::Any aRet;
3387 uno::Sequence<uno::Any> aParams;
3388 uno::Sequence<sal_Int16> aOutArgsIndex;
3389 uno::Sequence<uno::Any> aOutArgs;
3390 pDocShell->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs );
3391 }
3392 }
3393
3394 try
3395 {
3396 uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( rDoc.GetVbaEventProcessor(), uno::UNO_SET_THROW );
3397 uno::Sequence< uno::Any > aArgs{ uno::Any(nTab) };
3398 xVbaEvents->processVbaEvent( ScSheetEvents::GetVbaSheetEventId( ScSheetEventId::CALCULATE ), aArgs );
3399 }
3400 catch( uno::Exception& )
3401 {
3402 }
3403 }
3404 }
3405 }
3407}
3408
3409// XOpenCLSelection
3410
3412{
3414}
3415
3417{
3418 if (ScCalcConfig::isOpenCLEnabled() == static_cast<bool>(bEnable))
3419 return;
3421 return;
3422
3423 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
3424 officecfg::Office::Common::Misc::UseOpenCL::set(bEnable, batch);
3425 batch->commit();
3426
3428 if (bEnable)
3429 aConfig.setOpenCLConfigToDefault();
3431
3432#if HAVE_FEATURE_OPENCL
3433 sc::FormulaGroupInterpreter::switchOpenCLDevice(u"", true);
3434#endif
3435
3436 ScDocument* pDoc = GetDocument();
3438
3439}
3440
3442{
3444 aConfig.mbOpenCLAutoSelect = true;
3446 ScFormulaOptions aOptions = SC_MOD()->GetFormulaOptions();
3447 aOptions.SetCalcConfig(aConfig);
3448 SC_MOD()->SetFormulaOptions(aOptions);
3449#if !HAVE_FEATURE_OPENCL
3450 (void) bForce;
3451#else
3452 sc::FormulaGroupInterpreter::switchOpenCLDevice(u"", true, bForce);
3453#endif
3454}
3455
3457{
3459 aConfig.mbOpenCLAutoSelect = false;
3461 ScFormulaOptions aOptions = SC_MOD()->GetFormulaOptions();
3462 aOptions.SetCalcConfig(aConfig);
3463 SC_MOD()->SetFormulaOptions(aOptions);
3464}
3465
3466void ScModelObj::selectOpenCLDevice( sal_Int32 nPlatform, sal_Int32 nDevice )
3467{
3468 if(nPlatform < 0 || nDevice < 0)
3469 throw uno::RuntimeException();
3470
3471#if !HAVE_FEATURE_OPENCL
3472 throw uno::RuntimeException();
3473#else
3474 std::vector<OpenCLPlatformInfo> aPlatformInfo;
3475 sc::FormulaGroupInterpreter::fillOpenCLInfo(aPlatformInfo);
3476 if(o3tl::make_unsigned(nPlatform) >= aPlatformInfo.size())
3477 throw uno::RuntimeException();
3478
3479 if(o3tl::make_unsigned(nDevice) >= aPlatformInfo[nPlatform].maDevices.size())
3480 throw uno::RuntimeException();
3481
3482 OUString aDeviceString = aPlatformInfo[nPlatform].maVendor + " " + aPlatformInfo[nPlatform].maDevices[nDevice].maName;
3483 sc::FormulaGroupInterpreter::switchOpenCLDevice(aDeviceString, false);
3484#endif
3485}
3486
3488{
3489#if !HAVE_FEATURE_OPENCL
3490 return -1;
3491#else
3492 sal_Int32 nPlatformId;
3493 sal_Int32 nDeviceId;
3494 sc::FormulaGroupInterpreter::getOpenCLDeviceInfo(nDeviceId, nPlatformId);
3495 return nPlatformId;
3496#endif
3497}
3498
3500{
3501#if !HAVE_FEATURE_OPENCL
3502 return -1;
3503#else
3504 sal_Int32 nPlatformId;
3505 sal_Int32 nDeviceId;
3506 sc::FormulaGroupInterpreter::getOpenCLDeviceInfo(nDeviceId, nPlatformId);
3507 return nDeviceId;
3508#endif
3509}
3510
3511uno::Sequence< sheet::opencl::OpenCLPlatform > ScModelObj::getOpenCLPlatforms()
3512{
3513#if !HAVE_FEATURE_OPENCL
3514 return uno::Sequence<sheet::opencl::OpenCLPlatform>();
3515#else
3516 std::vector<OpenCLPlatformInfo> aPlatformInfo;
3517 sc::FormulaGroupInterpreter::fillOpenCLInfo(aPlatformInfo);
3518
3519 uno::Sequence<sheet::opencl::OpenCLPlatform> aRet(aPlatformInfo.size());
3520 auto aRetRange = asNonConstRange(aRet);
3521 for(size_t i = 0; i < aPlatformInfo.size(); ++i)
3522 {
3523 aRetRange[i].Name = aPlatformInfo[i].maName;
3524 aRetRange[i].Vendor = aPlatformInfo[i].maVendor;
3525
3526 aRetRange[i].Devices.realloc(aPlatformInfo[i].maDevices.size());
3527 auto pDevices = aRetRange[i].Devices.getArray();
3528 for(size_t j = 0; j < aPlatformInfo[i].maDevices.size(); ++j)
3529 {
3530 const OpenCLDeviceInfo& rDevice = aPlatformInfo[i].maDevices[j];
3531 pDevices[j].Name = rDevice.maName;
3532 pDevices[j].Vendor = rDevice.maVendor;
3533 pDevices[j].Driver = rDevice.maDriver;
3534 }
3535 }
3536
3537 return aRet;
3538#endif
3539}
3540
3541namespace {
3542
3544void setOpcodeSubsetTest(bool bFlag)
3545{
3546 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
3547 officecfg::Office::Calc::Formula::Calculation::OpenCLSubsetOnly::set(bFlag, batch);
3548 batch->commit();
3549}
3550
3551}
3552
3554{
3555 setOpcodeSubsetTest(true);
3556}
3557
3559{
3560 setOpcodeSubsetTest(false);
3561}
3562
3564{
3565 return officecfg::Office::Calc::Formula::Calculation::OpenCLSubsetOnly::get();
3566}
3567
3569{
3570 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
3571 officecfg::Office::Calc::Formula::Calculation::OpenCLMinimumDataSize::set(number, batch);
3572 batch->commit();
3573}
3574
3576{
3577 return officecfg::Office::Calc::Formula::Calculation::OpenCLMinimumDataSize::get();
3578}
3579
3581 pDocShell( pDocSh )
3582{
3584}
3585
3587{
3589
3590 if (pDocShell)
3592}
3593
3595{
3596 // we don't care about update of references here
3597
3598 if ( rHint.GetId() == SfxHintId::Dying )
3599 {
3600 pDocShell = nullptr; // became invalid
3601 }
3602}
3603
3604uno::Reference<drawing::XDrawPage> ScDrawPagesObj::GetObjectByIndex_Impl(sal_Int32 nIndex) const
3605{
3606 if (pDocShell)
3607 {
3608 ScDrawLayer* pDrawLayer = pDocShell->MakeDrawLayer();
3609 OSL_ENSURE(pDrawLayer,"Cannot create Draw-Layer");
3610 if ( pDrawLayer && nIndex >= 0 && nIndex < pDocShell->GetDocument().GetTableCount() )
3611 {
3612 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nIndex));
3613 OSL_ENSURE(pPage,"Draw-Page not found");
3614 if (pPage)
3615 {
3616 return uno::Reference<drawing::XDrawPage> (pPage->getUnoPage(), uno::UNO_QUERY);
3617 }
3618 }
3619 }
3620 return nullptr;
3621}
3622
3623// XDrawPages
3624
3625uno::Reference<drawing::XDrawPage> SAL_CALL ScDrawPagesObj::insertNewByIndex( sal_Int32 nPos )
3626{
3627 SolarMutexGuard aGuard;
3628 uno::Reference<drawing::XDrawPage> xRet;
3629 if (pDocShell)
3630 {
3631 OUString aNewName;
3633 if ( pDocShell->GetDocFunc().InsertTable( static_cast<SCTAB>(nPos),
3634 aNewName, true, true ) )
3635 xRet.set(GetObjectByIndex_Impl( nPos ));
3636 }
3637 return xRet;
3638}
3639
3640void SAL_CALL ScDrawPagesObj::remove( const uno::Reference<drawing::XDrawPage>& xPage )
3641{
3642 SolarMutexGuard aGuard;
3643 SvxDrawPage* pImp = comphelper::getFromUnoTunnel<SvxDrawPage>( xPage );
3644 if ( pDocShell && pImp )
3645 {
3646 SdrPage* pPage = pImp->GetSdrPage();
3647 if (pPage)
3648 {
3649 SCTAB nPageNum = static_cast<SCTAB>(pPage->GetPageNum());
3650 pDocShell->GetDocFunc().DeleteTable( nPageNum, true );
3651 }
3652 }
3653}
3654
3655// XIndexAccess
3656
3657sal_Int32 SAL_CALL ScDrawPagesObj::getCount()
3658{
3659 SolarMutexGuard aGuard;
3660 if (pDocShell)
3662 return 0;
3663}
3664
3665uno::Any SAL_CALL ScDrawPagesObj::getByIndex( sal_Int32 nIndex )
3666{
3667 SolarMutexGuard aGuard;
3668 uno::Reference<drawing::XDrawPage> xPage(GetObjectByIndex_Impl(nIndex));
3669 if (!xPage.is())
3670 throw lang::IndexOutOfBoundsException();
3671
3672 return uno::Any(xPage);
3673}
3674
3676{
3678}
3679
3681{
3682 SolarMutexGuard aGuard;
3683 return ( getCount() != 0 );
3684}
3685
3687 pDocShell( pDocSh )
3688{
3690}
3691
3693{
3695
3696 if (pDocShell)
3698}
3699
3701{
3702 // we don't care about update of references here
3703
3704 if ( rHint.GetId() == SfxHintId::Dying )
3705 {
3706 pDocShell = nullptr; // became invalid
3707 }
3708}
3709
3710// XSpreadsheets
3711
3713{
3714 if ( pDocShell && nIndex >= 0 && nIndex < pDocShell->GetDocument().GetTableCount() )
3715 return new ScTableSheetObj( pDocShell, static_cast<SCTAB>(nIndex) );
3716
3717 return nullptr;
3718}
3719
3721{
3722 if (pDocShell)
3723 {
3724 SCTAB nIndex;
3726 return new ScTableSheetObj( pDocShell, nIndex );
3727 }
3728 return nullptr;
3729}
3730
3731void SAL_CALL ScTableSheetsObj::insertNewByName( const OUString& aName, sal_Int16 nPosition )
3732{
3733 SolarMutexGuard aGuard;
3734 bool bDone = false;
3735 if (pDocShell)
3736 {
3737 bDone = pDocShell->GetDocFunc().InsertTable( nPosition, aName, true, true );
3738 }
3739 if (!bDone)
3740 throw uno::RuntimeException(); // no other exceptions specified
3741}
3742
3743void SAL_CALL ScTableSheetsObj::moveByName( const OUString& aName, sal_Int16 nDestination )
3744{
3745 SolarMutexGuard aGuard;
3746 bool bDone = false;
3747 if (pDocShell)
3748 {
3749 SCTAB nSource;
3750 if ( pDocShell->GetDocument().GetTable( aName, nSource ) )
3751 bDone = pDocShell->MoveTable( nSource, nDestination, false, true );
3752 }
3753 if (!bDone)
3754 throw uno::RuntimeException(); // no other exceptions specified
3755}
3756
3757void SAL_CALL ScTableSheetsObj::copyByName( const OUString& aName,
3758 const OUString& aCopy, sal_Int16 nDestination )
3759{
3760 SolarMutexGuard aGuard;
3761 bool bDone = false;
3762 if (pDocShell)
3763 {
3764 SCTAB nSource;
3765 if ( pDocShell->GetDocument().GetTable( aName, nSource ) )
3766 {
3767 bDone = pDocShell->MoveTable( nSource, nDestination, true, true );
3768 if (bDone)
3769 {
3770 // #i92477# any index past the last sheet means "append" in MoveTable
3771 SCTAB nResultTab = static_cast<SCTAB>(nDestination);
3772 SCTAB nTabCount = pDocShell->GetDocument().GetTableCount(); // count after copying
3773 if (nResultTab >= nTabCount)
3774 nResultTab = nTabCount - 1;
3775
3776 bDone = pDocShell->GetDocFunc().RenameTable( nResultTab, aCopy,
3777 true, true );
3778 }
3779 }
3780 }
3781 if (!bDone)
3782 throw uno::RuntimeException(); // no other exceptions specified
3783}
3784
3785void SAL_CALL ScTableSheetsObj::insertByName( const OUString& aName, const uno::Any& aElement )
3786{
3787 SolarMutexGuard aGuard;
3788 bool bDone = false;
3789 bool bIllArg = false;
3790
3792
3793 if ( pDocShell )
3794 {
3795 uno::Reference<uno::XInterface> xInterface(aElement, uno::UNO_QUERY);
3796 if ( xInterface.is() )
3797 {
3798 ScTableSheetObj* pSheetObj = dynamic_cast<ScTableSheetObj*>( xInterface.get() );
3799 if ( pSheetObj && !pSheetObj->GetDocShell() ) // not inserted yet?
3800 {
3801 ScDocument& rDoc = pDocShell->GetDocument();
3802 SCTAB nDummy;
3803 if ( rDoc.GetTable( aName, nDummy ) )
3804 {
3805 // name already exists
3806 throw container::ElementExistException();
3807 }
3808 SCTAB nPosition = rDoc.GetTableCount();
3809 bDone = pDocShell->GetDocFunc().InsertTable( nPosition, aName,
3810 true, true );
3811 if (bDone)
3812 pSheetObj->InitInsertSheet( pDocShell, nPosition );
3813 // set document and new range in the object
3814 }
3815 else
3816 bIllArg = true;
3817 }
3818 else
3819 bIllArg = true;
3820 }
3821
3822 if (!bDone)
3823 {
3824 if (bIllArg)
3825 throw lang::IllegalArgumentException();
3826 else
3827 throw uno::RuntimeException(); // ElementExistException is handled above
3828 }
3829}
3830
3831void SAL_CALL ScTableSheetsObj::replaceByName( const OUString& aName, const uno::Any& aElement )
3832{
3833 SolarMutexGuard aGuard;
3834 bool bDone = false;
3835 bool bIllArg = false;
3836
3838
3839 if ( pDocShell )
3840 {
3841 uno::Reference<uno::XInterface> xInterface(aElement, uno::UNO_QUERY);
3842 if ( xInterface.is() )
3843 {
3844 ScTableSheetObj* pSheetObj = dynamic_cast<ScTableSheetObj*>( xInterface.get() );
3845 if ( pSheetObj && !pSheetObj->GetDocShell() ) // not inserted yet?
3846 {
3847 SCTAB nPosition;
3848 if ( !pDocShell->GetDocument().GetTable( aName, nPosition ) )
3849 {
3850 // not found
3851 throw container::NoSuchElementException();
3852 }
3853
3854 if ( pDocShell->GetDocFunc().DeleteTable( nPosition, true ) )
3855 {
3856 // InsertTable can't really go wrong now
3857 bDone = pDocShell->GetDocFunc().InsertTable( nPosition, aName, true, true );
3858 if (bDone)
3859 pSheetObj->InitInsertSheet( pDocShell, nPosition );
3860 }
3861
3862 }
3863 else
3864 bIllArg = true;
3865 }
3866 else
3867 bIllArg = true;
3868 }
3869
3870 if (!bDone)
3871 {
3872 if (bIllArg)
3873 throw lang::IllegalArgumentException();
3874 else
3875 throw uno::RuntimeException(); // NoSuchElementException is handled above
3876 }
3877}
3878
3879void SAL_CALL ScTableSheetsObj::removeByName( const OUString& aName )
3880{
3881 SolarMutexGuard aGuard;
3882 bool bDone = false;
3883 if (pDocShell)
3884 {
3885 SCTAB nIndex;
3887 throw container::NoSuchElementException(); // not found
3888 bDone = pDocShell->GetDocFunc().DeleteTable( nIndex, true );
3889 }
3890
3891 if (!bDone)
3892 throw uno::RuntimeException(); // NoSuchElementException is handled above
3893}
3894
3896 const uno::Reference < sheet::XSpreadsheetDocument > & xDocSrc,
3897 const OUString& srcName, const sal_Int32 nDestPosition )
3898{
3899 //pDocShell is the destination
3900 ScDocument& rDocDest = pDocShell->GetDocument();
3901
3902 // Source document docShell
3903 if ( !xDocSrc.is() )
3904 throw uno::RuntimeException();
3905 ScModelObj* pObj = comphelper::getFromUnoTunnel<ScModelObj>(xDocSrc);
3906 ScDocShell* pDocShellSrc = static_cast<ScDocShell*>(pObj->GetEmbeddedObject());
3907
3908 // SourceSheet Position and does srcName exists ?
3909 SCTAB nIndexSrc;
3910 if ( !pDocShellSrc->GetDocument().GetTable( srcName, nIndexSrc ) )
3911 throw lang::IllegalArgumentException();
3912
3913 // Check the validity of destination index.
3914 SCTAB nCount = rDocDest.GetTableCount();
3915 SCTAB nIndexDest = static_cast<SCTAB>(nDestPosition);
3916 if (nIndexDest > nCount || nIndexDest < 0)
3917 throw lang::IndexOutOfBoundsException();
3918
3919 // Transfer Tab
3921 *pDocShellSrc, nIndexSrc, nIndexDest, true/*bInsertNew*/, true/*bNotifyAndPaint*/ );
3922
3923 return nIndexDest;
3924}
3925
3926// XCellRangesAccess
3927
3928uno::Reference< table::XCell > SAL_CALL ScTableSheetsObj::getCellByPosition( sal_Int32 nColumn, sal_Int32 nRow, sal_Int32 nSheet )
3929{
3930 SolarMutexGuard aGuard;
3931 rtl::Reference<ScTableSheetObj> xSheet = GetObjectByIndex_Impl(static_cast<sal_uInt16>(nSheet));
3932 if (! xSheet.is())
3933 throw lang::IndexOutOfBoundsException();
3934
3935 return xSheet->getCellByPosition(nColumn, nRow);
3936}
3937
3938uno::Reference< table::XCellRange > SAL_CALL ScTableSheetsObj::getCellRangeByPosition( sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom, sal_Int32 nSheet )
3939{
3940 SolarMutexGuard aGuard;
3941 rtl::Reference<ScTableSheetObj> xSheet = GetObjectByIndex_Impl(static_cast<sal_uInt16>(nSheet));
3942 if (! xSheet.is())
3943 throw lang::IndexOutOfBoundsException();
3944
3945 return xSheet->getCellRangeByPosition(nLeft, nTop, nRight, nBottom);
3946}
3947
3948uno::Sequence < uno::Reference< table::XCellRange > > SAL_CALL ScTableSheetsObj::getCellRangesByName( const OUString& aRange )
3949{
3950 SolarMutexGuard aGuard;
3951 uno::Sequence < uno::Reference < table::XCellRange > > xRet;
3952
3953 ScRangeList aRangeList;
3954 ScDocument& rDoc = pDocShell->GetDocument();
3956 throw lang::IllegalArgumentException();
3957
3958 size_t nCount = aRangeList.size();
3959 if (!nCount)
3960 throw lang::IllegalArgumentException();
3961
3962 xRet.realloc(nCount);
3963 auto pRet = xRet.getArray();
3964 for( size_t nIndex = 0; nIndex < nCount; nIndex++ )
3965 {
3966 const ScRange & rRange = aRangeList[ nIndex ];
3967 pRet[nIndex] = new ScCellRangeObj(pDocShell, rRange);
3968 }
3969
3970 return xRet;
3971}
3972
3973// XEnumerationAccess
3974
3975uno::Reference<container::XEnumeration> SAL_CALL ScTableSheetsObj::createEnumeration()
3976{
3977 SolarMutexGuard aGuard;
3978 return new ScIndexEnumeration(this, "com.sun.star.sheet.SpreadsheetsEnumeration");
3979}
3980
3981// XIndexAccess
3982
3983sal_Int32 SAL_CALL ScTableSheetsObj::getCount()
3984{
3985 SolarMutexGuard aGuard;
3986 if (pDocShell)
3988 return 0;
3989}
3990
3991uno::Any SAL_CALL ScTableSheetsObj::getByIndex( sal_Int32 nIndex )
3992{
3993 SolarMutexGuard aGuard;
3994 uno::Reference<sheet::XSpreadsheet> xSheet(GetObjectByIndex_Impl(nIndex));
3995 if (!xSheet.is())
3996 throw lang::IndexOutOfBoundsException();
3997
3998 return uno::Any(xSheet);
3999
4000// return uno::Any();
4001}
4002
4004{
4006}
4007
4009{
4010 SolarMutexGuard aGuard;
4011 return ( getCount() != 0 );
4012}
4013
4014// XNameAccess
4015
4016uno::Any SAL_CALL ScTableSheetsObj::getByName( const OUString& aName )
4017{
4018 SolarMutexGuard aGuard;
4019 uno::Reference<sheet::XSpreadsheet> xSheet(GetObjectByName_Impl(aName));
4020 if (!xSheet.is())
4021 throw container::NoSuchElementException();
4022
4023 return uno::Any(xSheet);
4024}
4025
4026uno::Sequence<OUString> SAL_CALL ScTableSheetsObj::getElementNames()
4027{
4028 SolarMutexGuard aGuard;
4029 if (pDocShell)
4030 {
4031 ScDocument& rDoc = pDocShell->GetDocument();
4032 SCTAB nCount = rDoc.GetTableCount();
4033 OUString aName;
4034 uno::Sequence<OUString> aSeq(nCount);
4035 OUString* pAry = aSeq.getArray();
4036 for (SCTAB i=0; i<nCount; i++)
4037 {
4038 rDoc.GetName( i, aName );
4039 pAry[i] = aName;
4040 }
4041 return aSeq;
4042 }
4043 return uno::Sequence<OUString>();
4044}
4045
4046sal_Bool SAL_CALL ScTableSheetsObj::hasByName( const OUString& aName )
4047{
4048 SolarMutexGuard aGuard;
4049 if (pDocShell)
4050 {
4051 SCTAB nIndex;
4053 return true;
4054 }
4055 return false;
4056}
4057
4059 pDocShell( pDocSh ),
4060 nTab ( nT ),
4061 nStartCol( nSC ),
4062 nEndCol ( nEC )
4063{
4065}
4066
4068{
4070
4071 if (pDocShell)
4073}
4074
4076{
4077 if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
4078 {
4080 }
4081 else if ( rHint.GetId() == SfxHintId::Dying )
4082 {
4083 pDocShell = nullptr; // became invalid
4084 }
4085}
4086
4087// XTableColumns
4088
4090{
4091 SCCOL nCol = static_cast<SCCOL>(nIndex) + nStartCol;
4092 if ( pDocShell && nCol <= nEndCol )
4093 return new ScTableColumnObj( pDocShell, nCol, nTab );
4094
4095 return nullptr; // wrong index
4096}
4097
4099{
4100 SCCOL nCol = 0;
4102 if (nCol >= nStartCol && nCol <= nEndCol)
4103 return new ScTableColumnObj( pDocShell, nCol, nTab );
4104
4105 return nullptr;
4106}
4107
4108void SAL_CALL ScTableColumnsObj::insertByIndex( sal_Int32 nPosition, sal_Int32 nCount )
4109{
4110 SolarMutexGuard aGuard;
4111 bool bDone = false;
4112 if ( pDocShell )
4113 {
4114 const ScDocument& rDoc = pDocShell->GetDocument();
4115 if ( nCount > 0 && nPosition >= 0 && nStartCol+nPosition <= nEndCol &&
4116 nStartCol+nPosition+nCount-1 <= rDoc.MaxCol() )
4117 {
4118 ScRange aRange( static_cast<SCCOL>(nStartCol+nPosition), 0, nTab,
4119 static_cast<SCCOL>(nStartCol+nPosition+nCount-1), rDoc.MaxRow(), nTab );
4120 bDone = pDocShell->GetDocFunc().InsertCells( aRange, nullptr, INS_INSCOLS_BEFORE, true, true );
4121 }
4122 }
4123 if (!bDone)
4124 throw uno::RuntimeException(); // no other exceptions specified
4125}
4126
4127void SAL_CALL ScTableColumnsObj::removeByIndex( sal_Int32 nIndex, sal_Int32 nCount )
4128{
4129 SolarMutexGuard aGuard;
4130 bool bDone = false;
4131 // the range to be deleted has to lie within the object
4132 if ( pDocShell )
4133 {
4134 const ScDocument& rDoc = pDocShell->GetDocument();
4135 if ( nCount > 0 && nIndex >= 0 && nStartCol+nIndex+nCount-1 <= nEndCol )
4136 {
4137 ScRange aRange( static_cast<SCCOL>(nStartCol+nIndex), 0, nTab,
4138 static_cast<SCCOL>(nStartCol+nIndex+nCount-1), rDoc.MaxRow(), nTab );
4139 bDone = pDocShell->GetDocFunc().DeleteCells( aRange, nullptr, DelCellCmd::Cols, true );
4140 }
4141 }
4142 if (!bDone)
4143 throw uno::RuntimeException(); // no other exceptions specified
4144}
4145
4146// XEnumerationAccess
4147
4148uno::Reference<container::XEnumeration> SAL_CALL ScTableColumnsObj::createEnumeration()
4149{
4150 SolarMutexGuard aGuard;
4151 return new ScIndexEnumeration(this, "com.sun.star.table.TableColumnsEnumeration");
4152}
4153
4154// XIndexAccess
4155
4157{
4158 SolarMutexGuard aGuard;
4159 return nEndCol - nStartCol + 1;
4160}
4161
4162uno::Any SAL_CALL ScTableColumnsObj::getByIndex( sal_Int32 nIndex )
4163{
4164 SolarMutexGuard aGuard;
4165 uno::Reference<table::XCellRange> xColumn(GetObjectByIndex_Impl(nIndex));
4166 if (!xColumn.is())
4167 throw lang::IndexOutOfBoundsException();
4168
4169 return uno::Any(xColumn);
4170
4171}
4172
4174{
4176}
4177
4179{
4180 SolarMutexGuard aGuard;
4181 return ( getCount() != 0 );
4182}
4183
4184uno::Any SAL_CALL ScTableColumnsObj::getByName( const OUString& aName )
4185{
4186 SolarMutexGuard aGuard;
4187 uno::Reference<table::XCellRange> xColumn(GetObjectByName_Impl(aName));
4188 if (!xColumn.is())
4189 throw container::NoSuchElementException();
4190
4191 return uno::Any(xColumn);
4192}
4193
4194uno::Sequence<OUString> SAL_CALL ScTableColumnsObj::getElementNames()
4195{
4196 SolarMutexGuard aGuard;
4197 SCCOL nCount = nEndCol - nStartCol + 1;
4198 uno::Sequence<OUString> aSeq(nCount);
4199 OUString* pAry = aSeq.getArray();
4200 for (SCCOL i=0; i<nCount; i++)
4201 pAry[i] = ::ScColToAlpha( nStartCol + i );
4202
4203 return aSeq;
4204}
4205
4206sal_Bool SAL_CALL ScTableColumnsObj::hasByName( const OUString& aName )
4207{
4208 SolarMutexGuard aGuard;
4209 SCCOL nCol = 0;
4211 if (nCol >= nStartCol && nCol <= nEndCol)
4212 return true;
4213
4214 return false; // not found
4215}
4216
4217// XPropertySet
4218
4219uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableColumnsObj::getPropertySetInfo()
4220{
4221 static uno::Reference<beans::XPropertySetInfo> aRef(
4223 return aRef;
4224}
4225
4227 const OUString& aPropertyName, const uno::Any& aValue )
4228{
4229 SolarMutexGuard aGuard;
4230 if (!pDocShell)
4231 throw uno::RuntimeException();
4232
4233 std::vector<sc::ColRowSpan> aColArr(1, sc::ColRowSpan(nStartCol,nEndCol));
4234 ScDocFunc& rFunc = pDocShell->GetDocFunc();
4235
4236 if ( aPropertyName == SC_UNONAME_CELLWID )
4237 {
4238 sal_Int32 nNewWidth = 0;
4239 if ( aValue >>= nNewWidth )
4240 rFunc.SetWidthOrHeight(
4241 true, aColArr, nTab, SC_SIZE_ORIGINAL, o3tl::toTwips(nNewWidth, o3tl::Length::mm100), true, true);
4242 }
4243 else if ( aPropertyName == SC_UNONAME_CELLVIS )
4244 {
4245 bool bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4247 rFunc.SetWidthOrHeight(true, aColArr, nTab, eMode, 0, true, true);
4248 // SC_SIZE_DIRECT with size 0: hide
4249 }
4250 else if ( aPropertyName == SC_UNONAME_OWIDTH )
4251 {
4252 bool bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4253 if (bOpt)
4254 rFunc.SetWidthOrHeight(
4255 true, aColArr, nTab, SC_SIZE_OPTIMAL, STD_EXTRA_WIDTH, true, true);
4256 // sal_False for columns currently has no effect
4257 }
4258 else if ( aPropertyName == SC_UNONAME_NEWPAGE || aPropertyName == SC_UNONAME_MANPAGE )
4259 {
4261 bool bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4262 for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
4263 if (bSet)
4264 rFunc.InsertPageBreak( true, ScAddress(nCol,0,nTab), true, true );
4265 else
4266 rFunc.RemovePageBreak( true, ScAddress(nCol,0,nTab), true, true );
4267 }
4268}
4269
4270uno::Any SAL_CALL ScTableColumnsObj::getPropertyValue( const OUString& aPropertyName )
4271{
4272 SolarMutexGuard aGuard;
4273 if (!pDocShell)
4274 throw uno::RuntimeException();
4275
4276 ScDocument& rDoc = pDocShell->GetDocument();
4277 uno::Any aAny;
4278
4280
4281 if ( aPropertyName == SC_UNONAME_CELLWID )
4282 {
4283 // for hidden column, return original height
4284 sal_uInt16 nWidth = rDoc.GetOriginalWidth( nStartCol, nTab );
4285 aAny <<= static_cast<sal_Int32>(convertTwipToMm100(nWidth));
4286 }
4287 else if ( aPropertyName == SC_UNONAME_CELLVIS )
4288 {
4289 bool bVis = !rDoc.ColHidden(nStartCol, nTab);
4290 aAny <<= bVis;
4291 }
4292 else if ( aPropertyName == SC_UNONAME_OWIDTH )
4293 {
4294 bool bOpt = !(rDoc.GetColFlags( nStartCol, nTab ) & CRFlags::ManualSize);
4295 aAny <<= bOpt;
4296 }
4297 else if ( aPropertyName == SC_UNONAME_NEWPAGE )
4298 {
4299 ScBreakType nBreak = rDoc.HasColBreak(nStartCol, nTab);
4300 aAny <<= (nBreak != ScBreakType::NONE);
4301 }
4302 else if ( aPropertyName == SC_UNONAME_MANPAGE )
4303 {
4304 ScBreakType nBreak = rDoc.HasColBreak(nStartCol, nTab);
4305 aAny <<= bool(nBreak & ScBreakType::Manual);
4306 }
4307
4308 return aAny;
4309}
4310
4312
4314 pDocShell( pDocSh ),
4315 nTab ( nT ),
4316 nStartRow( nSR ),
4317 nEndRow ( nER )
4318{
4319 pDocShell->GetDocument().AddUnoObject(*this);
4320}
4321
4323{
4325
4326 if (pDocShell)
4328}
4329
4331{
4332 if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
4333 {
4335 }
4336 else if ( rHint.GetId() == SfxHintId::Dying )
4337 {
4338 pDocShell = nullptr; // became invalid
4339 }
4340}
4341
4342// XTableRows
4343
4345{
4346 SCROW nRow = static_cast<SCROW>(nIndex) + nStartRow;
4347 if ( pDocShell && nRow <= nEndRow )
4348 return new ScTableRowObj( pDocShell, nRow, nTab );
4349
4350 return nullptr; // wrong index
4351}
4352
4353void SAL_CALL ScTableRowsObj::insertByIndex( sal_Int32 nPosition, sal_Int32 nCount )
4354{
4355 SolarMutexGuard aGuard;
4356 bool bDone = false;
4357 if ( pDocShell )
4358 {
4359 const ScDocument& rDoc = pDocShell->GetDocument();
4360 if ( nCount > 0 && nPosition >= 0 && nStartRow+nPosition <= nEndRow &&
4361 nStartRow+nPosition+nCount-1 <= rDoc.MaxRow() )
4362 {
4363 ScRange aRange( 0, static_cast<SCROW>(nStartRow+nPosition), nTab,
4364 rDoc.MaxCol(), static_cast<SCROW>(nStartRow+nPosition+nCount-1), nTab );
4365 bDone = pDocShell->GetDocFunc().InsertCells( aRange, nullptr, INS_INSROWS_BEFORE, true, true );
4366 }
4367 }
4368 if (!bDone)
4369 throw uno::RuntimeException(); // no other exceptions specified
4370}
4371
4372void SAL_CALL ScTableRowsObj::removeByIndex( sal_Int32 nIndex, sal_Int32 nCount )
4373{
4374 SolarMutexGuard aGuard;
4375 bool bDone = false;
4376 // the range to be deleted has to lie within the object
4377 if ( pDocShell && nCount > 0 && nIndex >= 0 && nStartRow+nIndex+nCount-1 <= nEndRow )
4378 {
4379 const ScDocument& rDoc = pDocShell->GetDocument();
4380 ScRange aRange( 0, static_cast<SCROW>(nStartRow+nIndex), nTab,
4381 rDoc.MaxCol(), static_cast<SCROW>(nStartRow+nIndex+nCount-1), nTab );
4382 bDone = pDocShell->GetDocFunc().DeleteCells( aRange, nullptr, DelCellCmd::Rows, true );
4383 }
4384 if (!bDone)
4385 throw uno::RuntimeException(); // no other exceptions specified
4386}
4387
4388// XEnumerationAccess
4389
4390uno::Reference<container::XEnumeration> SAL_CALL ScTableRowsObj::createEnumeration()
4391{
4392 SolarMutexGuard aGuard;
4393 return new ScIndexEnumeration(this, "com.sun.star.table.TableRowsEnumeration");
4394}
4395
4396// XIndexAccess
4397
4398sal_Int32 SAL_CALL ScTableRowsObj::getCount()
4399{
4400 SolarMutexGuard aGuard;
4401 return nEndRow - nStartRow + 1;
4402}
4403
4404uno::Any SAL_CALL ScTableRowsObj::getByIndex( sal_Int32 nIndex )
4405{
4406 SolarMutexGuard aGuard;
4407 uno::Reference<table::XCellRange> xRow(GetObjectByIndex_Impl(nIndex));
4408 if (!xRow.is())
4409 throw lang::IndexOutOfBoundsException();
4410
4411 return uno::Any(xRow);
4412}
4413
4415{
4417}
4418
4420{
4421 SolarMutexGuard aGuard;
4422 return ( getCount() != 0 );
4423}
4424
4425// XPropertySet
4426
4427uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableRowsObj::getPropertySetInfo()
4428{
4429 static uno::Reference<beans::XPropertySetInfo> aRef(
4431 return aRef;
4432}
4433
4435 const OUString& aPropertyName, const uno::Any& aValue )
4436{
4437 SolarMutexGuard aGuard;
4438 if (!pDocShell)
4439 throw uno::RuntimeException();
4440
4441 ScDocFunc& rFunc = pDocShell->GetDocFunc();
4442 ScDocument& rDoc = pDocShell->GetDocument();
4443 std::vector<sc::ColRowSpan> aRowArr(1, sc::ColRowSpan(nStartRow,nEndRow));
4444
4445 if ( aPropertyName == SC_UNONAME_OHEIGHT )
4446 {
4447 sal_Int32 nNewHeight = 0;
4448 if ( rDoc.IsImportingXML() && ( aValue >>= nNewHeight ) )
4449 {
4450 // used to set the stored row height for rows with optimal height when loading.
4451
4452 // TODO: It's probably cleaner to use a different property name
4453 // for this.
4455 }
4456 else
4457 {
4458 bool bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4459 if (bOpt)
4460 rFunc.SetWidthOrHeight(false, aRowArr, nTab, SC_SIZE_OPTIMAL, 0, true, true);
4461 else
4462 {
4464 }
4465 }
4466 }
4467 else if ( aPropertyName == SC_UNONAME_CELLHGT )
4468 {
4469 sal_Int32 nNewHeight = 0;
4470 if ( aValue >>= nNewHeight )
4471 {
4472 if (rDoc.IsImportingXML())
4473 {
4474 // TODO: This is a band-aid fix. Eventually we need to
4475 // re-work ods' style import to get it to set styles to
4476 // ScDocument directly.
4478 rDoc.SetManualHeight( nStartRow, nEndRow, nTab, true );
4479 }
4480 else
4481 rFunc.SetWidthOrHeight(
4482 false, aRowArr, nTab, SC_SIZE_ORIGINAL, o3tl::toTwips(nNewHeight, o3tl::Length::mm100), true, true);
4483 }
4484 }
4485 else if ( aPropertyName == SC_UNONAME_CELLVIS )
4486 {
4487 bool bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4489 rFunc.SetWidthOrHeight(false, aRowArr, nTab, eMode, 0, true, true);
4490 // SC_SIZE_DIRECT with size 0: hide
4491 }
4492 else if ( aPropertyName == SC_UNONAME_VISFLAG )
4493 {
4494 // #i116460# Shortcut to only set the flag, without drawing layer update etc.
4495 // Should only be used from import filters.
4497 }
4498 else if ( aPropertyName == SC_UNONAME_CELLFILT )
4499 {
4502 rDoc.SetRowFiltered(nStartRow, nEndRow, nTab, true);
4503 else
4504 rDoc.SetRowFiltered(nStartRow, nEndRow, nTab, false);
4505 }
4506 else if ( aPropertyName == SC_UNONAME_NEWPAGE || aPropertyName == SC_UNONAME_MANPAGE )
4507 {
4509 bool bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4510 for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++)
4511 if (bSet)
4512 rFunc.InsertPageBreak( false, ScAddress(0,nRow,nTab), true, true );
4513 else
4514 rFunc.RemovePageBreak( false, ScAddress(0,nRow,nTab), true, true );
4515 }
4516 else if ( aPropertyName == SC_UNONAME_CELLBACK || aPropertyName == SC_UNONAME_CELLTRAN )
4517 {
4518 // #i57867# Background color is specified for row styles in the file format,
4519 // so it has to be supported along with the row properties (import only).
4520
4521 // Use ScCellRangeObj to set the property for all cells in the rows
4522 // (this means, the "row attribute" must be set before individual cell attributes).
4523
4524 ScRange aRange( 0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab );
4525 uno::Reference<beans::XPropertySet> xRangeObj = new ScCellRangeObj( pDocShell, aRange );
4526 xRangeObj->setPropertyValue( aPropertyName, aValue );
4527 }
4528}
4529
4530uno::Any SAL_CALL ScTableRowsObj::getPropertyValue( const OUString& aPropertyName )
4531{
4532 SolarMutexGuard aGuard;
4533 if (!pDocShell)
4534 throw uno::RuntimeException();
4535
4536 ScDocument& rDoc = pDocShell->GetDocument();
4537 uno::Any aAny;
4538
4540
4541 if ( aPropertyName == SC_UNONAME_CELLHGT )
4542 {
4543 // for hidden row, return original height
4544 sal_uInt16 nHeight = rDoc.GetOriginalHeight( nStartRow, nTab );
4545 aAny <<= static_cast<sal_Int32>(convertTwipToMm100(nHeight));
4546 }
4547 else if ( aPropertyName == SC_UNONAME_CELLVIS )
4548 {
4549 SCROW nLastRow;
4550 bool bVis = !rDoc.RowHidden(nStartRow, nTab, nullptr, &nLastRow);
4551 aAny <<= bVis;
4552 }
4553 else if ( aPropertyName == SC_UNONAME_CELLFILT )
4554 {
4555 bool bVis = rDoc.RowFiltered(nStartRow, nTab);
4556 aAny <<= bVis;
4557 }
4558 else if ( aPropertyName == SC_UNONAME_OHEIGHT )
4559 {
4560 bool bOpt = !(rDoc.GetRowFlags( nStartRow, nTab ) & CRFlags::ManualSize);
4561 aAny <<= bOpt;
4562 }
4563 else if ( aPropertyName == SC_UNONAME_NEWPAGE )
4564 {
4565 ScBreakType nBreak = rDoc.HasRowBreak(nStartRow, nTab);
4566 aAny <<= (nBreak != ScBreakType::NONE);
4567 }
4568 else if ( aPropertyName == SC_UNONAME_MANPAGE )
4569 {
4570 ScBreakType nBreak = rDoc.HasRowBreak(nStartRow, nTab);
4571 aAny <<= bool(nBreak & ScBreakType::Manual);
4572 }
4573 else if ( aPropertyName == SC_UNONAME_CELLBACK || aPropertyName == SC_UNONAME_CELLTRAN )
4574 {
4575 // Use ScCellRangeObj to get the property from the cell range
4576 // (for completeness only, this is not used by the XML filter).
4577
4578 ScRange aRange( 0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab );
4579 uno::Reference<beans::XPropertySet> xRangeObj = new ScCellRangeObj( pDocShell, aRange );
4580 aAny = xRangeObj->getPropertyValue( aPropertyName );
4581 }
4582
4583 return aAny;
4584}
4585
4587
4589{
4590}
4591
4592// XPropertySet
4593
4594uno::Reference<beans::XPropertySetInfo> SAL_CALL ScSpreadsheetSettingsObj::getPropertySetInfo()
4595{
4596 return nullptr;
4597}
4598
4600 const OUString& /* aPropertyName */, const uno::Any& /* aValue */ )
4601{
4602}
4603
4604uno::Any SAL_CALL ScSpreadsheetSettingsObj::getPropertyValue( const OUString& /* aPropertyName */ )
4605{
4606 return uno::Any();
4607}
4608
4610
4612 pDocShell( pDocSh ),
4613 nTab( nT )
4614{
4615 pDocShell->GetDocument().AddUnoObject(*this);
4616}
4617
4619{
4621
4622 if (pDocShell)
4624}
4625
4627{
4629
4630 if ( rHint.GetId() == SfxHintId::Dying )
4631 {
4632 pDocShell = nullptr; // became invalid
4633 }
4634}
4635
4636bool ScAnnotationsObj::GetAddressByIndex_Impl( sal_Int32 nIndex, ScAddress& rPos ) const
4637{
4638 if (!pDocShell)
4639 return false;
4640
4641 ScDocument& rDoc = pDocShell->GetDocument();
4642 rPos = rDoc.GetNotePosition(nIndex, nTab);
4643 return rPos.IsValid();
4644}
4645
4647{
4648 if (pDocShell)
4649 {
4650 ScAddress aPos;
4651 if ( GetAddressByIndex_Impl( nIndex, aPos ) )
4652 return new ScAnnotationObj( pDocShell, aPos );
4653 }
4654 return nullptr;
4655}
4656
4657// XSheetAnnotations
4658
4660 const table::CellAddress& aPosition, const OUString& rText )
4661{
4662 SolarMutexGuard aGuard;
4663 if (pDocShell)
4664 {
4665 OSL_ENSURE( aPosition.Sheet == nTab, "addAnnotation with a wrong Sheet" );
4666 ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
4667 pDocShell->GetDocFunc().ReplaceNote( aPos, rText, nullptr, nullptr, true );
4668 }
4669}
4670
4671void SAL_CALL ScAnnotationsObj::removeByIndex( sal_Int32 nIndex )
4672{
4673 SolarMutexGuard aGuard;
4674 if (pDocShell)
4675 {
4676 ScAddress aPos;
4677 if ( GetAddressByIndex_Impl( nIndex, aPos ) )
4678 {
4680 aMarkData.SelectTable( aPos.Tab(), true );
4681 aMarkData.SetMultiMarkArea( ScRange(aPos) );
4682
4683 pDocShell->GetDocFunc().DeleteContents( aMarkData, InsertDeleteFlags::NOTE, true, true );
4684 }
4685 }
4686}
4687
4688// XEnumerationAccess
4689
4690uno::Reference<container::XEnumeration> SAL_CALL ScAnnotationsObj::createEnumeration()
4691{
4693
4694 SolarMutexGuard aGuard;
4695 return new ScIndexEnumeration(this, "com.sun.star.sheet.CellAnnotationsEnumeration");
4696}
4697
4698// XIndexAccess
4699
4700sal_Int32 SAL_CALL ScAnnotationsObj::getCount()
4701{
4702 SolarMutexGuard aGuard;
4703 sal_Int32 nCount = 0;
4704 if (pDocShell)
4705 {
4706 const ScDocument& rDoc = pDocShell->GetDocument();
4707 for (SCCOL nCol : rDoc.GetAllocatedColumnsRange(nTab, 0, rDoc.MaxCol()))
4708 nCount += rDoc.GetNoteCount(nTab, nCol);
4709 }
4710 return nCount;
4711}
4712
4713uno::Any SAL_CALL ScAnnotationsObj::getByIndex( sal_Int32 nIndex )
4714{
4715 SolarMutexGuard aGuard;
4716 uno::Reference<sheet::XSheetAnnotation> xAnnotation(GetObjectByIndex_Impl(nIndex));
4717 if (!xAnnotation.is())
4718 throw lang::IndexOutOfBoundsException();
4719
4720 return uno::Any(xAnnotation);
4721}
4722
4724{
4726}
4727
4729{
4730 SolarMutexGuard aGuard;
4731 return ( getCount() != 0 );
4732}
4733
4735 pDocShell( pDocSh ),
4736 nTab ( nT )
4737{
4739}
4740
4742{
4744
4745 if (pDocShell)
4747}
4748
4750{
4751 if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
4752 {
4754 }
4755 else if ( rHint.GetId() == SfxHintId::Dying )
4756 {
4757 pDocShell = nullptr; // became invalid
4758 }
4759}
4760
4761// XScenarios
4762
4763bool ScScenariosObj::GetScenarioIndex_Impl( std::u16string_view rName, SCTAB& rIndex )
4764{
4766
4767 if ( pDocShell )
4768 {
4769 OUString aTabName;
4770 ScDocument& rDoc = pDocShell->GetDocument();
4771 SCTAB nCount = static_cast<SCTAB>(getCount());
4772 for (SCTAB i=0; i<nCount; i++)
4773 if (rDoc.GetName( nTab+i+1, aTabName ))
4774 if (aTabName == rName)
4775 {
4776 rIndex = i;
4777 return true;
4778 }
4779 }
4780
4781 return false;
4782}
4783
4785{
4786 sal_uInt16 nCount = static_cast<sal_uInt16>(getCount());
4787 if ( pDocShell && nIndex >= 0 && nIndex < nCount )
4788 return new ScTableSheetObj( pDocShell, nTab+static_cast<SCTAB>(nIndex)+1 );
4789
4790 return nullptr; // no document or wrong index
4791}
4792
4794{
4795 SCTAB nIndex;
4797 return new ScTableSheetObj( pDocShell, nTab+nIndex+1 );
4798
4799 return nullptr; // not found
4800}
4801
4802void SAL_CALL ScScenariosObj::addNewByName( const OUString& aName,
4803 const uno::Sequence<table::CellRangeAddress>& aRanges,
4804 const OUString& aComment )
4805{
4806 SolarMutexGuard aGuard;
4807 if ( !pDocShell )
4808 return;
4809
4811 aMarkData.SelectTable( nTab, true );
4812
4813 for (const table::CellRangeAddress& rRange : aRanges)
4814 {
4815 OSL_ENSURE( rRange.Sheet == nTab, "addScenario with a wrong Tab" );
4816 ScRange aRange( static_cast<SCCOL>(rRange.StartColumn), static_cast<SCROW>(rRange.StartRow), nTab,
4817 static_cast<SCCOL>(rRange.EndColumn), static_cast<SCROW>(rRange.EndRow), nTab );
4818
4819 aMarkData.SetMultiMarkArea( aRange );
4820 }
4821
4824
4825 pDocShell->MakeScenario( nTab, aName, aComment, COL_LIGHTGRAY, nFlags, aMarkData );
4826}
4827
4828void SAL_CALL ScScenariosObj::removeByName( const OUString& aName )
4829{
4830 SolarMutexGuard aGuard;
4831 SCTAB nIndex;
4834}
4835
4836// XEnumerationAccess
4837
4838uno::Reference<container::XEnumeration> SAL_CALL ScScenariosObj::createEnumeration()
4839{
4840 SolarMutexGuard aGuard;
4841 return new ScIndexEnumeration(this, "com.sun.star.sheet.ScenariosEnumeration");
4842}
4843
4844// XIndexAccess
4845
4846sal_Int32 SAL_CALL ScScenariosObj::getCount()
4847{
4848 SolarMutexGuard aGuard;
4849 SCTAB nCount = 0;
4850 if ( pDocShell )
4851 {
4852 ScDocument& rDoc = pDocShell->GetDocument();
4853 if (!rDoc.IsScenario(nTab))
4854 {
4855 SCTAB nTabCount = rDoc.GetTableCount();
4856 SCTAB nNext = nTab + 1;
4857 while (nNext < nTabCount && rDoc.IsScenario(nNext))
4858 {
4859 ++nCount;
4860 ++nNext;
4861 }
4862 }
4863 }
4864 return nCount;
4865}
4866
4867uno::Any SAL_CALL ScScenariosObj::getByIndex( sal_Int32 nIndex )
4868{
4869 SolarMutexGuard aGuard;
4870 uno::Reference<sheet::XScenario> xScen(GetObjectByIndex_Impl(nIndex));
4871 if (!xScen.is())
4872 throw lang::IndexOutOfBoundsException();
4873
4874 return uno::Any(xScen);
4875}
4876
4878{
4880}
4881
4883{
4884 SolarMutexGuard aGuard;
4885 return ( getCount() != 0 );
4886}
4887
4888uno::Any SAL_CALL ScScenariosObj::getByName( const OUString& aName )
4889{
4890 SolarMutexGuard aGuard;
4891 uno::Reference<sheet::XScenario> xScen(GetObjectByName_Impl(aName));
4892 if (!xScen.is())
4893 throw container::NoSuchElementException();
4894
4895 return uno::Any(xScen);
4896}
4897
4898uno::Sequence<OUString> SAL_CALL ScScenariosObj::getElementNames()
4899{
4900 SolarMutexGuard aGuard;
4901 SCTAB nCount = static_cast<SCTAB>(getCount());
4902 uno::Sequence<OUString> aSeq(nCount);
4903
4904 if ( pDocShell ) // otherwise Count = 0
4905 {
4906 OUString aTabName;
4907 ScDocument& rDoc = pDocShell->GetDocument();
4908 OUString* pAry = aSeq.getArray();
4909 for (SCTAB i=0; i<nCount; i++)
4910 if (rDoc.GetName( nTab+i+1, aTabName ))
4911 pAry[i] = aTabName;
4912 }
4913
4914 return aSeq;
4915}
4916
4917sal_Bool SAL_CALL ScScenariosObj::hasByName( const OUString& aName )
4918{
4919 SolarMutexGuard aGuard;
4920 SCTAB nIndex;
4922}
4923
4924/* 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:2511
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 bool postMouseEvent(const SdrPage *pPage, const SdrView *pDrawView, vcl::Window const &rMainWindow, int nType, Point aPointHmm, int nCount, int nButtons, int nModifier)
static void paintControlTile(const SdrPage *pPage, const SdrView *pDrawView, vcl::Window const &rMainWindow, VirtualDevice &rDevice, Size aOutputSize, tools::Rectangle const &rTileRect)
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=nullptr)
Definition: address.cxx:1537
SCROW Row() const
Definition: address.hxx:274
SCCOL Col() const
Definition: address.hxx:279
virtual css::uno::Any SAL_CALL getByIndex(sal_Int32 Index) override
Definition: docuno.cxx:4713
SCTAB nTab
Collection belongs to the sheet.
Definition: docuno.hxx:673
virtual ~ScAnnotationsObj() override
Definition: docuno.cxx:4618
virtual css::uno::Type SAL_CALL getElementType() override
XElementAccess.
Definition: docuno.cxx:4723