Bump version to 6.4-15
[LibreOffice.git] / svx / source / core / extedit.cxx
blobe1d31771c06d08c26ffbc934d9af9b41ab573b0b
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/.
8 */
10 #include <svx/extedit.hxx>
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>
30 #include <svtools/filechangedchecker.hxx>
31 #include <tools/diagnose_ex.h>
32 #include <unotools/ucbstreamhelper.hxx>
33 #include <comphelper/processfactory.hxx>
35 #include <memory>
37 #include <com/sun/star/system/SystemShellExecute.hpp>
38 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
40 using namespace css::uno;
41 using namespace css::system;
43 ExternalToolEdit::ExternalToolEdit()
47 ExternalToolEdit::~ExternalToolEdit()
51 void ExternalToolEdit::HandleCloseEvent(ExternalToolEdit* pData)
53 Graphic newGraphic;
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)
59 GraphicConverter::Import(*pStream, newGraphic);
61 // Now update the Graphic in the shell by re-reading from the newGraphic
62 pData->Update( newGraphic );
66 void ExternalToolEdit::StartListeningEvent()
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); }));
74 // self-destructing thread to make shell execute async
75 class ExternalToolEditThread
76 : public ::salhelper::Thread
78 private:
79 OUString const m_aFileName;
81 virtual void execute() override;
83 public:
84 explicit ExternalToolEditThread(OUString const& rFileName)
85 : ::salhelper::Thread("ExternalToolEdit")
86 , m_aFileName(rFileName)
90 void ExternalToolEditThread::execute()
92 try
94 Reference<XSystemShellExecute> const xSystemShellExecute(
95 SystemShellExecute::create( ::comphelper::getProcessComponentContext()));
96 xSystemShellExecute->execute(m_aFileName, OUString(),
97 SystemShellExecuteFlags::URIS_ONLY);
99 catch (Exception const&)
101 TOOLS_WARN_EXCEPTION("svx", "ExternalToolEditThread");
105 void ExternalToolEdit::Edit(GraphicObject const*const pGraphicObject)
107 //Get the graphic from the GraphicObject
108 const Graphic& aGraphic = pGraphicObject->GetGraphic();
110 //get the Preferred File Extension for this graphic
111 OUString fExtension;
112 GraphicHelper::GetPreferredExtension(fExtension, aGraphic);
114 //Create the temp File
115 OUString aTempFileBase;
116 OUString aTempFileName;
118 osl::FileBase::RC rc =
119 osl::FileBase::createTempFile(nullptr, nullptr, &aTempFileBase);
120 if (osl::FileBase::E_None != rc)
122 SAL_WARN("svx", "ExternalToolEdit::Edit: cannot create temp file");
123 return;
126 // Move it to a file name with image extension properly set
127 aTempFileName = aTempFileBase + "." + fExtension;
128 // FIXME: this is pretty stupid, need a better osl temp file API
129 rc = osl::File::move(aTempFileBase, aTempFileName);
130 if (osl::FileBase::E_None != rc)
132 SAL_WARN("svx", "ExternalToolEdit::Edit: cannot move temp file");
133 return;
136 //Write Graphic to the Temp File
137 GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
138 sal_uInt16 nFilter(rGraphicFilter.GetExportFormatNumberForShortName(fExtension));
140 OUString aFilter(rGraphicFilter.GetExportFormatShortName(nFilter));
142 // Write the Graphic to the file now
143 XOutBitmap::WriteGraphic(aGraphic, aTempFileName, aFilter, XOutFlags::UseNativeIfPossible | XOutFlags::DontExpandFilename);
145 // There is a possibility that sPath extension might have been changed if the
146 // provided extension is not writable
147 m_aFileName = aTempFileName;
149 //Create a thread
151 rtl::Reference<ExternalToolEditThread> const pThread(
152 new ExternalToolEditThread(m_aFileName));
153 pThread->launch();
155 StartListeningEvent();
158 SdrExternalToolEdit::SdrExternalToolEdit(
159 FmFormView* pView,
160 SdrObject* pObj)
161 : m_pView(pView)
162 ,m_pObj(pObj)
164 assert(m_pObj && m_pView);
165 StartListening(m_pObj->getSdrModelFromSdrObject());
169 void SdrExternalToolEdit::Notify(SfxBroadcaster & rBC, SfxHint const& rHint)
171 if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
172 return;
173 SdrHint const*const pSdrHint(static_cast<SdrHint const*>(&rHint));
174 if (SdrHintKind::ModelCleared == pSdrHint->GetKind()
175 || (pSdrHint->GetObject() == m_pObj
176 && SdrHintKind::ObjectRemoved == pSdrHint->GetKind()))
178 m_pView = nullptr;
179 m_pObj = nullptr;
180 m_pChecker.reset(); // avoid modifying deleted object
181 EndListening(rBC);
185 void SdrExternalToolEdit::Update(Graphic & rGraphic)
187 assert(m_pObj && m_pView); // timer should be deleted by Notify() too
188 SdrPageView *const pPageView = m_pView->GetSdrPageView();
189 if (pPageView)
191 SdrGrafObj *const pNewObj(static_cast<SdrGrafObj*>(m_pObj->CloneSdrObject(m_pObj->getSdrModelFromSdrObject())));
192 assert(pNewObj);
193 OUString const description =
194 m_pView->GetDescriptionOfMarkedObjects() + " External Edit";
195 m_pView->BegUndo(description);
196 pNewObj->SetGraphicObject(rGraphic);
197 // set to new object before ReplaceObjectAtView() so that Notify() will
198 // not delete the running timer and crash
199 SdrObject *const pOldObj = m_pObj;
200 m_pObj = pNewObj;
201 m_pView->ReplaceObjectAtView(pOldObj, *pPageView, pNewObj);
202 m_pView->EndUndo();
206 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */