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