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 <sal/log.hxx>
23 #include <sfx2/opengrf.hxx>
24 #include <svx/svdograf.hxx>
25 #include <svx/svdomedia.hxx>
26 #include <svx/svdpage.hxx>
27 #include <svx/svdpagv.hxx>
28 #include <svx/svdview.hxx>
29 #include <svx/linkwarn.hxx>
30 #include <svx/svxids.hrc>
31 #include <vcl/graphicfilter.hxx>
32 #include <svl/stritem.hxx>
33 #include <svtools/miscopt.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, const OUString& rFilterName, 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  bAsLink ? rFilterName : OUString());
143 
144  if(pResult)
145  {
146  // we are done; mark the modified/new object
147  pDrawView->MarkObj(pResult, pDrawView->GetSdrPageView());
148  return;
149  }
150  }
151  }
152 
153  // set the size so the graphic has its original pixel size
154  // at 100% view scale (as in SetMarkedOriginalSize),
155  // instead of respecting the current view scale
156  MapMode aSourceMap = rGraphic.GetPrefMapMode();
157  MapMode aDestMap( MapUnit::Map100thMM );
158  if ( aSourceMap.GetMapUnit() == MapUnit::MapPixel && pDrawView )
159  {
160  Fraction aScaleX, aScaleY;
161  pDrawView->CalcNormScale( aScaleX, aScaleY );
162  aDestMap.SetScaleX(aScaleX);
163  aDestMap.SetScaleY(aScaleY);
164  }
165  Size aLogicSize = pWindow->LogicToLogic(
166  rGraphic.GetPrefSize(), &aSourceMap, &aDestMap );
167 
168  // Limit size
169 
170  SdrPageView* pPV = pView->GetSdrPageView();
171  SdrPage* pPage = pPV->GetPage();
172  Point aInsertPos = rViewSh.GetInsertPos();
173 
174  ScViewData& rData = rViewSh.GetViewData();
175  if ( rData.GetDocument().IsNegativePage( rData.GetTabNo() ) )
176  aInsertPos.AdjustX( -(aLogicSize.Width()) ); // move position to left edge
177 
178  ScLimitSizeOnDrawPage( aLogicSize, aInsertPos, pPage->GetSize() );
179 
180  tools::Rectangle aRect ( aInsertPos, aLogicSize );
181 
182  SdrGrafObj* pObj = new SdrGrafObj(
183  pView->getSdrModelFromSdrView(), // TTTT pView should be reference
184  rGraphic1,
185  aRect);
186 
187  // calling SetGraphicLink here doesn't work
188  // Yes, due to the SdrObject had no SdrModel
189  // Path is no longer used as name for the graphics object
190 
191  ScDrawLayer* pLayer = static_cast<ScDrawLayer*>(pView->GetModel());
192  OUString aName = pLayer->GetNewGraphicName(); // "Graphics"
193  pObj->SetName(aName);
194 
195  if (aAnchorType == SCA_CELL || aAnchorType == SCA_CELL_RESIZE)
197  aAnchorType == SCA_CELL_RESIZE);
198 
199  // don't select if from (dispatch) API, to allow subsequent cell operations
200  SdrInsertFlags nInsOptions = bApi ? SdrInsertFlags::DONTMARK : SdrInsertFlags::NONE;
201  bool bSuccess = pView->InsertObjectAtView( pObj, *pPV, nInsOptions );
202 
203  // SetGraphicLink has to be used after inserting the object,
204  // otherwise an empty graphic is swapped in and the contact stuff crashes.
205  // See #i37444#.
206  if (bSuccess && bAsLink)
207  pObj->SetGraphicLink( rFileName, ""/*TODO?*/, rFilterName );
208 }
209 
210 static void lcl_InsertMedia( const OUString& rMediaURL, bool bApi,
211  ScTabViewShell* pViewSh, const vcl::Window* pWindow, SdrView* pView,
212  const Size& rPrefSize, bool const bLink )
213 {
214  SdrPageView* pPV = pView->GetSdrPageView();
215  SdrPage* pPage = pPV->GetPage();
216  ScViewData& rData = pViewSh->GetViewData();
217  Point aInsertPos( pViewSh->GetInsertPos() );
218  Size aSize;
219 
220  if( rPrefSize.Width() && rPrefSize.Height() )
221  {
222  if( pWindow )
223  aSize = pWindow->PixelToLogic(rPrefSize, MapMode(MapUnit::Map100thMM));
224  else
225  aSize = Application::GetDefaultDevice()->PixelToLogic(rPrefSize, MapMode(MapUnit::Map100thMM));
226  }
227  else
228  aSize = Size( 5000, 5000 );
229 
230  ScLimitSizeOnDrawPage( aSize, aInsertPos, pPage->GetSize() );
231 
232  if( rData.GetDocument().IsNegativePage( rData.GetTabNo() ) )
233  aInsertPos.AdjustX( -(aSize.Width()) );
234 
235  OUString realURL;
236  if (bLink)
237  {
238  realURL = rMediaURL;
239  }
240  else
241  {
242  uno::Reference<frame::XModel> const xModel(
243  rData.GetDocument().GetDocumentShell()->GetModel());
244 #if HAVE_FEATURE_AVMEDIA
245  bool const bRet = ::avmedia::EmbedMedia(xModel, rMediaURL, realURL);
246  if (!bRet) { return; }
247 #else
248  return;
249 #endif
250  }
251 
252  SdrMediaObj* pObj = new SdrMediaObj(
253  *rData.GetDocument().GetDrawLayer(),
254  tools::Rectangle(aInsertPos, aSize));
255 
256  pObj->setURL( realURL, ""/*TODO?*/ );
257  pView->InsertObjectAtView( pObj, *pPV, bApi ? SdrInsertFlags::DONTMARK : SdrInsertFlags::NONE );
258 }
259 
261  vcl::Window* pWin,
262  ScDrawView* pViewP,
263  SdrModel* pDoc,
264  SfxRequest& rReq )
265  : FuPoor(rViewSh, pWin, pViewP, pDoc, rReq)
266 {
267  const SfxItemSet* pReqArgs = rReq.GetArgs();
268  const SfxPoolItem* pItem;
269  if ( pReqArgs &&
270  pReqArgs->GetItemState( SID_INSERT_GRAPHIC, true, &pItem ) == SfxItemState::SET )
271  {
272  OUString aFileName = static_cast<const SfxStringItem*>(pItem)->GetValue();
273 
274  OUString aFilterName;
275  if ( pReqArgs->GetItemState( FN_PARAM_FILTER, true, &pItem ) == SfxItemState::SET )
276  aFilterName = static_cast<const SfxStringItem*>(pItem)->GetValue();
277 
278  bool bAsLink = false;
279  if ( pReqArgs->GetItemState( FN_PARAM_1, true, &pItem ) == SfxItemState::SET )
280  bAsLink = static_cast<const SfxBoolItem*>(pItem)->GetValue();
281 
282  Graphic aGraphic;
283  ErrCode nError = GraphicFilter::LoadGraphic( aFileName, aFilterName, aGraphic, &GraphicFilter::GetGraphicFilter() );
284  if ( nError == ERRCODE_NONE )
285  {
286  lcl_InsertGraphic( aGraphic, aFileName, aFilterName, bAsLink, true, rViewSh, pWindow, pView );
287  }
288  }
289  else
290  {
291  SvxOpenGraphicDialog aDlg(ScResId(STR_INSERTGRAPHIC), pWin ? pWin->GetFrameWeld() : nullptr,
292  ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR);
293 
294  Reference<ui::dialogs::XFilePickerControlAccess> xCtrlAcc = aDlg.GetFilePickerControlAccess();
295  sal_Int16 nSelect = 0;
296  Sequence<OUString> aListBoxEntries {
297  ScResId(STR_ANCHOR_TO_CELL),
298  ScResId(STR_ANCHOR_TO_CELL_RESIZE),
299  ScResId(STR_ANCHOR_TO_PAGE)
300  };
301  try
302  {
303  Any aTemplates(&aListBoxEntries, cppu::UnoType<decltype(aListBoxEntries)>::get());
304 
305  xCtrlAcc->setValue(ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR,
306  ui::dialogs::ListboxControlActions::ADD_ITEMS, aTemplates);
307 
308  Any aSelectPos(&nSelect, cppu::UnoType<decltype(nSelect)>::get());
309  xCtrlAcc->setValue(ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR,
310  ui::dialogs::ListboxControlActions::SET_SELECT_ITEM, aSelectPos);
311  }
312  catch (const Exception&)
313  {
314  SAL_WARN("sc", "control access failed");
315  }
316 
317  if( aDlg.Execute() == ERRCODE_NONE )
318  {
319  Graphic aGraphic;
320  ErrCode nError = aDlg.GetGraphic(aGraphic);
321  if( nError == ERRCODE_NONE )
322  {
323  OUString aFileName = aDlg.GetPath();
324  const OUString& aFilterName = aDlg.GetDetectedFilter();
325  bool bAsLink = aDlg.IsAsLink();
326 
327  // really store as link only?
328  if( bAsLink && SvtMiscOptions().ShowLinkWarningDialog() )
329  {
330  SvxLinkWarningDialog aWarnDlg(pWin ? pWin->GetFrameWeld() : nullptr, aFileName);
331  if (aWarnDlg.run() != RET_OK)
332  bAsLink = false; // don't store as link
333  }
334 
335  // Anchor to cell or to page?
336  Any aAnchorValue = xCtrlAcc->getValue(
337  ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR,
338  ui::dialogs::ListboxControlActions::GET_SELECTED_ITEM );
339  OUString sAnchor;
340  aAnchorValue >>= sAnchor;
341 
342  ScAnchorType aAnchorType;
343  if (sAnchor == ScResId(STR_ANCHOR_TO_CELL))
344  aAnchorType = SCA_CELL;
345  else if (sAnchor == ScResId(STR_ANCHOR_TO_CELL_RESIZE))
346  aAnchorType = SCA_CELL_RESIZE;
347  else if (sAnchor == ScResId(STR_ANCHOR_TO_PAGE))
348  aAnchorType = SCA_PAGE;
349  else
350  aAnchorType = SCA_DONTKNOW;
351 
352  lcl_InsertGraphic( aGraphic, aFileName, aFilterName, bAsLink, false, rViewSh, pWindow, pView, aAnchorType );
353 
354  // append items for recording
355  rReq.AppendItem( SfxStringItem( SID_INSERT_GRAPHIC, aFileName ) );
356  rReq.AppendItem( SfxStringItem( FN_PARAM_FILTER, aFilterName ) );
357  rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bAsLink ) );
358  rReq.Done();
359  }
360  else
361  {
362  // error is handled in SvxOpenGraphicDialog::GetGraphic
363  }
364  }
365  }
366 }
367 
369 {
370 }
371 
373  vcl::Window* pWin,
374  ScDrawView* pViewP,
375  SdrModel* pDoc,
376  const SfxRequest& rReq ) :
377  FuPoor(rViewSh, pWin, pViewP, pDoc, rReq)
378 {
379  OUString aURL;
380  const SfxItemSet* pReqArgs = rReq.GetArgs();
381  bool bAPI = false;
382 
383  if( pReqArgs )
384  {
385  const SfxStringItem* pStringItem = dynamic_cast<const SfxStringItem*>( &pReqArgs->Get( rReq.GetSlot() ) );
386 
387  if( pStringItem )
388  {
389  aURL = pStringItem->GetValue();
390  bAPI = aURL.getLength();
391  }
392  }
393 
394  bool bLink(true);
395  bool bInsertMedia = bAPI;
396 #if HAVE_FEATURE_AVMEDIA
397  if (!bInsertMedia)
398  bInsertMedia = ::avmedia::MediaWindow::executeMediaURLDialog(pWin ? pWin->GetFrameWeld() : nullptr, aURL, &bLink);
399 #endif
400  if (!bInsertMedia)
401  return;
402 
403  Size aPrefSize;
404 
405  if( pWin )
406  pWin->EnterWait();
407 
408 #if HAVE_FEATURE_AVMEDIA
409  if( !::avmedia::MediaWindow::isMediaURL( aURL, ""/*TODO?*/, true, &aPrefSize ) )
410  {
411  if( pWin )
412  pWin->LeaveWait();
413 
414  if( !bAPI )
416  }
417  else
418 #endif
419  {
420  lcl_InsertMedia( aURL, bAPI, &rViewSh, pWindow, pView, aPrefSize,
421  bLink );
422 
423  if( pWin )
424  pWin->LeaveWait();
425  }
426 }
427 
429 {
430 }
431 
432 /* 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:1002
void setWidth(tools::Long nWidth)
std::string GetValue
Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
virtual ~FuInsertGraphic() override
Definition: fuins1.cxx:368
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:210
ScViewData & GetViewData()
Definition: tabview.hxx:332
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:383
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1059
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:2040
void SetGraphicLink(const OUString &rFileName, const OUString &rReferer, const OUString &rFilterName)
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:95
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
FuInsertGraphic(ScTabViewShell &rViewSh, vcl::Window *pWin, ScDrawView *pView, SdrModel *pDoc, SfxRequest &rReq)
Definition: fuins1.cxx:260
Point PixelToLogic(const Point &rDevicePt) const
Size GetPrefSize() const
sal_uInt16 GetSlot() const
ScDrawView * GetScDrawView()
Definition: tabview.hxx:340
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
#define ERRCODE_NONE
MapMode GetPrefMapMode() const
SdrPage * GetPage() const
OUString aName
RET_OK
ScDrawView * pView
Definition: fupoor.hxx:43
SdrObject * ApplyGraphicToObject(SdrObject &rHitObject, const Graphic &rGraphic, const OUString &rBeginUndoText, const OUString &rFile, const OUString &rFilter)
Definition: drawview.cxx:1113
tools::Long Height() const
SdrObject * GetMarkedObjectByIndex(size_t nNum) const
SdrPageView * GetSdrPageView() const
FuInsertMedia(ScTabViewShell &rViewSh, vcl::Window *pWin, ScDrawView *pView, SdrModel *pDoc, const SfxRequest &rReq)
Definition: fuins1.cxx:372
bool read(Graphic const &rGraphic)
void setHeight(tools::Long nHeight)
static GraphicFilter & GetGraphicFilter()
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1058
void AppendItem(const SfxPoolItem &)
#define SAL_WARN(area, stream)
Point GetInsertPos() const
Definition: tabview.cxx:1663
void rotate(Degree10 aRotation)
SdrModel & getSdrModelFromSdrView() const
Reference< XModel > xModel
virtual ~FuInsertMedia() override
Definition: fuins1.cxx:428
bool MarkObj(const Point &rPnt, short nTol=-2, bool bToggle=false, bool bDeep=false)
static void lcl_InsertGraphic(const Graphic &rGraphic, const OUString &rFileName, const OUString &rFilterName, bool bAsLink, bool bApi, ScTabViewShell &rViewSh, const vcl::Window *pWindow, SdrView *pView, ScAnchorType aAnchorType=SCA_CELL)
Definition: fuins1.cxx:102
void LeaveWait()
void SetName(const OUString &rStr)
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)