tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / view / drawvie4.cxx
blobdf5615741958252dde505e3f2d366b6fd7261940
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <svx/svditer.hxx>
21 #include <svx/svdograf.hxx>
22 #include <svx/svdogrp.hxx>
23 #include <svx/svdoole2.hxx>
24 #include <svx/svdundo.hxx>
25 #include <sfx2/docfile.hxx>
26 #include <tools/urlobj.hxx>
27 #include <toolkit/helper/vclunohelper.hxx>
28 #include <sal/log.hxx>
30 #include <drawview.hxx>
31 #include <global.hxx>
32 #include <drwlayer.hxx>
33 #include <viewdata.hxx>
34 #include <document.hxx>
35 #include <docsh.hxx>
36 #include <drwtrans.hxx>
37 #include <transobj.hxx>
38 #include <drawutil.hxx>
39 #include <scmod.hxx>
40 #include <globstr.hrc>
41 #include <scresid.hxx>
42 #include <gridwin.hxx>
43 #include <userdat.hxx>
45 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
46 #include <com/sun/star/embed/Aspects.hpp>
47 #include <com/sun/star/embed/XEmbeddedObject.hpp>
48 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
49 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
50 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
51 #include <com/sun/star/chart2/XChartDocument.hpp>
52 #include <comphelper/diagnose_ex.hxx>
54 using namespace com::sun::star;
56 Point aDragStartDiff;
58 void ScDrawView::BeginDrag( vcl::Window* pWindow, const Point& rStartPos )
60 const SdrMarkList& rMarkList = GetMarkedObjectList();
61 if ( rMarkList.GetMarkCount() == 0 )
62 return;
64 BrkAction();
66 tools::Rectangle aMarkedRect = GetAllMarkedRect();
68 aDragStartDiff = rStartPos - aMarkedRect.TopLeft();
70 bool bAnyOle, bOneOle;
71 CheckOle( rMarkList, bAnyOle, bOneOle );
73 ScDocShellRef aDragShellRef;
74 if (bAnyOle)
76 aDragShellRef = new ScDocShell; // DocShell needs a Ref immediately
77 aDragShellRef->DoInitNew();
79 ScDrawLayer::SetGlobalDrawPersist( aDragShellRef.get() );
80 std::unique_ptr<SdrModel> pModel(CreateMarkedObjModel());
81 ScDrawLayer::SetGlobalDrawPersist(nullptr);
83 // Charts now always copy their data in addition to the source reference, so
84 // there's no need to call SchDLL::Update for the charts in the clipboard doc.
85 // Update with the data (including NumberFormatter) from the live document would
86 // also store the NumberFormatter in the clipboard chart (#88749#)
88 ScDocShell* pDocSh = pViewData->GetDocShell();
90 TransferableObjectDescriptor aObjDesc;
91 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
92 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
93 // maSize is set in ScDrawTransferObj ctor
95 rtl::Reference<ScDrawTransferObj> pTransferObj = new ScDrawTransferObj( std::move(pModel), pDocSh, std::move(aObjDesc) );
97 pTransferObj->SetDrawPersist(aDragShellRef); // keep persist for ole objects alive
98 pTransferObj->SetDragSource( this ); // copies selection
100 ScModule::get()->SetDragObject(nullptr, pTransferObj.get()); // for internal D&D
101 pTransferObj->StartDrag( pWindow, DND_ACTION_COPYMOVE | DND_ACTION_LINK );
104 namespace {
106 void getRangeFromDataSource( uno::Reference< chart2::data::XDataSource > const & xDataSource, std::vector<OUString>& rRangeRep)
108 const uno::Sequence<uno::Reference<chart2::data::XLabeledDataSequence> > xSeqs = xDataSource->getDataSequences();
109 for (const uno::Reference<chart2::data::XLabeledDataSequence>& xLS : xSeqs)
111 uno::Reference<chart2::data::XDataSequence> xSeq = xLS->getValues();
112 if (xSeq.is())
114 OUString aRep = xSeq->getSourceRangeRepresentation();
115 rRangeRep.push_back(aRep);
117 xSeq = xLS->getLabel();
118 if (xSeq.is())
120 OUString aRep = xSeq->getSourceRangeRepresentation();
121 rRangeRep.push_back(aRep);
126 void getRangeFromErrorBar(const uno::Reference< chart2::XChartDocument >& rChartDoc, std::vector<OUString>& rRangeRep)
128 uno::Reference <chart2::XDiagram > xDiagram = rChartDoc->getFirstDiagram();
129 if(!xDiagram.is())
130 return;
132 uno::Reference< chart2::XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY);
133 if(!xCooSysContainer.is())
134 return;
136 const uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > xCooSysSequence( xCooSysContainer->getCoordinateSystems());
137 for(const auto& rCooSys : xCooSysSequence)
139 uno::Reference< chart2::XChartTypeContainer > xChartTypeContainer( rCooSys, uno::UNO_QUERY);
140 if(!xChartTypeContainer.is())
141 continue;
143 const uno::Sequence< uno::Reference< chart2::XChartType > > xChartTypeSequence( xChartTypeContainer->getChartTypes() );
144 for(const auto& rChartType : xChartTypeSequence)
146 uno::Reference< chart2::XDataSeriesContainer > xDataSequenceContainer( rChartType, uno::UNO_QUERY);
147 if(!xDataSequenceContainer.is())
148 continue;
150 const uno::Sequence< uno::Reference< chart2::XDataSeries > > xSeriesSequence( xDataSequenceContainer->getDataSeries() );
151 for(const uno::Reference<chart2::XDataSeries>& xSeries : xSeriesSequence)
153 uno::Reference< beans::XPropertySet > xPropSet( xSeries, uno::UNO_QUERY);
154 uno::Reference< chart2::data::XDataSource > xErrorBarY;
155 xPropSet->getPropertyValue(u"ErrorBarY"_ustr) >>= xErrorBarY;
156 if(xErrorBarY.is())
157 getRangeFromDataSource(xErrorBarY, rRangeRep);
158 uno::Reference< chart2::data::XDataSource > xErrorBarX;
159 xPropSet->getPropertyValue(u"ErrorBarX"_ustr) >>= xErrorBarX;
160 if(xErrorBarX.is())
161 getRangeFromDataSource(xErrorBarX, rRangeRep);
167 void getRangeFromOle2Object(const SdrOle2Obj& rObj, std::vector<OUString>& rRangeRep)
169 if (!rObj.IsChart())
170 // not a chart object.
171 return;
173 const uno::Reference<embed::XEmbeddedObject>& xObj = rObj.GetObjRef();
174 if (!xObj.is())
175 return;
177 uno::Reference<chart2::XChartDocument> xChartDoc(xObj->getComponent(), uno::UNO_QUERY);
178 if (!xChartDoc.is())
179 return;
181 if(xChartDoc->hasInternalDataProvider())
182 return;
184 getRangeFromErrorBar(xChartDoc, rRangeRep);
186 uno::Reference<chart2::data::XDataSource> xDataSource(xChartDoc, uno::UNO_QUERY);
187 if (!xDataSource.is())
188 return;
190 // Get all data sources used in this chart.
191 getRangeFromDataSource(xDataSource, rRangeRep);
193 return;
196 // Get all cell ranges that are referenced by the selected chart objects.
197 void getOleSourceRanges(const SdrMarkList& rMarkList, bool& rAnyOle, bool& rOneOle, std::vector<ScRange>* pRanges = nullptr, const ScDocument* pDoc = nullptr )
199 bool bCalcSourceRanges = pRanges && pDoc;
200 std::vector<OUString> aRangeReps;
201 rAnyOle = rOneOle = false;
202 const size_t nCount = rMarkList.GetMarkCount();
203 for (size_t i=0; i<nCount; ++i)
205 SdrMark* pMark = rMarkList.GetMark(i);
206 if ( !pMark )
207 continue;
209 SdrObject* pObj = pMark->GetMarkedSdrObj();
210 if ( !pObj )
211 continue;
213 SdrObjKind nSdrObjKind = pObj->GetObjIdentifier();
214 if (nSdrObjKind == SdrObjKind::OLE2)
216 rAnyOle = true;
217 rOneOle = (nCount == 1);
218 if ( bCalcSourceRanges )
219 getRangeFromOle2Object( static_cast<const SdrOle2Obj&>( *pObj ), aRangeReps );
220 else
221 break;
223 else if ( dynamic_cast<const SdrObjGroup*>( pObj) != nullptr )
225 SdrObjListIter aIter( *pObj, SdrIterMode::DeepNoGroups );
226 SdrObject* pSubObj = aIter.Next();
227 while (pSubObj)
229 if ( pSubObj->GetObjIdentifier() == SdrObjKind::OLE2 )
231 rAnyOle = true;
232 // rOneOle remains false - a group isn't treated like a single OLE object
233 if ( !bCalcSourceRanges )
234 return;
236 getRangeFromOle2Object( static_cast<const SdrOle2Obj&>( *pSubObj ), aRangeReps );
238 pSubObj = aIter.Next();
243 if (!bCalcSourceRanges)
244 return;
246 // Compile all range representation strings into ranges.
247 for (const auto& rRangeRep : aRangeReps)
249 ScRangeList aRange;
250 ScAddress aAddr;
251 if (aRange.Parse(rRangeRep, *pDoc, pDoc->GetAddressConvention()) & ScRefFlags::VALID)
253 pRanges->insert(pRanges->end(), aRange.begin(), aRange.end());
255 else if (aAddr.Parse(rRangeRep, *pDoc, pDoc->GetAddressConvention()) & ScRefFlags::VALID)
256 pRanges->push_back(ScRange(aAddr));
259 return;
262 class InsertTabIndex
264 std::vector<SCTAB>& mrTabs;
265 public:
266 explicit InsertTabIndex(std::vector<SCTAB>& rTabs) : mrTabs(rTabs) {}
267 void operator() (const ScRange& rRange)
269 mrTabs.push_back(rRange.aStart.Tab());
273 class CopyRangeData
275 ScDocument& mrSrc;
276 ScDocument& mrDest;
277 public:
278 CopyRangeData(ScDocument& rSrc, ScDocument& rDest) : mrSrc(rSrc), mrDest(rDest) {}
280 void operator() (const ScRange& rRange)
282 OUString aTabName;
283 mrSrc.GetName(rRange.aStart.Tab(), aTabName);
285 SCTAB nTab;
286 if (!mrDest.GetTable(aTabName, nTab))
287 // Sheet by this name doesn't exist.
288 return;
290 mrSrc.CopyStaticToDocument(rRange, nTab, mrDest);
294 void copyChartRefDataToClipDoc(ScDocument& rSrcDoc, ScDocument& rClipDoc, const std::vector<ScRange>& rRanges)
296 // Get a list of referenced table indices.
297 std::vector<SCTAB> aTabs;
298 std::for_each(rRanges.begin(), rRanges.end(), InsertTabIndex(aTabs));
299 std::sort(aTabs.begin(), aTabs.end());
300 aTabs.erase(std::unique(aTabs.begin(), aTabs.end()), aTabs.end());
302 // Get table names.
303 if (aTabs.empty())
304 return;
306 // Create sheets only for referenced source sheets.
307 OUString aName;
308 std::vector<SCTAB>::const_iterator it = aTabs.begin(), itEnd = aTabs.end();
309 if (!rSrcDoc.GetName(*it, aName))
310 return;
312 rClipDoc.SetTabNameOnLoad(0, aName); // document initially has one sheet.
314 for (++it; it != itEnd; ++it)
316 if (!rSrcDoc.GetName(*it, aName))
317 return;
319 rClipDoc.AppendTabOnLoad(aName);
322 std::for_each(rRanges.begin(), rRanges.end(), CopyRangeData(rSrcDoc, rClipDoc));
327 void ScDrawView::CheckOle( const SdrMarkList& rMarkList, bool& rAnyOle, bool& rOneOle )
329 getOleSourceRanges( rMarkList, rAnyOle, rOneOle );
332 void ScDrawView::DoCopy()
334 const SdrMarkList& rMarkList = GetMarkedObjectList();
335 std::vector<ScRange> aRanges;
336 bool bAnyOle = false, bOneOle = false;
337 getOleSourceRanges( rMarkList, bAnyOle, bOneOle, &aRanges, &rDoc );
339 // update ScGlobal::xDrawClipDocShellRef
340 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
341 if (ScGlobal::xDrawClipDocShellRef.is() && !aRanges.empty())
343 // Copy data referenced by the chart objects to the draw clip
344 // document. We need to do this before CreateMarkedObjModel() below.
345 ScDocShellRef xDocSh = ScGlobal::xDrawClipDocShellRef;
346 ScDocument& rClipDoc = xDocSh->GetDocument();
347 copyChartRefDataToClipDoc(rDoc, rClipDoc, aRanges);
349 std::unique_ptr<SdrModel> pModel(CreateMarkedObjModel());
350 ScDrawLayer::SetGlobalDrawPersist(nullptr);
352 // Charts now always copy their data in addition to the source reference, so
353 // there's no need to call SchDLL::Update for the charts in the clipboard doc.
354 // Update with the data (including NumberFormatter) from the live document would
355 // also store the NumberFormatter in the clipboard chart (#88749#)
357 ScDocShell* pDocSh = pViewData->GetDocShell();
359 TransferableObjectDescriptor aObjDesc;
360 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
361 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
362 // maSize is set in ScDrawTransferObj ctor
364 rtl::Reference<ScDrawTransferObj> pTransferObj(new ScDrawTransferObj( std::move(pModel), pDocSh, std::move(aObjDesc) ));
366 if ( ScGlobal::xDrawClipDocShellRef.is() )
368 pTransferObj->SetDrawPersist( ScGlobal::xDrawClipDocShellRef ); // keep persist for ole objects alive
371 pTransferObj->CopyToClipboard( pViewData->GetActiveWin() ); // system clipboard
374 uno::Reference<datatransfer::XTransferable> ScDrawView::CopyToTransferable()
376 bool bAnyOle, bOneOle;
377 const SdrMarkList& rMarkList = GetMarkedObjectList();
378 CheckOle( rMarkList, bAnyOle, bOneOle );
380 // update ScGlobal::xDrawClipDocShellRef
381 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
382 std::unique_ptr<SdrModel> pModel( CreateMarkedObjModel() );
383 ScDrawLayer::SetGlobalDrawPersist(nullptr);
385 // Charts now always copy their data in addition to the source reference, so
386 // there's no need to call SchDLL::Update for the charts in the clipboard doc.
387 // Update with the data (including NumberFormatter) from the live document would
388 // also store the NumberFormatter in the clipboard chart (#88749#)
389 // lcl_RefreshChartData( pModel, pViewData->GetDocument() );
391 ScDocShell* pDocSh = pViewData->GetDocShell();
393 TransferableObjectDescriptor aObjDesc;
394 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
395 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
396 // maSize is set in ScDrawTransferObj ctor
398 rtl::Reference<ScDrawTransferObj> pTransferObj = new ScDrawTransferObj( std::move(pModel), pDocSh, std::move(aObjDesc) );
400 if ( ScGlobal::xDrawClipDocShellRef.is() )
402 pTransferObj->SetDrawPersist( ScGlobal::xDrawClipDocShellRef ); // keep persist for ole objects alive
405 return pTransferObj;
408 // Calculate correction for 100%, regardless of current settings
410 void ScDrawView::CalcNormScale( Fraction& rFractX, Fraction& rFractY ) const
412 double nPPTX = ScGlobal::nScreenPPTX;
413 double nPPTY = ScGlobal::nScreenPPTY;
415 if (pViewData)
416 nPPTX /= pViewData->GetDocShell()->GetOutputFactor();
418 SCCOL nEndCol = 0;
419 SCROW nEndRow = 0;
420 rDoc.GetTableArea( nTab, nEndCol, nEndRow );
421 if (nEndCol<20)
422 nEndCol = 20;
423 if (nEndRow<20)
424 nEndRow = 1000;
426 Fraction aZoom(1,1);
427 ScDrawUtil::CalcScale( rDoc, nTab, 0,0, nEndCol,nEndRow, pDev, aZoom,aZoom,
428 nPPTX, nPPTY, rFractX,rFractY );
431 void ScDrawView::SetMarkedOriginalSize()
433 std::unique_ptr<SdrUndoGroup> pUndoGroup(new SdrUndoGroup(GetModel()));
435 const SdrMarkList& rMarkList = GetMarkedObjectList();
436 tools::Long nDone = 0;
437 const size_t nCount = rMarkList.GetMarkCount();
438 for (size_t i=0; i<nCount; ++i)
440 SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
441 SdrObjKind nIdent = pObj->GetObjIdentifier();
442 bool bDo = false;
443 Size aOriginalSize;
444 if (nIdent == SdrObjKind::OLE2)
446 // TODO/LEAN: working with visual area can switch object to running state
447 uno::Reference < embed::XEmbeddedObject > xObj = static_cast<SdrOle2Obj*>(pObj)->GetObjRef();
448 if ( xObj.is() ) // NULL for an invalid object that couldn't be loaded
450 sal_Int64 nAspect = static_cast<SdrOle2Obj*>(pObj)->GetAspect();
452 if ( nAspect == embed::Aspects::MSOLE_ICON )
454 MapMode aMapMode( MapUnit::Map100thMM );
455 aOriginalSize = static_cast<SdrOle2Obj*>(pObj)->GetOrigObjSize( &aMapMode );
456 bDo = true;
458 else
460 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( static_cast<SdrOle2Obj*>(pObj)->GetAspect() ) );
463 awt::Size aSz = xObj->getVisualAreaSize( static_cast<SdrOle2Obj*>(pObj)->GetAspect() );
464 aOriginalSize = OutputDevice::LogicToLogic(
465 Size( aSz.Width, aSz.Height ),
466 MapMode(aUnit),
467 MapMode(MapUnit::Map100thMM));
468 bDo = true;
469 } catch( embed::NoVisualAreaSizeException& )
471 TOOLS_WARN_EXCEPTION("sc.ui", "Can't get the original size of the object!" );
476 else if (nIdent == SdrObjKind::Graphic)
478 const SdrGrafObj* pSdrGrafObj = static_cast<const SdrGrafObj*>(pObj);
480 MapMode aSourceMap = pSdrGrafObj->GetGraphic().GetPrefMapMode();
481 MapMode aDestMap( MapUnit::Map100thMM );
482 if (aSourceMap.GetMapUnit() == MapUnit::MapPixel)
484 // consider pixel correction, so that the bitmap is correct on the screen
485 Fraction aNormScaleX, aNormScaleY;
486 CalcNormScale( aNormScaleX, aNormScaleY );
487 aDestMap.SetScaleX(aNormScaleX);
488 aDestMap.SetScaleY(aNormScaleY);
490 aOriginalSize = pSdrGrafObj->getOriginalSize();
491 bDo = true;
494 if ( bDo )
496 tools::Rectangle aDrawRect = pObj->GetLogicRect();
498 pUndoGroup->AddAction( std::make_unique<SdrUndoGeoObj>( *pObj ) );
499 pObj->Resize( aDrawRect.TopLeft(), Fraction( aOriginalSize.Width(), aDrawRect.GetWidth() ),
500 Fraction( aOriginalSize.Height(), aDrawRect.GetHeight() ) );
501 ++nDone;
505 if (nDone && pViewData)
507 pUndoGroup->SetComment(ScResId( STR_UNDO_ORIGINALSIZE ));
508 ScDocShell* pDocSh = pViewData->GetDocShell();
509 pDocSh->GetUndoManager()->AddUndoAction(std::move(pUndoGroup));
510 pDocSh->SetDrawModified();
514 void ScDrawView::FitToCellSize()
516 const SdrMarkList& rMarkList = GetMarkedObjectList();
518 if (rMarkList.GetMarkCount() != 1)
520 SAL_WARN("sc.ui", "Fit to cell only works with one graphic!");
521 return;
524 SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
526 ScAnchorType aAnchorType = ScDrawLayer::GetAnchorType(*pObj);
527 if (aAnchorType != SCA_CELL && aAnchorType != SCA_CELL_RESIZE)
529 SAL_WARN("sc.ui", "Fit to cell only works with cell anchored graphics!");
530 return;
533 ScDrawObjData* pObjData = ScDrawLayer::GetObjData(pObj);
534 if (!pObjData)
536 SAL_WARN("sc.ui", "Missing ScDrawObjData!");
537 return;
540 std::unique_ptr<SdrUndoGroup> pUndoGroup(new SdrUndoGroup(GetModel()));
541 tools::Rectangle aGraphicRect = pObj->GetSnapRect();
542 tools::Rectangle aCellRect = ScDrawLayer::GetCellRect( rDoc, pObjData->maStart, true);
544 // For graphic objects, we want to keep the aspect ratio
545 if (pObj->shouldKeepAspectRatio())
547 tools::Long nWidth = aGraphicRect.GetWidth();
548 assert(nWidth && "div-by-zero");
549 double fScaleX = static_cast<double>(aCellRect.GetWidth()) / static_cast<double>(nWidth);
550 tools::Long nHeight = aGraphicRect.GetHeight();
551 assert(nHeight && "div-by-zero");
552 double fScaleY = static_cast<double>(aCellRect.GetHeight()) / static_cast<double>(nHeight);
553 double fScaleMin = std::min(fScaleX, fScaleY);
555 aCellRect.setWidth(static_cast<double>(aGraphicRect.GetWidth()) * fScaleMin);
556 aCellRect.setHeight(static_cast<double>(aGraphicRect.GetHeight()) * fScaleMin);
559 pUndoGroup->AddAction( std::make_unique<SdrUndoGeoObj>( *pObj ) );
560 if (pObj->GetObjIdentifier() == SdrObjKind::CustomShape)
561 pObj->AdjustToMaxRect(aCellRect);
562 else
563 pObj->SetSnapRect(aCellRect);
565 pUndoGroup->SetComment(ScResId( STR_UNDO_FITCELLSIZE ));
566 ScDocShell* pDocSh = pViewData->GetDocShell();
567 pDocSh->GetUndoManager()->AddUndoAction(std::move(pUndoGroup));
571 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */