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