summaryrefslogtreecommitdiffstats
path: root/svx/source/core/extedit.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/core/extedit.cxx')
-rw-r--r--svx/source/core/extedit.cxx204
1 files changed, 204 insertions, 0 deletions
diff --git a/svx/source/core/extedit.cxx b/svx/source/core/extedit.cxx
new file mode 100644
index 000000000..3225e47f0
--- /dev/null
+++ b/svx/source/core/extedit.cxx
@@ -0,0 +1,204 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <svx/extedit.hxx>
+
+#include <vcl/graph.hxx>
+#include <vcl/GraphicObject.hxx>
+#include <vcl/cvtgrf.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <svx/xoutbmp.hxx>
+#include <svx/graphichelper.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/fmview.hxx>
+#include <salhelper/thread.hxx>
+#include <sal/log.hxx>
+#include <osl/file.hxx>
+#include <svtools/filechangedchecker.hxx>
+#include <tools/diagnose_ex.h>
+#include <unotools/ucbstreamhelper.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <memory>
+
+#include <com/sun/star/system/SystemShellExecute.hpp>
+#include <com/sun/star/system/SystemShellExecuteFlags.hpp>
+
+using namespace css::uno;
+using namespace css::system;
+
+ExternalToolEdit::ExternalToolEdit()
+{
+}
+
+ExternalToolEdit::~ExternalToolEdit()
+{
+}
+
+void ExternalToolEdit::HandleCloseEvent(ExternalToolEdit* pData)
+{
+ Graphic newGraphic;
+
+ //import the temp file image stream into the newGraphic
+ std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(pData->m_aFileName, StreamMode::READ));
+ if(pStream)
+ {
+ GraphicConverter::Import(*pStream, newGraphic);
+
+ // Now update the Graphic in the shell by re-reading from the newGraphic
+ pData->Update( newGraphic );
+ }
+}
+
+void ExternalToolEdit::StartListeningEvent()
+{
+ //Start an event listener implemented via VCL timeout
+ assert(!m_pChecker);
+ m_pChecker.reset(new FileChangedChecker(
+ m_aFileName, [this] () { return HandleCloseEvent(this); }));
+}
+
+namespace {
+
+// self-destructing thread to make shell execute async
+class ExternalToolEditThread
+ : public ::salhelper::Thread
+{
+private:
+ OUString const m_aFileName;
+
+ virtual void execute() override;
+
+public:
+ explicit ExternalToolEditThread(OUString const& rFileName)
+ : ::salhelper::Thread("ExternalToolEdit")
+ , m_aFileName(rFileName)
+ {}
+};
+
+}
+
+void ExternalToolEditThread::execute()
+{
+ try
+ {
+ Reference<XSystemShellExecute> const xSystemShellExecute(
+ SystemShellExecute::create( ::comphelper::getProcessComponentContext()));
+ xSystemShellExecute->execute(m_aFileName, OUString(),
+ SystemShellExecuteFlags::URIS_ONLY);
+ }
+ catch (Exception const&)
+ {
+ TOOLS_WARN_EXCEPTION("svx", "ExternalToolEditThread");
+ }
+}
+
+void ExternalToolEdit::Edit(GraphicObject const*const pGraphicObject)
+{
+ //Get the graphic from the GraphicObject
+ const Graphic& aGraphic = pGraphicObject->GetGraphic();
+
+ //get the Preferred File Extension for this graphic
+ OUString fExtension;
+ GraphicHelper::GetPreferredExtension(fExtension, aGraphic);
+
+ //Create the temp File
+ OUString aTempFileBase;
+ OUString aTempFileName;
+
+ osl::FileBase::RC rc =
+ osl::FileBase::createTempFile(nullptr, nullptr, &aTempFileBase);
+ if (osl::FileBase::E_None != rc)
+ {
+ SAL_WARN("svx", "ExternalToolEdit::Edit: cannot create temp file");
+ return;
+ }
+
+ // Move it to a file name with image extension properly set
+ aTempFileName = aTempFileBase + "." + fExtension;
+ // FIXME: this is pretty stupid, need a better osl temp file API
+ rc = osl::File::move(aTempFileBase, aTempFileName);
+ if (osl::FileBase::E_None != rc)
+ {
+ SAL_WARN("svx", "ExternalToolEdit::Edit: cannot move temp file");
+ return;
+ }
+
+ //Write Graphic to the Temp File
+ GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+ sal_uInt16 nFilter(rGraphicFilter.GetExportFormatNumberForShortName(fExtension));
+
+ OUString aFilter(rGraphicFilter.GetExportFormatShortName(nFilter));
+
+ // Write the Graphic to the file now
+ XOutBitmap::WriteGraphic(aGraphic, aTempFileName, aFilter, XOutFlags::UseNativeIfPossible | XOutFlags::DontExpandFilename);
+
+ // There is a possibility that sPath extension might have been changed if the
+ // provided extension is not writable
+ m_aFileName = aTempFileName;
+
+ //Create a thread
+
+ rtl::Reference<ExternalToolEditThread> const pThread(
+ new ExternalToolEditThread(m_aFileName));
+ pThread->launch();
+
+ StartListeningEvent();
+}
+
+SdrExternalToolEdit::SdrExternalToolEdit(
+ FmFormView* pView,
+ SdrObject* pObj)
+: m_pView(pView)
+ ,m_pObj(pObj)
+{
+ assert(m_pObj && m_pView);
+ StartListening(m_pObj->getSdrModelFromSdrObject());
+}
+
+
+void SdrExternalToolEdit::Notify(SfxBroadcaster & rBC, SfxHint const& rHint)
+{
+ if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
+ return;
+ SdrHint const*const pSdrHint(static_cast<SdrHint const*>(&rHint));
+ if (SdrHintKind::ModelCleared == pSdrHint->GetKind()
+ || (pSdrHint->GetObject() == m_pObj
+ && SdrHintKind::ObjectRemoved == pSdrHint->GetKind()))
+ {
+ m_pView = nullptr;
+ m_pObj = nullptr;
+ m_pChecker.reset(); // avoid modifying deleted object
+ EndListening(rBC);
+ }
+}
+
+void SdrExternalToolEdit::Update(Graphic & rGraphic)
+{
+ assert(m_pObj && m_pView); // timer should be deleted by Notify() too
+ SdrPageView *const pPageView = m_pView->GetSdrPageView();
+ if (!pPageView)
+ return;
+
+ SdrGrafObj *const pNewObj(static_cast<SdrGrafObj*>(m_pObj->CloneSdrObject(m_pObj->getSdrModelFromSdrObject())));
+ assert(pNewObj);
+ OUString const description =
+ m_pView->GetDescriptionOfMarkedObjects() + " External Edit";
+ m_pView->BegUndo(description);
+ pNewObj->SetGraphicObject(rGraphic);
+ // set to new object before ReplaceObjectAtView() so that Notify() will
+ // not delete the running timer and crash
+ SdrObject *const pOldObj = m_pObj;
+ m_pObj = pNewObj;
+ m_pView->ReplaceObjectAtView(pOldObj, *pPageView, pNewObj);
+ m_pView->EndUndo();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */