tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / drawfunc / fuins1.cxx
blob728865a43f4d6ed35674b12ab1c3e2f9b86dc74f
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 <config_features.h>
22 #include <officecfg/Office/Common.hxx>
23 #include <editeng/sizeitem.hxx>
24 #include <sal/log.hxx>
25 #include <sfx2/lokhelper.hxx>
26 #include <sfx2/opengrf.hxx>
27 #include <sfx2/viewfrm.hxx>
28 #include <svx/svdograf.hxx>
29 #include <svx/svdomedia.hxx>
30 #include <svx/svdpage.hxx>
31 #include <svx/svdpagv.hxx>
32 #include <svx/svdview.hxx>
33 #include <svx/linkwarn.hxx>
34 #include <svx/svxids.hrc>
35 #include <vcl/graphicfilter.hxx>
36 #include <svl/stritem.hxx>
37 #include <avmedia/mediawindow.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/weld.hxx>
40 #include <vcl/GraphicNativeTransform.hxx>
41 #include <vcl/GraphicNativeMetadata.hxx>
42 #include <fuinsert.hxx>
43 #include <tabvwsh.hxx>
44 #include <drwlayer.hxx>
45 #include <drawview.hxx>
46 #include <document.hxx>
47 #include <scresid.hxx>
48 #include <strings.hrc>
49 #include <globstr.hrc>
50 #include <comphelper/lok.hxx>
52 #include <tools/hostfilter.hxx>
53 #include <tools/urlobj.hxx>
55 #include <com/sun/star/frame/XDispatchProvider.hpp>
56 #include <com/sun/star/media/XPlayer.hpp>
57 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
58 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
59 #include <com/sun/star/ui/dialogs/ListboxControlActions.hpp>
60 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
61 #include <com/sun/star/uno/Sequence.hxx>
63 using namespace css;
64 using namespace css::uno;
66 void ScLimitSizeOnDrawPage( Size& rSize, Point& rPos, const Size& rPage )
68 if ( !rPage.Width() || !rPage.Height() )
69 return;
71 Size aPageSize = rPage;
72 bool bNegative = aPageSize.Width() < 0;
73 if ( bNegative )
75 // make everything positive temporarily
76 aPageSize.setWidth( -aPageSize.Width() );
77 rPos.setX( -rPos.X() - rSize.Width() );
80 if ( rSize.Width() > aPageSize.Width() || rSize.Height() > aPageSize.Height() )
82 double fX = aPageSize.Width() / static_cast<double>(rSize.Width());
83 double fY = aPageSize.Height() / static_cast<double>(rSize.Height());
85 if ( fX < fY )
87 rSize.setWidth( aPageSize.Width() );
88 rSize.setHeight( static_cast<tools::Long>( rSize.Height() * fX ) );
90 else
92 rSize.setHeight( aPageSize.Height() );
93 rSize.setWidth( static_cast<tools::Long>( rSize.Width() * fY ) );
96 if (!rSize.Width())
97 rSize.setWidth( 1 );
98 if (!rSize.Height())
99 rSize.setHeight( 1 );
102 if ( rPos.X() + rSize.Width() > aPageSize.Width() )
103 rPos.setX( aPageSize.Width() - rSize.Width() );
104 if ( rPos.Y() + rSize.Height() > aPageSize.Height() )
105 rPos.setY( aPageSize.Height() - rSize.Height() );
107 if ( bNegative )
108 rPos.setX( -rPos.X() - rSize.Width() ); // back to real position
111 static void lcl_InsertGraphic( const Graphic& rGraphic,
112 const OUString& rFileName, bool bAsLink, bool bApi,
113 ScTabViewShell& rViewSh, const vcl::Window* pWindow, SdrView* pView,
114 ScAnchorType aAnchorType = SCA_CELL )
116 Graphic& rGraphic1 = const_cast<Graphic &>(rGraphic);
117 GraphicNativeMetadata aMetadata;
118 if ( aMetadata.read(rGraphic1) )
120 const Degree10 aRotation = aMetadata.getRotation();
121 if (aRotation)
123 GraphicNativeTransform aTransform( rGraphic1 );
124 aTransform.rotate( aRotation );
127 ScDrawView* pDrawView = rViewSh.GetScDrawView();
129 // #i123922# check if an existing object is selected; if yes, evtl. replace
130 // the graphic for a SdrGraphObj (including link state updates) or adapt the fill
131 // style for other objects
132 if(pDrawView)
134 const SdrMarkList& rMarkList = pDrawView->GetMarkedObjectList();
135 if (1 == rMarkList.GetMarkCount())
137 SdrObject* pPickObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
139 if(pPickObj)
141 //sal_Int8 nAction(DND_ACTION_MOVE);
142 //Point aPos;
143 const OUString aBeginUndo(ScResId(STR_UNDO_DRAGDROP));
145 SdrObject* pResult = pDrawView->ApplyGraphicToObject(
146 *pPickObj,
147 rGraphic1,
148 aBeginUndo,
149 bAsLink ? rFileName : OUString());
151 if(pResult)
153 // we are done; mark the modified/new object
154 pDrawView->MarkObj(pResult, pDrawView->GetSdrPageView());
155 return;
161 // set the size so the graphic has its original pixel size
162 // at 100% view scale (as in SetMarkedOriginalSize),
163 // instead of respecting the current view scale
164 MapMode aSourceMap = rGraphic.GetPrefMapMode();
165 MapMode aDestMap( MapUnit::Map100thMM );
166 if ( aSourceMap.GetMapUnit() == MapUnit::MapPixel && pDrawView )
168 Fraction aScaleX, aScaleY;
169 pDrawView->CalcNormScale( aScaleX, aScaleY );
170 aDestMap.SetScaleX(aScaleX);
171 aDestMap.SetScaleY(aScaleY);
173 Size aLogicSize = pWindow->LogicToLogic(
174 rGraphic.GetPrefSize(), &aSourceMap, &aDestMap );
176 // Limit size
178 SdrPageView* pPV = pView->GetSdrPageView();
179 SdrPage* pPage = pPV->GetPage();
180 Point aInsertPos = rViewSh.GetInsertPos();
182 ScViewData& rData = rViewSh.GetViewData();
183 if ( rData.GetDocument().IsNegativePage( rData.GetTabNo() ) )
184 aInsertPos.AdjustX( -(aLogicSize.Width()) ); // move position to left edge
186 ScLimitSizeOnDrawPage( aLogicSize, aInsertPos, pPage->GetSize() );
188 tools::Rectangle aRect ( aInsertPos, aLogicSize );
190 rtl::Reference<SdrGrafObj> pObj = new SdrGrafObj(
191 pView->getSdrModelFromSdrView(), // TTTT pView should be reference
192 rGraphic1,
193 aRect);
195 // calling SetGraphicLink here doesn't work
196 // Yes, due to the SdrObject had no SdrModel
197 // Path is no longer used as name for the graphics object
199 ScDrawLayer* pLayer = static_cast<ScDrawLayer*>(&pView->GetModel());
200 OUString aName = pLayer->GetNewGraphicName(); // "Graphics"
201 pObj->SetName(aName);
203 if (aAnchorType == SCA_CELL || aAnchorType == SCA_CELL_RESIZE)
204 ScDrawLayer::SetCellAnchoredFromPosition(*pObj, rData.GetDocument(), rData.GetTabNo(),
205 aAnchorType == SCA_CELL_RESIZE);
207 // don't select if from (dispatch) API, to allow subsequent cell operations
208 SdrInsertFlags nInsOptions = (bApi && !comphelper::LibreOfficeKit::isActive()) ? SdrInsertFlags::DONTMARK : SdrInsertFlags::NONE;
209 bool bSuccess = pView->InsertObjectAtView( pObj.get(), *pPV, nInsOptions );
211 // SetGraphicLink has to be used after inserting the object,
212 // otherwise an empty graphic is swapped in and the contact stuff crashes.
213 // See #i37444#.
214 if (bSuccess && bAsLink)
215 pObj->SetGraphicLink( rFileName );
218 #if HAVE_FEATURE_AVMEDIA
220 static void lcl_InsertMedia( const OUString& rMediaURL, bool bApi,
221 ScTabViewShell* pViewSh, const vcl::Window* pWindow, SdrView* pView,
222 const Size& rPrefSize, bool const bLink )
224 SdrPageView* pPV = pView->GetSdrPageView();
225 SdrPage* pPage = pPV->GetPage();
226 ScViewData& rData = pViewSh->GetViewData();
227 Point aInsertPos( pViewSh->GetInsertPos() );
228 Size aSize;
230 if( rPrefSize.Width() && rPrefSize.Height() )
232 if( pWindow )
233 aSize = pWindow->PixelToLogic(rPrefSize, MapMode(MapUnit::Map100thMM));
234 else
235 aSize = Application::GetDefaultDevice()->PixelToLogic(rPrefSize, MapMode(MapUnit::Map100thMM));
237 else
238 aSize = Size( 5000, 5000 );
240 ScLimitSizeOnDrawPage( aSize, aInsertPos, pPage->GetSize() );
242 if( rData.GetDocument().IsNegativePage( rData.GetTabNo() ) )
243 aInsertPos.AdjustX( -(aSize.Width()) );
245 OUString realURL;
246 if (bLink)
248 realURL = rMediaURL;
250 else
252 uno::Reference<frame::XModel> const xModel(
253 rData.GetDocument().GetDocumentShell()->GetModel());
254 bool const bRet = ::avmedia::EmbedMedia(xModel, rMediaURL, realURL);
255 if (!bRet) { return; }
258 rtl::Reference<SdrMediaObj> pObj = new SdrMediaObj(
259 *rData.GetDocument().GetDrawLayer(),
260 tools::Rectangle(aInsertPos, aSize));
262 pObj->setURL( realURL, u""_ustr/*TODO?*/ );
263 pView->InsertObjectAtView( pObj.get(), *pPV, bApi ? SdrInsertFlags::DONTMARK : SdrInsertFlags::NONE );
265 #endif
267 FuInsertGraphic::FuInsertGraphic( ScTabViewShell& rViewSh,
268 vcl::Window* pWin,
269 ScDrawView* pViewP,
270 SdrModel* pDoc,
271 SfxRequest& rReq )
272 : FuPoor(rViewSh, pWin, pViewP, pDoc, rReq)
274 const SfxItemSet* pReqArgs = rReq.GetArgs();
275 const SfxStringItem* pGraphicItem;
276 if ( pReqArgs &&
277 (pGraphicItem = pReqArgs->GetItemIfSet( SID_INSERT_GRAPHIC, true )) )
279 const OUString& aFileName = pGraphicItem->GetValue();
281 OUString aFilterName;
282 if ( const SfxStringItem* pFilterItem = pReqArgs->GetItemIfSet( FN_PARAM_FILTER ) )
283 aFilterName = pFilterItem->GetValue();
285 bool bAsLink = false;
286 const SfxPoolItem* pItem;
287 if ( pReqArgs->GetItemState( FN_PARAM_1, true, &pItem ) == SfxItemState::SET )
288 bAsLink = static_cast<const SfxBoolItem*>(pItem)->GetValue();
290 if (comphelper::LibreOfficeKit::isActive())
292 INetURLObject aURL(aFileName);
293 if (INetProtocol::File != aURL.GetProtocol() && HostFilter::isForbidden(aURL.GetHost()))
294 SfxLokHelper::sendNetworkAccessError("insert");
297 Graphic aGraphic;
298 ErrCode nError = GraphicFilter::LoadGraphic( aFileName, aFilterName, aGraphic, &GraphicFilter::GetGraphicFilter() );
299 if ( nError == ERRCODE_NONE )
301 lcl_InsertGraphic( aGraphic, aFileName, bAsLink, true, rViewSh, pWindow, pView );
304 else
306 SvxOpenGraphicDialog aDlg(ScResId(STR_INSERTGRAPHIC), pWin ? pWin->GetFrameWeld() : nullptr,
307 ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR);
309 Reference<ui::dialogs::XFilePickerControlAccess> xCtrlAcc = aDlg.GetFilePickerControlAccess();
310 sal_Int16 nSelect = 0;
311 Sequence<OUString> aListBoxEntries {
312 ScResId(STR_ANCHOR_TO_CELL),
313 ScResId(STR_ANCHOR_TO_CELL_RESIZE),
314 ScResId(STR_ANCHOR_TO_PAGE)
318 Any aTemplates(&aListBoxEntries, cppu::UnoType<decltype(aListBoxEntries)>::get());
320 xCtrlAcc->setValue(ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR,
321 ui::dialogs::ListboxControlActions::ADD_ITEMS, aTemplates);
323 Any aSelectPos(&nSelect, cppu::UnoType<decltype(nSelect)>::get());
324 xCtrlAcc->setValue(ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR,
325 ui::dialogs::ListboxControlActions::SET_SELECT_ITEM, aSelectPos);
327 catch (const Exception&)
329 SAL_WARN("sc", "control access failed");
332 if( aDlg.Execute() == ERRCODE_NONE )
334 Graphic aGraphic;
335 ErrCode nError = aDlg.GetGraphic(aGraphic);
336 if( nError == ERRCODE_NONE )
338 OUString aFileName = aDlg.GetPath();
339 const OUString& aFilterName = aDlg.GetDetectedFilter();
340 bool bAsLink = aDlg.IsAsLink();
342 // really store as link only?
343 if( bAsLink && officecfg::Office::Common::Misc::ShowLinkWarningDialog::get() )
345 SvxLinkWarningDialog aWarnDlg(pWin ? pWin->GetFrameWeld() : nullptr, aFileName);
346 if (aWarnDlg.run() != RET_OK)
347 bAsLink = false; // don't store as link
350 // Anchor to cell or to page?
351 Any aAnchorValue = xCtrlAcc->getValue(
352 ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR,
353 ui::dialogs::ListboxControlActions::GET_SELECTED_ITEM );
354 OUString sAnchor;
355 aAnchorValue >>= sAnchor;
357 ScAnchorType aAnchorType;
358 if (sAnchor == ScResId(STR_ANCHOR_TO_CELL))
359 aAnchorType = SCA_CELL;
360 else if (sAnchor == ScResId(STR_ANCHOR_TO_CELL_RESIZE))
361 aAnchorType = SCA_CELL_RESIZE;
362 else if (sAnchor == ScResId(STR_ANCHOR_TO_PAGE))
363 aAnchorType = SCA_PAGE;
364 else
365 aAnchorType = SCA_DONTKNOW;
367 lcl_InsertGraphic( aGraphic, aFileName, bAsLink, false, rViewSh, pWindow, pView, aAnchorType );
369 // append items for recording
370 rReq.AppendItem( SfxStringItem( SID_INSERT_GRAPHIC, aFileName ) );
371 rReq.AppendItem( SfxStringItem( FN_PARAM_FILTER, aFilterName ) );
372 rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bAsLink ) );
373 rReq.Done();
375 else
377 // error is handled in SvxOpenGraphicDialog::GetGraphic
383 FuInsertGraphic::~FuInsertGraphic()
387 FuInsertMedia::FuInsertMedia( ScTabViewShell& rViewSh,
388 vcl::Window* pWin,
389 ScDrawView* pViewP,
390 SdrModel* pDoc,
391 const SfxRequest& rReq ) :
392 FuPoor(rViewSh, pWin, pViewP, pDoc, rReq)
394 #if HAVE_FEATURE_AVMEDIA
395 OUString aURL;
396 const SfxItemSet* pReqArgs = rReq.GetArgs();
397 bool bAPI = false;
399 const SvxSizeItem* pSizeItem = rReq.GetArg<SvxSizeItem>(FN_PARAM_1);
400 const SfxBoolItem* pLinkItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_2);
401 const bool bSizeUnknown = !pSizeItem;
402 Size aPrefSize;
404 if( pReqArgs )
406 const SfxStringItem* pStringItem = dynamic_cast<const SfxStringItem*>( &pReqArgs->Get( rReq.GetSlot() ) );
408 if( pStringItem )
410 aURL = pStringItem->GetValue();
411 bAPI = aURL.getLength();
415 bool bLink(pLinkItem ? pLinkItem->GetValue() : true);
416 bool bInsertMedia = bAPI;
417 if (!bInsertMedia)
418 bInsertMedia = ::avmedia::MediaWindow::executeMediaURLDialog(pWin ? pWin->GetFrameWeld() : nullptr, aURL, &bLink);
419 if (!bInsertMedia)
420 return;
422 if (!bSizeUnknown)
424 aPrefSize = pSizeItem->GetSize();
426 else
428 if( pWin )
429 pWin->EnterWait();
431 css::uno::Reference<css::frame::XDispatchProvider> xDispatchProvider(rViewShell.GetViewFrame().GetFrame().GetFrameInterface(), css::uno::UNO_QUERY);
433 rtl::Reference<avmedia::PlayerListener> xPlayerListener(new avmedia::PlayerListener(
434 [xDispatchProvider, aURL, bLink](const css::uno::Reference<css::media::XPlayer>& rPlayer){
435 css::awt::Size aSize = rPlayer->getPreferredPlayerWindowSize();
436 avmedia::MediaWindow::dispatchInsertAVMedia(xDispatchProvider, aSize, aURL, bLink);
437 }));
439 const bool bIsMediaURL = ::avmedia::MediaWindow::isMediaURL(aURL, u""_ustr/*TODO?*/, true, xPlayerListener);
441 if( pWin )
442 pWin->LeaveWait();
444 if (!bIsMediaURL && !bAPI)
445 ::avmedia::MediaWindow::executeFormatErrorBox(pWindow ? pWindow->GetFrameWeld() : nullptr);
447 return;
450 if (pWin)
451 pWin->EnterWait();
453 lcl_InsertMedia(aURL, bAPI, &rViewSh, pWindow, pView, aPrefSize, bLink);
455 if (pWin)
456 pWin->LeaveWait();
457 #endif
460 FuInsertMedia::~FuInsertMedia()
464 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */