LibreOffice Module svx (master)  1
extedit.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 
10 #include <svx/extedit.hxx>
11 
12 #include <vcl/graph.hxx>
13 #include <vcl/GraphicObject.hxx>
14 #include <vcl/cvtgrf.hxx>
15 #include <vcl/graphicfilter.hxx>
16 #include <svx/xoutbmp.hxx>
17 #include <svx/graphichelper.hxx>
18 #include <svx/svdpagv.hxx>
19 #include <svx/svdograf.hxx>
20 #include <svx/fmview.hxx>
21 #include <salhelper/thread.hxx>
22 #include <sal/log.hxx>
23 #include <osl/file.hxx>
25 #include <tools/diagnose_ex.h>
28 
29 #include <memory>
30 
31 #include <com/sun/star/system/SystemShellExecute.hpp>
32 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
33 
34 using namespace css::uno;
35 using namespace css::system;
36 
38 {
39 }
40 
42 {
43 }
44 
46 {
47  Graphic newGraphic;
48 
49  //import the temp file image stream into the newGraphic
50  std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(pData->m_aFileName, StreamMode::READ));
51  if(pStream)
52  {
53  GraphicConverter::Import(*pStream, newGraphic);
54 
55  // Now update the Graphic in the shell by re-reading from the newGraphic
56  pData->Update( newGraphic );
57  }
58 }
59 
61 {
62  //Start an event listener implemented via VCL timeout
63  assert(!m_pChecker);
64  m_pChecker.reset(new FileChangedChecker(
65  m_aFileName, [this] () { return HandleCloseEvent(this); }));
66 }
67 
68 namespace {
69 
70 // self-destructing thread to make shell execute async
71 class ExternalToolEditThread
72  : public ::salhelper::Thread
73 {
74 private:
75  OUString const m_aFileName;
76 
77  virtual void execute() override;
78 
79 public:
80  explicit ExternalToolEditThread(OUString const& rFileName)
81  : ::salhelper::Thread("ExternalToolEdit")
82  , m_aFileName(rFileName)
83  {}
84 };
85 
86 }
87 
88 void ExternalToolEditThread::execute()
89 {
90  try
91  {
92  Reference<XSystemShellExecute> const xSystemShellExecute(
93  SystemShellExecute::create( ::comphelper::getProcessComponentContext()));
94  xSystemShellExecute->execute(m_aFileName, OUString(),
95  SystemShellExecuteFlags::URIS_ONLY);
96  }
97  catch (Exception const&)
98  {
99  TOOLS_WARN_EXCEPTION("svx", "ExternalToolEditThread");
100  }
101 }
102 
103 void ExternalToolEdit::Edit(GraphicObject const*const pGraphicObject)
104 {
105  //Get the graphic from the GraphicObject
106  const Graphic& aGraphic = pGraphicObject->GetGraphic();
107 
108  //get the Preferred File Extension for this graphic
109  OUString fExtension;
110  GraphicHelper::GetPreferredExtension(fExtension, aGraphic);
111 
112  //Create the temp File
113  OUString aTempFileBase;
114  OUString aTempFileName;
115 
116  osl::FileBase::RC rc =
117  osl::FileBase::createTempFile(nullptr, nullptr, &aTempFileBase);
118  if (osl::FileBase::E_None != rc)
119  {
120  SAL_WARN("svx", "ExternalToolEdit::Edit: cannot create temp file");
121  return;
122  }
123 
124  // Move it to a file name with image extension properly set
125  aTempFileName = aTempFileBase + "." + fExtension;
126  // FIXME: this is pretty stupid, need a better osl temp file API
127  rc = osl::File::move(aTempFileBase, aTempFileName);
128  if (osl::FileBase::E_None != rc)
129  {
130  SAL_WARN("svx", "ExternalToolEdit::Edit: cannot move temp file");
131  return;
132  }
133 
134  //Write Graphic to the Temp File
136  sal_uInt16 nFilter(rGraphicFilter.GetExportFormatNumberForShortName(fExtension));
137 
138  OUString aFilter(rGraphicFilter.GetExportFormatShortName(nFilter));
139 
140  // Write the Graphic to the file now
142 
143  // There is a possibility that sPath extension might have been changed if the
144  // provided extension is not writable
145  m_aFileName = aTempFileName;
146 
147  //Create a thread
148 
150  new ExternalToolEditThread(m_aFileName));
151  pThread->launch();
152 
153  StartListeningEvent();
154 }
155 
157  FmFormView* pView,
158  SdrObject* pObj)
159 : m_pView(pView)
160  ,m_pObj(pObj)
161 {
162  assert(m_pObj && m_pView);
164 }
165 
166 
168 {
169  if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
170  return;
171  SdrHint const*const pSdrHint(static_cast<SdrHint const*>(&rHint));
172  if (SdrHintKind::ModelCleared == pSdrHint->GetKind()
173  || (pSdrHint->GetObject() == m_pObj
174  && SdrHintKind::ObjectRemoved == pSdrHint->GetKind()))
175  {
176  m_pView = nullptr;
177  m_pObj = nullptr;
178  m_pChecker.reset(); // avoid modifying deleted object
179  EndListening(rBC);
180  }
181 }
182 
184 {
185  assert(m_pObj && m_pView); // timer should be deleted by Notify() too
186  SdrPageView *const pPageView = m_pView->GetSdrPageView();
187  if (!pPageView)
188  return;
189 
190  SdrGrafObj *const pNewObj(static_cast<SdrGrafObj*>(m_pObj->CloneSdrObject(m_pObj->getSdrModelFromSdrObject())));
191  assert(pNewObj);
192  OUString const description =
193  m_pView->GetDescriptionOfMarkedObjects() + " External Edit";
194  m_pView->BegUndo(description);
195  pNewObj->SetGraphicObject(rGraphic);
196  // set to new object before ReplaceObjectAtView() so that Notify() will
197  // not delete the running timer and crash
198  SdrObject *const pOldObj = m_pObj;
199  m_pObj = pNewObj;
200  m_pView->ReplaceObjectAtView(pOldObj, *pPageView, pNewObj);
201  m_pView->EndUndo();
202 }
203 
204 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SdrHintKind GetKind() const
Definition: svdmodel.hxx:123
void ReplaceObjectAtView(SdrObject *pOldObj, SdrPageView &rPV, SdrObject *pNewObj, bool bMark=true)
Definition: svdedtv.cxx:1012
virtual SAL_DLLPRIVATE void Update(Graphic &) override
Definition: extedit.cxx:183
void BegUndo()
Definition: svdedtv.hxx:178
SfxHintId GetId() const
FmFormView * m_pView
Definition: extedit.hxx:50
static std::unique_ptr< SvStream > CreateStream(const OUString &rFileName, StreamMode eOpenMode, css::uno::Reference< css::awt::XWindow > xParentWin=nullptr)
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
static ErrCode WriteGraphic(const Graphic &rGraphic, OUString &rFileName, const OUString &rFilterName, const XOutFlags nFlags, const Size *pMtfSize_100TH_MM=nullptr, const css::uno::Sequence< css::beans::PropertyValue > *pFilterData=nullptr)
Definition: _xoutbmp.cxx:103
sal_uInt16 GetExportFormatNumberForShortName(std::u16string_view rShortName)
void EndUndo()
Definition: svdedtv.cxx:301
virtual SAL_DLLPRIVATE void Notify(SfxBroadcaster &, const SfxHint &) override
Definition: extedit.cxx:167
SdrObject * m_pObj
Definition: extedit.hxx:51
virtual ~ExternalToolEdit()
Definition: extedit.cxx:41
#define TOOLS_WARN_EXCEPTION(area, stream)
static void HandleCloseEvent(ExternalToolEdit *pData)
Definition: extedit.cxx:45
SdrExternalToolEdit(FmFormView *pView, SdrObject *pObj)
Definition: extedit.cxx:156
OUString const & GetDescriptionOfMarkedObjects() const
Definition: svdmrkv.hxx:260
void Edit(GraphicObject const *const pGraphic)
Definition: extedit.cxx:103
SdrModel & getSdrModelFromSdrObject() const
Definition: svdobj.cxx:273
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
This class represents an embedded or linked bitmap graphic object.
Definition: svdograf.hxx:77
Abstract DrawObject.
Definition: svdobj.hxx:260
static ErrCode Import(SvStream &rIStm, Graphic &rGraphic, ConvertDataFormat nFormat=ConvertDataFormat::Unknown)
OUString GetExportFormatShortName(sal_uInt16 nFormat)
void StartListeningEvent()
Definition: extedit.cxx:60
const Graphic & GetGraphic() const
virtual void Update(Graphic &aGraphic)=0
OUString m_aFileName
Definition: extedit.hxx:25
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
virtual SdrObject * CloneSdrObject(SdrModel &rTargetModel) const
Definition: svdobj.cxx:974
Reference< XComponentContext > getProcessComponentContext()
SdrPageView * GetSdrPageView() const
Definition: svdpntv.hxx:303
static GraphicFilter & GetGraphicFilter()
#define SAL_WARN(area, stream)
::std::unique_ptr< FileChangedChecker > m_pChecker
Definition: extedit.hxx:27
const SdrObject * GetObject() const
Definition: svdmodel.hxx:122