From cca66b9ec4e494c1d919bff0f71a820d8afab1fa Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:24:48 +0200 Subject: Adding upstream version 1.2.2. Signed-off-by: Daniel Baumann --- src/extension/internal/vsd-input.cpp | 380 +++++++++++++++++++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 src/extension/internal/vsd-input.cpp (limited to 'src/extension/internal/vsd-input.cpp') diff --git a/src/extension/internal/vsd-input.cpp b/src/extension/internal/vsd-input.cpp new file mode 100644 index 0000000..57763d5 --- /dev/null +++ b/src/extension/internal/vsd-input.cpp @@ -0,0 +1,380 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * This file came from libwpg as a source, their utility wpg2svg + * specifically. It has been modified to work as an Inkscape extension. + * The Inkscape extension code is covered by this copyright, but the + * rest is covered by the one below. + * + * Authors: + * Fridrich Strba (fridrich.strba@bluewin.ch) + * + * Copyright (C) 2012 Authors + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" // only include where actually required! +#endif + +#include + +#include "vsd-input.h" + +#ifdef WITH_LIBVISIO + +#include +#include + +#include + +#include + +using librevenge::RVNGString; +using librevenge::RVNGFileStream; +using librevenge::RVNGStringVector; + +#include + +#include "extension/system.h" +#include "extension/input.h" + +#include "document.h" +#include "inkscape.h" + +#include "ui/dialog-events.h" +#include + +#include "ui/view/svg-view-widget.h" + +#include "object/sp-root.h" + +#include "util/units.h" + +namespace Inkscape { +namespace Extension { +namespace Internal { + + +class VsdImportDialog : public Gtk::Dialog { +public: + VsdImportDialog(const std::vector &vec); + ~VsdImportDialog() override; + + bool showDialog(); + unsigned getSelectedPage(); + void getImportSettings(Inkscape::XML::Node *prefs); + +private: + void _setPreviewPage(); + + // Signal handlers + void _onPageNumberChanged(); + void _onSpinButtonPress(GdkEventButton* button_event); + void _onSpinButtonRelease(GdkEventButton* button_event); + + class Gtk::Box * vbox1; + class Inkscape::UI::View::SVGViewWidget * _previewArea; + class Gtk::Button * cancelbutton; + class Gtk::Button * okbutton; + + class Gtk::Box * _page_selector_box; + class Gtk::Label * _labelSelect; + class Gtk::Label * _labelTotalPages; + class Gtk::SpinButton * _pageNumberSpin; + + const std::vector &_vec; // Document to be imported + unsigned _current_page; // Current selected page + bool _spinning; // whether SpinButton is pressed (i.e. we're "spinning") +}; + +VsdImportDialog::VsdImportDialog(const std::vector &vec) + : _previewArea(nullptr) + , _vec(vec) + , _current_page(1) + , _spinning(false) +{ + int num_pages = _vec.size(); + if ( num_pages <= 1 ) + return; + + + // Dialog settings + this->set_title(_("Page Selector")); + this->set_modal(true); + sp_transientize(GTK_WIDGET(this->gobj())); //Make transient + this->property_window_position().set_value(Gtk::WIN_POS_NONE); + this->set_resizable(true); + this->property_destroy_with_parent().set_value(false); + + // Preview area + vbox1 = Gtk::manage(new class Gtk::Box(Gtk::ORIENTATION_VERTICAL)); + this->get_content_area()->pack_start(*vbox1); + + // CONTROLS + _page_selector_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL)); + + // Labels + _labelSelect = Gtk::manage(new class Gtk::Label(_("Select page:"))); + _labelTotalPages = Gtk::manage(new class Gtk::Label()); + _labelSelect->set_line_wrap(false); + _labelSelect->set_use_markup(false); + _labelSelect->set_selectable(false); + _page_selector_box->pack_start(*_labelSelect, Gtk::PACK_SHRINK); + + // Adjustment + spinner + auto _pageNumberSpin_adj = Gtk::Adjustment::create(1, 1, _vec.size(), 1, 10, 0); + _pageNumberSpin = Gtk::manage(new Gtk::SpinButton(_pageNumberSpin_adj, 1, 0)); + _pageNumberSpin->set_can_focus(); + _pageNumberSpin->set_update_policy(Gtk::UPDATE_ALWAYS); + _pageNumberSpin->set_numeric(true); + _pageNumberSpin->set_wrap(false); + _page_selector_box->pack_start(*_pageNumberSpin, Gtk::PACK_SHRINK); + + _labelTotalPages->set_line_wrap(false); + _labelTotalPages->set_use_markup(false); + _labelTotalPages->set_selectable(false); + gchar *label_text = g_strdup_printf(_("out of %i"), num_pages); + _labelTotalPages->set_label(label_text); + g_free(label_text); + _page_selector_box->pack_start(*_labelTotalPages, Gtk::PACK_SHRINK); + + vbox1->pack_end(*_page_selector_box, Gtk::PACK_SHRINK); + + // Buttons + cancelbutton = Gtk::manage(new Gtk::Button(_("_Cancel"), true)); + okbutton = Gtk::manage(new Gtk::Button(_("_OK"), true)); + this->add_action_widget(*cancelbutton, Gtk::RESPONSE_CANCEL); + this->add_action_widget(*okbutton, Gtk::RESPONSE_OK); + + // Show all widgets in dialog + this->show_all(); + + // Connect signals + _pageNumberSpin->signal_value_changed().connect(sigc::mem_fun(*this, &VsdImportDialog::_onPageNumberChanged)); + _pageNumberSpin->signal_button_press_event().connect_notify(sigc::mem_fun(*this, &VsdImportDialog::_onSpinButtonPress)); + _pageNumberSpin->signal_button_release_event().connect_notify(sigc::mem_fun(*this, &VsdImportDialog::_onSpinButtonRelease)); + + _setPreviewPage(); +} + +VsdImportDialog::~VsdImportDialog() = default; + +bool VsdImportDialog::showDialog() +{ + show(); + gint b = run(); + hide(); + if (b == Gtk::RESPONSE_OK || b == Gtk::RESPONSE_ACCEPT) { + return TRUE; + } else { + return FALSE; + } +} + +unsigned VsdImportDialog::getSelectedPage() +{ + return _current_page; +} + +void VsdImportDialog::_onPageNumberChanged() +{ + unsigned page = static_cast(_pageNumberSpin->get_value_as_int()); + _current_page = CLAMP(page, 1U, _vec.size()); + _setPreviewPage(); +} + +void VsdImportDialog::_onSpinButtonPress(GdkEventButton* /*button_event*/) +{ + _spinning = true; +} + +void VsdImportDialog::_onSpinButtonRelease(GdkEventButton* /*button_event*/) +{ + _spinning = false; + _setPreviewPage(); +} + +/** + * \brief Renders the given page's thumbnail + */ +void VsdImportDialog::_setPreviewPage() +{ + if (_spinning) { + return; + } + + SPDocument *doc = SPDocument::createNewDocFromMem(_vec[_current_page-1].cstr(), strlen(_vec[_current_page-1].cstr()), false); + if(!doc) { + g_warning("VSD import: Could not create preview for page %d", _current_page); + gchar const *no_preview_template = R"A( + + + + %s + + )A"; + gchar * no_preview = g_strdup_printf(no_preview_template, _("No preview")); + doc = SPDocument::createNewDocFromMem(no_preview, strlen(no_preview), false); + g_free(no_preview); + } + + if (!doc) { + std::cerr << "VsdImportDialog::_setPreviewPage: No document!" << std::endl; + return; + } + + if (_previewArea) { + _previewArea->setDocument(doc); + } else { + _previewArea = Gtk::manage(new Inkscape::UI::View::SVGViewWidget(doc)); + vbox1->pack_start(*_previewArea, Gtk::PACK_EXPAND_WIDGET, 0); + } + + _previewArea->setResize(400, 400); + _previewArea->show_all(); +} + +SPDocument *VsdInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * uri) +{ + #ifdef _WIN32 + // RVNGFileStream uses fopen() internally which unfortunately only uses ANSI encoding on Windows + // therefore attempt to convert uri to the system codepage + // even if this is not possible the alternate short (8.3) file name will be used if available + gchar * converted_uri = g_win32_locale_filename_from_utf8(uri); + RVNGFileStream input(converted_uri); + g_free(converted_uri); + #else + RVNGFileStream input(uri); + #endif + + if (!libvisio::VisioDocument::isSupported(&input)) { + return nullptr; + } + + RVNGStringVector output; + librevenge::RVNGSVGDrawingGenerator generator(output, "svg"); + + if (!libvisio::VisioDocument::parse(&input, &generator)) { + return nullptr; + } + + if (output.empty()) { + return nullptr; + } + + std::vector tmpSVGOutput; + for (unsigned i=0; i\n\n"); + tmpString.append(output[i]); + tmpSVGOutput.push_back(tmpString); + } + + unsigned page_num = 1; + + // If only one page is present, import that one without bothering user + if (tmpSVGOutput.size() > 1) { + VsdImportDialog *dlg = nullptr; + if (INKSCAPE.use_gui()) { + dlg = new VsdImportDialog(tmpSVGOutput); + if (!dlg->showDialog()) { + delete dlg; + throw Input::open_cancelled(); + } + } + + // Get needed page + if (dlg) { + page_num = dlg->getSelectedPage(); + if (page_num < 1) + page_num = 1; + if (page_num > tmpSVGOutput.size()) + page_num = tmpSVGOutput.size(); + } + } + + SPDocument * doc = SPDocument::createNewDocFromMem(tmpSVGOutput[page_num-1].cstr(), strlen(tmpSVGOutput[page_num-1].cstr()), TRUE); + + // Set viewBox if it doesn't exist + if (doc && !doc->getRoot()->viewBox_set) { + doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value(doc->getDisplayUnit()), doc->getHeight().value(doc->getDisplayUnit()))); + } + return doc; +} + +#include "clear-n_.h" + +void VsdInput::init() +{ + // clang-format off + /* VSD */ + Inkscape::Extension::build_from_mem( + "\n" + "" N_("VSD Input") "\n" + "org.inkscape.input.vsd\n" + "\n" + ".vsd\n" + "application/vnd.visio\n" + "" N_("Microsoft Visio Diagram (*.vsd)") "\n" + "" N_("File format used by Microsoft Visio 6 and later") "\n" + "\n" + "", new VsdInput()); + + /* VDX */ + Inkscape::Extension::build_from_mem( + "\n" + "" N_("VDX Input") "\n" + "org.inkscape.input.vdx\n" + "\n" + ".vdx\n" + "application/vnd.visio\n" + "" N_("Microsoft Visio XML Diagram (*.vdx)") "\n" + "" N_("File format used by Microsoft Visio 2010 and later") "\n" + "\n" + "", new VsdInput()); + + /* VSDM */ + Inkscape::Extension::build_from_mem( + "\n" + "" N_("VSDM Input") "\n" + "org.inkscape.input.vsdm\n" + "\n" + ".vsdm\n" + "application/vnd.visio\n" + "" N_("Microsoft Visio 2013 drawing (*.vsdm)") "\n" + "" N_("File format used by Microsoft Visio 2013 and later") "\n" + "\n" + "", new VsdInput()); + + /* VSDX */ + Inkscape::Extension::build_from_mem( + "\n" + "" N_("VSDX Input") "\n" + "org.inkscape.input.vsdx\n" + "\n" + ".vsdx\n" + "application/vnd.visio\n" + "" N_("Microsoft Visio 2013 drawing (*.vsdx)") "\n" + "" N_("File format used by Microsoft Visio 2013 and later") "\n" + "\n" + "", new VsdInput()); + // clang-format on + + return; + +} // init + +} } } /* namespace Inkscape, Extension, Implementation */ +#endif /* WITH_LIBVISIO */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : -- cgit v1.2.3