LibreOffice Module sc (master)  1
fuins1.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_features.h>
21 
22 #include <officecfg/Office/Common.hxx>
23 #include <sal/log.hxx>
24 #include <sfx2/opengrf.hxx>
25 #include <svx/svdograf.hxx>
26 #include <svx/svdomedia.hxx>
27 #include <svx/svdpage.hxx>
28 #include <svx/svdpagv.hxx>
29 #include <svx/svdview.hxx>
30 #include <svx/linkwarn.hxx>
31 #include <svx/svxids.hrc>
32 #include <vcl/graphicfilter.hxx>
33 #include <svl/stritem.hxx>
34 #include <avmedia/mediawindow.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/weld.hxx>
39 #include <fuinsert.hxx>
40 #include <tabvwsh.hxx>
41 #include <drwlayer.hxx>
42 #include <drawview.hxx>
43 #include <document.hxx>
44 #include <scresid.hxx>
45 #include <strings.hrc>
46 #include <globstr.hrc>
47 
48 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
49 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
50 #include <com/sun/star/ui/dialogs/ListboxControlActions.hpp>
51 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
52 #include <com/sun/star/uno/Sequence.hxx>
53 
54 using namespace css;
55 using namespace css::uno;
56 
57 void ScLimitSizeOnDrawPage( Size& rSize, Point& rPos, const Size& rPage )
58 {
59  if ( !rPage.Width() || !rPage.Height() )
60  return;
61 
62  Size aPageSize = rPage;
63  bool bNegative = aPageSize.Width() < 0;
64  if ( bNegative )
65  {
66  // make everything positive temporarily
67  aPageSize.setWidth( -aPageSize.Width() );
68  rPos.setX( -rPos.X() - rSize.Width() );
69  }
70 
71  if ( rSize.Width() > aPageSize.Width() || rSize.Height() > aPageSize.Height() )
72  {
73  double fX = aPageSize.Width() / static_cast<double>(rSize.Width());
74  double fY = aPageSize.Height() / static_cast<double>(rSize.Height());
75 
76  if ( fX < fY )
77  {
78  rSize.setWidth( aPageSize.Width() );
79  rSize.setHeight( static_cast<tools::Long>( rSize.Height() * fX ) );
80  }
81  else
82  {
83  rSize.setHeight( aPageSize.Height() );
84  rSize.setWidth( static_cast<tools::Long>( rSize.Width() * fY ) );
85  }
86 
87  if (!rSize.Width())
88  rSize.setWidth( 1 );
89  if (!rSize.Height())
90  rSize.setHeight( 1 );
91  }
92 
93  if ( rPos.X() + rSize.Width() > aPageSize.Width() )
94  rPos.setX( aPageSize.Width() - rSize.Width() );
95  if ( rPos.Y() + rSize.Height() > aPageSize.Height() )
96  rPos.setY( aPageSize.Height() - rSize.Height() );
97 
98  if ( bNegative )
99  rPos.setX( -rPos.X() - rSize.Width() ); // back to real position
100 }
101 
102 static void lcl_InsertGraphic( const Graphic& rGraphic,
103  const OUString& rFileName, bool bAsLink, bool bApi,
104  ScTabViewShell& rViewSh, const vcl::Window* pWindow, SdrView* pView,
105  ScAnchorType aAnchorType = SCA_CELL )
106 {
107  Graphic& rGraphic1 = const_cast<Graphic &>(rGraphic);
108  GraphicNativeMetadata aMetadata;
109  if ( aMetadata.read(rGraphic1) )
110  {
111  const Degree10 aRotation = aMetadata.getRotation();
112  if (aRotation)
113  {
114  std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(nullptr, VclMessageType::Question,VclButtonsType::YesNo,ScResId(STR_QUERYROTATION)));
115  if (xQueryBox->run() == RET_YES)
116  {
117  GraphicNativeTransform aTransform( rGraphic1 );
118  aTransform.rotate( aRotation );
119  }
120  }
121  }
122  ScDrawView* pDrawView = rViewSh.GetScDrawView();
123 
124  // #i123922# check if an existing object is selected; if yes, evtl. replace
125  // the graphic for a SdrGraphObj (including link state updates) or adapt the fill
126  // style for other objects
127  if(pDrawView && 1 == pDrawView->GetMarkedObjectCount())
128  {
129  SdrObject* pPickObj = pDrawView->GetMarkedObjectByIndex(0);
130 
131  if(pPickObj)
132  {
133  //sal_Int8 nAction(DND_ACTION_MOVE);
134  //Point aPos;
135  const OUString aBeginUndo(ScResId(STR_UNDO_DRAGDROP));
136 
137  SdrObject* pResult = pDrawView->ApplyGraphicToObject(
138  *pPickObj,
139  rGraphic1,
140  aBeginUndo,
141  bAsLink ? rFileName : OUString());
142 
143  if(pResult)
144  {
145  // we are done; mark the modified/new object
146  pDrawView->MarkObj(pResult, pDrawView->GetSdrPageView());
147  return;
148  }
149  }
150  }
151 
152  // set the size so the graphic has its original pixel size
153  // at 100% view scale (as in SetMarkedOriginalSize),
154  // instead of respecting the current view scale
155  MapMode aSourceMap = rGraphic.GetPrefMapMode();
156  MapMode aDestMap( MapUnit::Map100thMM );
157  if ( aSourceMap.GetMapUnit() == MapUnit::MapPixel && pDrawView )
158  {
159  Fraction aScaleX, aScaleY;
160  pDrawView->CalcNormScale( aScaleX, aScaleY );
161  aDestMap.SetScaleX(aScaleX);
162  aDestMap.SetScaleY(aScaleY);
163  }
164  Size aLogicSize = pWindow->LogicToLogic(
165  rGraphic.GetPrefSize(), &aSourceMap, &aDestMap );
166 
167  // Limit size
168 
169  SdrPageView* pPV = pView->GetSdrPageView();
170  SdrPage* pPage = pPV->GetPage();
171  Point aInsertPos = rViewSh.GetInsertPos();
172 
173  ScViewData& rData = rViewSh.GetViewData();
174  if ( rData.GetDocument().IsNegativePage( rData.GetTabNo() ) )
175  aInsertPos.AdjustX( -(aLogicSize.Width()) ); // move position to left edge
176 
177  ScLimitSizeOnDrawPage( aLogicSize, aInsertPos, pPage->GetSize() );
178 
179  tools::Rectangle aRect ( aInsertPos, aLogicSize );
180 
181  SdrGrafObj* pObj = new SdrGrafObj(
182  pView->getSdrModelFromSdrView(), // TTTT pView should be reference
183  rGraphic1,
184  aRect);
185 
186  // calling SetGraphicLink here doesn't work
187  // Yes, due to the SdrObject had no SdrModel
188  // Path is no longer used as name for the graphics object
189 
190  ScDrawLayer* pLayer = static_cast<ScDrawLayer*>(pView->GetModel());
191  OUString aName = pLayer->GetNewGraphicName(); // "Graphics"
192  pObj->SetName(aName);
193 
194  if (aAnchorType == SCA_CELL || aAnchorType == SCA_CELL_RESIZE)
196  aAnchorType == SCA_CELL_RESIZE);
197 
198  // don't select if from (dispatch) API, to allow subsequent cell operations
199  SdrInsertFlags nInsOptions = bApi ? SdrInsertFlags::DONTMARK : SdrInsertFlags::NONE;
200  bool bSuccess = pView->InsertObjectAtView( pObj, *pPV, nInsOptions );
201 
202  // SetGraphicLink has to be used after inserting the object,
203  // otherwise an empty graphic is swapped in and the contact stuff crashes.
204  // See #i37444#.
205  if (bSuccess && bAsLink)
206  pObj->SetGraphicLink( rFileName );
207 }
208 
209 static void lcl_InsertMedia( const OUString& rMediaURL, bool bApi,
210  ScTabViewShell* pViewSh, const vcl::Window* pWindow, SdrView* pView,
211  const Size& rPrefSize, bool const bLink )
212 {
213  SdrPageView* pPV = pView->GetSdrPageView();
214  SdrPage* pPage = pPV->GetPage();
215  ScViewData& rData = pViewSh->GetViewData();
216  Point aInsertPos( pViewSh->GetInsertPos() );
217  Size aSize;
218 
219  if( rPrefSize.Width() && rPrefSize.Height() )
220  {
221  if( pWindow )
222  aSize = pWindow->PixelToLogic(rPrefSize, MapMode(MapUnit::Map100thMM));
223  else
224  aSize = Application::GetDefaultDevice()->PixelToLogic(rPrefSize, MapMode(MapUnit::Map100thMM));
225  }
226  else
227  aSize = Size( 5000, 5000 );
228 
229  ScLimitSizeOnDrawPage( aSize, aInsertPos, pPage->GetSize() );
230 
231  if( rData.GetDocument().IsNegativePage( rData.GetTabNo() ) )
232  aInsertPos.AdjustX( -(aSize.Width()) );
233 
234  OUString realURL;
235  if (bLink)
236  {
237  realURL = rMediaURL;
238  }
239  else
240  {
241  uno::Reference<frame::XModel> const xModel(
242  rData.GetDocument().GetDocumentShell()->GetModel());
243 #if HAVE_FEATURE_AVMEDIA
244  bool const bRet = ::avmedia::EmbedMedia(xModel, rMediaURL, realURL);
245  if (!bRet) { return; }
246 #else
247  return;
248 #endif
249  }
250 
251  SdrMediaObj* pObj = new SdrMediaObj(
252  *rData.GetDocument().GetDrawLayer(),
253  tools::Rectangle(aInsertPos, aSize));
254 
255  pObj->setURL( realURL, ""/*TODO?*/ );
256  pView->InsertObjectAtView( pObj, *pPV, bApi ? SdrInsertFlags::DONTMARK : SdrInsertFlags::NONE );
257 }
258 
260  vcl::Window* pWin,
261  ScDrawView* pViewP,
262  SdrModel* pDoc,
263  SfxRequest& rReq )
264  : FuPoor(rViewSh, pWin, pViewP, pDoc, rReq)
265 {
266  const SfxItemSet* pReqArgs = rReq.GetArgs();
267  const SfxPoolItem* pItem;
268  if ( pReqArgs &&
269  pReqArgs->GetItemState( SID_INSERT_GRAPHIC, true, &pItem ) == SfxItemState::SET )
270  {
271  OUString aFileName = static_cast<const SfxStringItem*>(pItem)->GetValue();
272 
273  OUString aFilterName;
274  if ( pReqArgs->GetItemState( FN_PARAM_FILTER, true, &pItem ) == SfxItemState::SET )
275  aFilterName = static_cast<const SfxStringItem*>(pItem)->GetValue();
276 
277  bool bAsLink = false;
278  if ( pReqArgs->GetItemState( FN_PARAM_1, true, &pItem ) == SfxItemState::SET )
279  bAsLink = static_cast<const SfxBoolItem*>(pItem)->GetValue();
280 
281  Graphic aGraphic;
282  ErrCode nError = GraphicFilter::LoadGraphic( aFileName, aFilterName, aGraphic, &GraphicFilter::GetGraphicFilter() );
283  if ( nError == ERRCODE_NONE )
284  {
285  lcl_InsertGraphic( aGraphic, aFileName, bAsLink, true, rViewSh, pWindow, pView );
286  }
287  }
288  else
289  {
290  SvxOpenGraphicDialog aDlg(ScResId(STR_INSERTGRAPHIC), pWin ? pWin->GetFrameWeld() : nullptr,
291  ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR);
292 
293  Reference<ui::dialogs::XFilePickerControlAccess> xCtrlAcc = aDlg.GetFilePickerControlAccess();
294  sal_Int16 nSelect = 0;
295  Sequence<OUString> aListBoxEntries {
296  ScResId(STR_ANCHOR_TO_CELL),
297  ScResId(STR_ANCHOR_TO_CELL_RESIZE),
298  ScResId(STR_ANCHOR_TO_PAGE)
299  };
300  try
301  {
302  Any aTemplates(&aListBoxEntries, cppu::UnoType<decltype(aListBoxEntries)>::get());
303 
304  xCtrlAcc->setValue(ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR,
305  ui::dialogs::ListboxControlActions::ADD_ITEMS, aTemplates);
306 
307  Any aSelectPos(&nSelect, cppu::UnoType<decltype(nSelect)>::get());
308  xCtrlAcc->setValue(ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR,
309  ui::dialogs::ListboxControlActions::SET_SELECT_ITEM, aSelectPos);
310  }
311  catch (const Exception&)
312  {
313  SAL_WARN("sc", "control access failed");
314  }
315 
316  if( aDlg.Execute() == ERRCODE_NONE )
317  {
318  Graphic aGraphic;
319  ErrCode nError = aDlg.GetGraphic(aGraphic);
320  if( nError == ERRCODE_NONE )
321  {
322  OUString aFileName = aDlg.GetPath();
323  const OUString& aFilterName = aDlg.GetDetectedFilter();
324  bool bAsLink = aDlg.IsAsLink();
325 
326  // really store as link only?
327  if( bAsLink && officecfg::Office::Common::Misc::ShowLinkWarningDialog::get() )
328  {
329  SvxLinkWarningDialog aWarnDlg(pWin ? pWin->GetFrameWeld() : nullptr, aFileName);
330  if (aWarnDlg.run() != RET_OK)
331  bAsLink = false; // don't store as link
332  }
333 
334  // Anchor to cell or to page?
335  Any aAnchorValue = xCtrlAcc->getValue(
336  ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR,
337  ui::dialogs::ListboxControlActions::GET_SELECTED_ITEM );
338  OUString sAnchor;
339  aAnchorValue >>= sAnchor;
340 
341  ScAnchorType aAnchorType;
342  if (sAnchor == ScResId(STR_ANCHOR_TO_CELL))
343  aAnchorType = SCA_CELL;
344  else if (sAnchor == ScResId(STR_ANCHOR_TO_CELL_RESIZE))
345  aAnchorType = SCA_CELL_RESIZE;
346  else if (sAnchor == ScResId(STR_ANCHOR_TO_PAGE))
347  aAnchorType = SCA_PAGE;
348  else
349  aAnchorType = SCA_DONTKNOW;
350 
351  lcl_InsertGraphic( aGraphic, aFileName, bAsLink, false, rViewSh, pWindow, pView, aAnchorType );
352 
353  // append items for recording
354  rReq.AppendItem( SfxStringItem( SID_INSERT_GRAPHIC, aFileName ) );
355  rReq.AppendItem( SfxStringItem( FN_PARAM_FILTER, aFilterName ) );
356  rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bAsLink ) );
357  rReq.Done();
358  }
359  else
360  {
361  // error is handled in SvxOpenGraphicDialog::GetGraphic
362  }
363  }
364  }
365 }
366 
368 {
369 }
370 
372  vcl::Window* pWin,
373  ScDrawView* pViewP,
374  SdrModel* pDoc,
375  const SfxRequest& rReq ) :
376  FuPoor(rViewSh, pWin, pViewP, pDoc, rReq)
377 {
378  OUString aURL;
379  const SfxItemSet* pReqArgs = rReq.GetArgs();
380  bool bAPI = false;
381 
382  if( pReqArgs )
383  {
384  const SfxStringItem* pStringItem = dynamic_cast<const SfxStringItem*>( &pReqArgs->Get( rReq.GetSlot() ) );
385 
386  if( pStringItem )
387  {
388  aURL = pStringItem->GetValue();
389  bAPI = aURL.getLength();
390  }
391  }
392 
393  bool bLink(true);
394  bool bInsertMedia = bAPI;
395 #if HAVE_FEATURE_AVMEDIA
396  if (!bInsertMedia)
397  bInsertMedia = ::avmedia::MediaWindow::executeMediaURLDialog(pWin ? pWin->GetFrameWeld() : nullptr, aURL, &bLink);
398 #endif
399  if (!bInsertMedia)
400  return;
401 
402  Size aPrefSize;
403 
404  if( pWin )
405  pWin->EnterWait();
406 
407 #if HAVE_FEATURE_AVMEDIA
408  if( !::avmedia::MediaWindow::isMediaURL( aURL, ""/*TODO?*/, true, &aPrefSize ) )
409  {
410  if( pWin )
411  pWin->LeaveWait();
412 
413  if( !bAPI )
415  }
416  else
417 #endif
418  {
419  lcl_InsertMedia( aURL, bAPI, &rViewSh, pWindow, pView, aPrefSize,
420  bLink );
421 
422  if( pWin )
423  pWin->LeaveWait();
424  }
425 }
426 
428 {
429 }
430 
431 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
URL aURL
static void executeFormatErrorBox(weld::Window *pParent)
SC_DLLPUBLIC bool IsNegativePage(SCTAB nTab) const
Definition: document.cxx:1000
void setWidth(tools::Long nWidth)
std::string GetValue
Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
void SetName(const OUString &rStr, const bool bSetChanged=true)
virtual ~FuInsertGraphic() override
Definition: fuins1.cxx:367
void CalcNormScale(Fraction &rFractX, Fraction &rFractY) const
Definition: drawvie4.cxx:411
void EnterWait()
const ContentProperties & rData
SCTAB GetTabNo() const
Definition: viewdata.hxx:395
void Done(bool bRemove=false)
ScDocument & GetDocument() const
Definition: viewdata.hxx:380
css::uno::Reference< css::frame::XModel > GetModel() const
const SfxItemSet * GetArgs() const
css::uno::Reference< css::ui::dialogs::XFilePickerControlAccess > const & GetFilePickerControlAccess() const
bool InsertObjectAtView(SdrObject *pObj, SdrPageView &rPV, SdrInsertFlags nOptions=SdrInsertFlags::NONE)
Degree10 getRotation() const
static OutputDevice * GetDefaultDevice()
weld::Window * GetFrameWeld() const
RET_YES
static void lcl_InsertMedia(const OUString &rMediaURL, bool bApi, ScTabViewShell *pViewSh, const vcl::Window *pWindow, SdrView *pView, const Size &rPrefSize, bool const bLink)
Definition: fuins1.cxx:209
ScViewData & GetViewData()
Definition: tabview.hxx:334
static bool executeMediaURLDialog(weld::Window *pParent, OUString &rURL, bool *const o_pbLink)
static ErrCode LoadGraphic(const OUString &rPath, const OUString &rFilter, Graphic &rGraphic, GraphicFilter *pFilter=nullptr, sal_uInt16 *pDeterminedFormat=nullptr)
ScAnchorType
Definition: global.hxx:384
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1056
void SetScaleX(const Fraction &rScaleX)
void setURL(const OUString &rURL, const OUString &rReferer, const OUString &rMimeType=OUString())
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
size_t GetMarkedObjectCount() const
static void SetCellAnchoredFromPosition(SdrObject &rObj, const ScDocument &rDoc, SCTAB nTab, bool bResizeWithCell)
Definition: drwlayer.cxx:2191
Size GetSize() const
void ScLimitSizeOnDrawPage(Size &rSize, Point &rPos, const Size &rPage)
Definition: fuins1.cxx:57
const OUString & GetValue() const
tools::Long Width() const
OUString ScResId(const char *pId)
Definition: scdll.cxx:89
void SetScaleY(const Fraction &rScaleY)
MapUnit GetMapUnit() const
static bool isMediaURL(const OUString &rURL, const OUString &rReferer, bool bDeep=false, Size *pPreferredSizePixel=nullptr)
Base class for all functions.
Definition: fupoor.hxx:40
SdrInsertFlags
void SetGraphicLink(const OUString &rFileName)
FuInsertGraphic(ScTabViewShell &rViewSh, vcl::Window *pWin, ScDrawView *pView, SdrModel *pDoc, SfxRequest &rReq)
Definition: fuins1.cxx:259
Point PixelToLogic(const Point &rDevicePt) const
Size GetPrefSize() const
sal_uInt16 GetSlot() const
ScDrawView * GetScDrawView()
Definition: tabview.hxx:342
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
#define ERRCODE_NONE
MapMode GetPrefMapMode() const
SdrPage * GetPage() const
static void lcl_InsertGraphic(const Graphic &rGraphic, const OUString &rFileName, bool bAsLink, bool bApi, ScTabViewShell &rViewSh, const vcl::Window *pWindow, SdrView *pView, ScAnchorType aAnchorType=SCA_CELL)
Definition: fuins1.cxx:102
OUString aName
RET_OK
ScDrawView * pView
Definition: fupoor.hxx:43
tools::Long Height() const
SdrObject * GetMarkedObjectByIndex(size_t nNum) const
SdrPageView * GetSdrPageView() const
SdrObject * ApplyGraphicToObject(SdrObject &rHitObject, const Graphic &rGraphic, const OUString &rBeginUndoText, const OUString &rFile)
Definition: drawview.cxx:1113
FuInsertMedia(ScTabViewShell &rViewSh, vcl::Window *pWin, ScDrawView *pView, SdrModel *pDoc, const SfxRequest &rReq)
Definition: fuins1.cxx:371
bool read(Graphic const &rGraphic)
void setHeight(tools::Long nHeight)
static GraphicFilter & GetGraphicFilter()
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1055
void AppendItem(const SfxPoolItem &)
#define SAL_WARN(area, stream)
Point GetInsertPos() const
Definition: tabview.cxx:1667
void rotate(Degree10 aRotation)
SdrModel & getSdrModelFromSdrView() const
Reference< XModel > xModel
virtual ~FuInsertMedia() override
Definition: fuins1.cxx:427
bool MarkObj(const Point &rPnt, short nTol=-2, bool bToggle=false, bool bDeep=false)
void LeaveWait()
SdrModel * GetModel() const
VclPtr< vcl::Window > pWindow
Definition: fupoor.hxx:45
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)