Line data Source code
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/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 <svtools/grfmgr.hxx>
22 : #include <sfx2/viewfrm.hxx>
23 : #include <sfx2/bindings.hxx>
24 : #include <salhelper/thread.hxx>
25 : #include <osl/file.hxx>
26 : #include <osl/thread.hxx>
27 : #include <osl/process.h>
28 : #include <osl/time.h>
29 : #include <svtools/filechangedchecker.hxx>
30 : #include <unotools/ucbstreamhelper.hxx>
31 : #include <comphelper/processfactory.hxx>
32 : #include <boost/bind.hpp>
33 : #include <boost/scoped_ptr.hpp>
34 :
35 : #include <com/sun/star/system/SystemShellExecute.hpp>
36 : #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
37 :
38 : using namespace css::uno;
39 : using namespace css::system;
40 :
41 0 : ExternalToolEdit::ExternalToolEdit()
42 : {
43 0 : }
44 :
45 0 : ExternalToolEdit::~ExternalToolEdit()
46 : {
47 0 : }
48 :
49 0 : void ExternalToolEdit::HandleCloseEvent(ExternalToolEdit* pData)
50 : {
51 0 : Graphic newGraphic;
52 :
53 : //import the temp file image stream into the newGraphic
54 0 : boost::scoped_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(pData->m_aFileName, StreamMode::READ));
55 0 : if(pStream)
56 : {
57 0 : GraphicConverter::Import(*pStream, newGraphic);
58 :
59 : // Now update the Graphic in the shell by re-reading from the newGraphic
60 0 : pData->Update( newGraphic );
61 0 : }
62 0 : }
63 :
64 0 : void ExternalToolEdit::StartListeningEvent()
65 : {
66 : //Start an event listener implemented via VCL timeout
67 : assert(!m_pChecker.get());
68 : m_pChecker.reset(new FileChangedChecker(
69 0 : m_aFileName, ::boost::bind(&HandleCloseEvent, this)));
70 0 : }
71 :
72 : // self-destructing thread to make shell execute async
73 0 : class ExternalToolEditThread
74 : : public ::salhelper::Thread
75 : {
76 : private:
77 : OUString const m_aFileName;
78 :
79 : virtual void execute() SAL_OVERRIDE;
80 :
81 : public:
82 0 : explicit ExternalToolEditThread(OUString const& rFileName)
83 : : ::salhelper::Thread("ExternalToolEdit")
84 0 : , m_aFileName(rFileName)
85 0 : {}
86 : };
87 :
88 0 : void ExternalToolEditThread::execute()
89 : {
90 : try
91 : {
92 : Reference<XSystemShellExecute> const xSystemShellExecute(
93 0 : SystemShellExecute::create( ::comphelper::getProcessComponentContext()));
94 0 : xSystemShellExecute->execute(m_aFileName, OUString(),
95 0 : SystemShellExecuteFlags::URIS_ONLY);
96 : }
97 0 : catch (Exception const& e)
98 : {
99 : SAL_WARN("svx", "ExternalToolEditThread: exception: " << e.Message);
100 : }
101 0 : }
102 :
103 0 : void ExternalToolEdit::Edit(GraphicObject const*const pGraphicObject)
104 : {
105 : //Get the graphic from the GraphicObject
106 0 : const Graphic aGraphic = pGraphicObject->GetGraphic();
107 :
108 : //get the Preferred File Extension for this graphic
109 0 : OUString fExtension;
110 0 : GraphicHelper::GetPreferredExtension(fExtension, aGraphic);
111 :
112 : //Create the temp File
113 0 : OUString aTempFileBase;
114 0 : OUString aTempFileName;
115 :
116 : osl::FileBase::RC rc =
117 0 : osl::FileBase::createTempFile(nullptr, nullptr, &aTempFileBase);
118 0 : if (osl::FileBase::E_None != rc)
119 : {
120 : SAL_WARN("svx", "ExternalToolEdit::Edit: cannot create temp file");
121 0 : return;
122 : }
123 :
124 : // Move it to a file name with image extension properly set
125 0 : aTempFileName = aTempFileBase + "." + OUString(fExtension);
126 : // FIXME: this is pretty stupid, need a better osl temp file API
127 0 : rc = osl::File::move(aTempFileBase, aTempFileName);
128 0 : if (osl::FileBase::E_None != rc)
129 : {
130 : SAL_WARN("svx", "ExternalToolEdit::Edit: cannot move temp file");
131 0 : return;
132 : }
133 :
134 : //Write Graphic to the Temp File
135 0 : GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
136 0 : sal_uInt16 nFilter(rGraphicFilter.GetExportFormatNumberForShortName(fExtension));
137 :
138 0 : OUString aFilter(rGraphicFilter.GetExportFormatShortName(nFilter));
139 :
140 : // Write the Graphic to the file now
141 0 : XOutBitmap::WriteGraphic(aGraphic, aTempFileName, aFilter, XOUTBMP_USE_NATIVE_IF_POSSIBLE | XOUTBMP_DONT_EXPAND_FILENAME);
142 :
143 : // There is a possibility that sPath extension might have been changed if the
144 : // provided extension is not writable
145 0 : m_aFileName = aTempFileName;
146 :
147 : //Create a thread
148 :
149 : rtl::Reference<ExternalToolEditThread> const pThread(
150 0 : new ExternalToolEditThread(m_aFileName));
151 0 : pThread->launch();
152 :
153 0 : StartListeningEvent();
154 : }
155 :
156 0 : SdrExternalToolEdit::SdrExternalToolEdit(
157 : FmFormView *const pView, SdrObject *const pObj)
158 : : m_pView(pView)
159 0 : , m_pObj(pObj)
160 : {
161 : assert(m_pObj && m_pView);
162 0 : StartListening(*m_pObj->GetModel());
163 0 : }
164 :
165 :
166 0 : void SdrExternalToolEdit::Notify(SfxBroadcaster & rBC, SfxHint const& rHint)
167 : {
168 0 : SdrHint const*const pSdrHint(dynamic_cast<SdrHint const*>(&rHint));
169 0 : if (pSdrHint
170 0 : && (HINT_MODELCLEARED == pSdrHint->GetKind()
171 0 : || (pSdrHint->GetObject() == m_pObj
172 0 : && HINT_OBJREMOVED == pSdrHint->GetKind())))
173 : {
174 0 : m_pView = 0;
175 0 : m_pObj = 0;
176 0 : m_pChecker.reset(); // avoid modifying deleted object
177 0 : EndListening(rBC);
178 : }
179 0 : }
180 :
181 0 : void SdrExternalToolEdit::Update(Graphic & rGraphic)
182 : {
183 : assert(m_pObj && m_pView); // timer should be deleted by Notify() too
184 0 : SdrPageView *const pPageView = m_pView->GetSdrPageView();
185 0 : if (pPageView)
186 : {
187 0 : SdrGrafObj *const pNewObj(static_cast<SdrGrafObj*>(m_pObj->Clone()));
188 : assert(pNewObj);
189 : OUString const description =
190 0 : m_pView->GetDescriptionOfMarkedObjects() + " External Edit";
191 0 : m_pView->BegUndo(description);
192 0 : pNewObj->SetGraphicObject(rGraphic);
193 : // set to new object before ReplaceObjectAtView() so that Notify() will
194 : // not delete the running timer and crash
195 0 : SdrObject *const pOldObj = m_pObj;
196 0 : m_pObj = pNewObj;
197 0 : m_pView->ReplaceObjectAtView(pOldObj, *pPageView, pNewObj);
198 0 : m_pView->EndUndo();
199 : }
200 435 : }
201 :
202 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|