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