1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #include <svx/extedit.hxx>
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>
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>
35 #include <com/sun/star/system/SystemShellExecute.hpp>
36 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
38 using namespace css::uno
;
39 using namespace css::system
;
41 ExternalToolEdit::ExternalToolEdit()
45 ExternalToolEdit::~ExternalToolEdit()
49 void ExternalToolEdit::HandleCloseEvent(ExternalToolEdit
* pData
)
53 //import the temp file image stream into the newGraphic
54 boost::scoped_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream(pData
->m_aFileName
, StreamMode::READ
));
57 GraphicConverter::Import(*pStream
, newGraphic
);
59 // Now update the Graphic in the shell by re-reading from the newGraphic
60 pData
->Update( newGraphic
);
64 void ExternalToolEdit::StartListeningEvent()
66 //Start an event listener implemented via VCL timeout
67 assert(!m_pChecker
.get());
68 m_pChecker
.reset(new FileChangedChecker(
69 m_aFileName
, ::boost::bind(&HandleCloseEvent
, this)));
72 // self-destructing thread to make shell execute async
73 class ExternalToolEditThread
74 : public ::salhelper::Thread
77 OUString
const m_aFileName
;
79 virtual void execute() SAL_OVERRIDE
;
82 ExternalToolEditThread(OUString
const& rFileName
)
83 : ::salhelper::Thread("ExternalToolEdit")
84 , m_aFileName(rFileName
)
88 void ExternalToolEditThread::execute()
92 Reference
<XSystemShellExecute
> const xSystemShellExecute(
93 SystemShellExecute::create( ::comphelper::getProcessComponentContext()));
94 xSystemShellExecute
->execute(m_aFileName
, OUString(),
95 SystemShellExecuteFlags::URIS_ONLY
);
97 catch (Exception
const& e
)
99 SAL_WARN("svx", "ExternalToolEditThread: exception: " << e
.Message
);
103 void ExternalToolEdit::Edit(GraphicObject
const*const pGraphicObject
)
105 //Get the graphic from the GraphicObject
106 const Graphic aGraphic
= pGraphicObject
->GetGraphic();
108 //get the Preferred File Extension for this graphic
110 GraphicHelper::GetPreferredExtension(fExtension
, aGraphic
);
112 //Create the temp File
113 OUString aTempFileBase
;
114 OUString aTempFileName
;
116 osl::FileBase::RC rc
=
117 osl::FileBase::createTempFile(nullptr, nullptr, &aTempFileBase
);
118 if (osl::FileBase::E_None
!= rc
)
120 SAL_WARN("svx", "ExternalToolEdit::Edit: cannot create temp file");
124 // Move it to a file name with image extension properly set
125 aTempFileName
= aTempFileBase
+ "." + OUString(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
)
130 SAL_WARN("svx", "ExternalToolEdit::Edit: cannot move temp file");
134 //Write Graphic to the Temp File
135 GraphicFilter
& rGraphicFilter
= GraphicFilter::GetGraphicFilter();
136 sal_uInt16
nFilter(rGraphicFilter
.GetExportFormatNumberForShortName(fExtension
));
138 OUString
aFilter(rGraphicFilter
.GetExportFormatShortName(nFilter
));
140 // Write the Graphic to the file now
141 XOutBitmap::WriteGraphic(aGraphic
, aTempFileName
, aFilter
, XOUTBMP_USE_NATIVE_IF_POSSIBLE
| XOUTBMP_DONT_EXPAND_FILENAME
);
143 // There is a possibility that sPath extension might have been changed if the
144 // provided extension is not writable
145 m_aFileName
= aTempFileName
;
149 rtl::Reference
<ExternalToolEditThread
> const pThread(
150 new ExternalToolEditThread(m_aFileName
));
153 StartListeningEvent();
156 SdrExternalToolEdit::SdrExternalToolEdit(
157 FmFormView
*const pView
, SdrObject
*const pObj
)
161 assert(m_pObj
&& m_pView
);
162 StartListening(*m_pObj
->GetModel());
166 void SdrExternalToolEdit::Notify(SfxBroadcaster
& rBC
, SfxHint
const& rHint
)
168 SdrHint
const*const pSdrHint(dynamic_cast<SdrHint
const*>(&rHint
));
170 && (HINT_MODELCLEARED
== pSdrHint
->GetKind()
171 || (pSdrHint
->GetObject() == m_pObj
172 && HINT_OBJREMOVED
== pSdrHint
->GetKind())))
176 m_pChecker
.reset(); // avoid modifying deleted object
181 void SdrExternalToolEdit::Update(Graphic
& rGraphic
)
183 assert(m_pObj
&& m_pView
); // timer should be deleted by Notify() too
184 SdrPageView
*const pPageView
= m_pView
->GetSdrPageView();
187 SdrGrafObj
*const pNewObj(static_cast<SdrGrafObj
*>(m_pObj
->Clone()));
189 OUString
const description
=
190 m_pView
->GetDescriptionOfMarkedObjects() + " External Edit";
191 m_pView
->BegUndo(description
);
192 pNewObj
->SetGraphicObject(rGraphic
);
193 // set to new object before ReplaceObjectAtView() so that Notify() will
194 // not delete the running timer and crash
195 SdrObject
*const pOldObj
= m_pObj
;
197 m_pView
->ReplaceObjectAtView(pOldObj
, *pPageView
, pNewObj
);
202 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */