clipboard.cpp revision 66e68c8651d5cb19ea8f1714244a6c40d212bc78
153bb1867986d6db392e2cfa711ad6231fce8abeJon A. Cruz/**
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * @file
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * System-wide clipboard management - implementation.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh */
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh/* Authors:
9dc68827cbd515262ecb8d5ae8547d9e82c72e00Jon A. Cruz * Krzysztof KosiƄski <tweenk@o2.pl>
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Jon A. Cruz <jon@joncruz.org>
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Incorporates some code from selection-chemistry.cpp, see that file for more credits.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Abhishek Sharma
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Tavmjong Bah
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh *
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Copyright (C) 2008 authors
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Copyright (C) 2010 Jon A. Cruz
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Copyright (C) 2012 Tavmjong Bah (Symbol additions)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh *
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * This program is free software; you can redistribute it and/or
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * modify it under the terms of the GNU General Public License
75b857d473541532819bd791105cb352c9a43214buliabyak * as published by the Free Software Foundation; either version 2
75b857d473541532819bd791105cb352c9a43214buliabyak * of the License, or (at your option) any later version.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh *
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * See the file COPYING for details.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh */
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include <gtkmm/clipboard.h>
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "ui/clipboard.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh// TODO: reduce header bloat if possible
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "file.h" // for file_import, used in _pasteImage
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include <list>
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include <algorithm>
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include <glibmm/ustring.h>
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include <glibmm/i18n.h>
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include <glib/gstdio.h> // for g_file_set_contents etc., used in _onGet and paste
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "inkgc/gc-core.h"
c751b68e56ace7b9d649ee20b7f25ed1f65922e3Matthew Petroff#include "xml/repr.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "inkscape.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "io/stringstream.h"
b5b35fce2e3df933e5223ef6645d814eacf51cfamiklosh#include "desktop.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "desktop-style.h" // for sp_desktop_set_style, used in _pasteStyle
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "document.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "document-private.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "selection.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "message-stack.h"
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh#include "context-fns.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "ui/tools/dropper-tool.h" // used in copy()
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "style.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "extension/db.h" // extension database
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "extension/input.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "extension/output.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "selection-chemistry.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include <2geom/rect.h>
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include <2geom/transforms.h>
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "box3d.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "gradient-drag.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "sp-marker.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "sp-item.h"
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh#include "sp-item-transform.h" // for sp_item_scale_rel, used in _pasteSize
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh#include "sp-path.h"
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh#include "sp-pattern.h"
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh#include "sp-shape.h"
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh#include "sp-gradient.h"
63e32b5fcb40d1d6ceffa7fa1f03e679cb694b23Jon A. Cruz#include "sp-gradient-reference.h"
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh#include "sp-linear-gradient.h"
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh#include "sp-radial-gradient.h"
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh#include "sp-clippath.h"
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh#include "sp-mask.h"
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh#include "sp-textpath.h"
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh#include "sp-rect.h"
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh#include "sp-use.h"
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh#include "sp-symbol.h"
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh#include "live_effects/lpeobject.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "live_effects/lpeobject-reference.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "live_effects/parameter/path.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "svg/svg.h" // for sp_svg_transform_write, used in _copySelection
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "svg/css-ostringstream.h" // used in copy
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "ui/tools/text-tool.h"
9dc68827cbd515262ecb8d5ae8547d9e82c72e00Jon A. Cruz#include "text-editing.h"
9dc68827cbd515262ecb8d5ae8547d9e82c72e00Jon A. Cruz#include "ui/tools-switch.h"
1cda9431ef400135f5e1bd899a94b921bdad0eafmiklosh#include "path-chemistry.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "util/units.h"
68664e00e2372534b4df2fdc5f54f836bafece18miklosh#include "helper/png-write.h"
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh#include "svg/svg-color.h"
9dc68827cbd515262ecb8d5ae8547d9e82c72e00Jon A. Cruz#include "sp-namedview.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "snap.h"
a4d12a5147f3d1d6b568a326e39ef5dca384248dmiklosh#include "persp3d.h"
1667116521643e2475184b048e0abb77a2aa9735miklosh#include "preferences.h"
cb814cb0df20053ca3ef16ce55da474435daf045miklosh
cb814cb0df20053ca3ef16ce55da474435daf045miklosh/// Made up mimetype to represent Gdk::Pixbuf clipboard contents.
cb814cb0df20053ca3ef16ce55da474435daf045miklosh#define CLIPBOARD_GDK_PIXBUF_TARGET "image/x-gdk-pixbuf"
cb814cb0df20053ca3ef16ce55da474435daf045miklosh
75b857d473541532819bd791105cb352c9a43214buliabyak#define CLIPBOARD_TEXT_TARGET "text/plain"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#ifdef WIN32
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include <windows.h>
1cda9431ef400135f5e1bd899a94b921bdad0eafmiklosh#endif
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
68664e00e2372534b4df2fdc5f54f836bafece18mikloshnamespace Inkscape {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7mikloshnamespace UI {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
cb814cb0df20053ca3ef16ce55da474435daf045miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh/**
1667116521643e2475184b048e0abb77a2aa9735miklosh * Default implementation of the clipboard manager.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh */
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshclass ClipboardManagerImpl : public ClipboardManager {
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshpublic:
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh virtual void copy(SPDesktop *desktop);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh virtual void copyPathParameter(Inkscape::LivePathEffect::PathParam *);
1667116521643e2475184b048e0abb77a2aa9735miklosh virtual void copySymbol(Inkscape::XML::Node* symbol, gchar const* style, bool user_symbol);
1667116521643e2475184b048e0abb77a2aa9735miklosh virtual bool paste(SPDesktop *desktop, bool in_place);
1667116521643e2475184b048e0abb77a2aa9735miklosh virtual bool pasteStyle(SPDesktop *desktop);
f9ab06d037336cf8796b54c94a119f40eda79a46Kris virtual bool pasteSize(SPDesktop *desktop, bool separately, bool apply_x, bool apply_y);
f9ab06d037336cf8796b54c94a119f40eda79a46Kris virtual bool pastePathEffect(SPDesktop *desktop);
f9ab06d037336cf8796b54c94a119f40eda79a46Kris virtual Glib::ustring getPathParameter(SPDesktop* desktop);
f9ab06d037336cf8796b54c94a119f40eda79a46Kris virtual Glib::ustring getShapeOrTextObjectId(SPDesktop *desktop);
f9ab06d037336cf8796b54c94a119f40eda79a46Kris virtual const gchar *getFirstObjectID();
1667116521643e2475184b048e0abb77a2aa9735miklosh
f9ab06d037336cf8796b54c94a119f40eda79a46Kris ClipboardManagerImpl();
f9ab06d037336cf8796b54c94a119f40eda79a46Kris ~ClipboardManagerImpl();
1667116521643e2475184b048e0abb77a2aa9735miklosh
75b857d473541532819bd791105cb352c9a43214buliabyakprivate:
be17b6e6b80af045ef40c635ea563ebd987269b8tavmjong-free void _copySelection(Inkscape::Selection *);
be17b6e6b80af045ef40c635ea563ebd987269b8tavmjong-free void _copyUsedDefs(SPItem *);
be17b6e6b80af045ef40c635ea563ebd987269b8tavmjong-free void _copyGradient(SPGradient *);
be17b6e6b80af045ef40c635ea563ebd987269b8tavmjong-free void _copyPattern(SPPattern *);
be17b6e6b80af045ef40c635ea563ebd987269b8tavmjong-free void _copyTextPath(SPTextPath *);
75b857d473541532819bd791105cb352c9a43214buliabyak Inkscape::XML::Node *_copyNode(Inkscape::XML::Node *, Inkscape::XML::Document *, Inkscape::XML::Node *);
75b857d473541532819bd791105cb352c9a43214buliabyak
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh bool _pasteImage(SPDocument *doc);
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh bool _pasteText(SPDesktop *desktop);
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh void _applyPathEffect(SPItem *, gchar const *);
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh SPDocument *_retrieveClipboard(Glib::ustring = "");
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh
1667116521643e2475184b048e0abb77a2aa9735miklosh // clipboard callbacks
7ddc475794d846646261f6b12015d44ac361d070Kris De Gussem void _onGet(Gtk::SelectionData &, guint);
7ddc475794d846646261f6b12015d44ac361d070Kris De Gussem void _onClear();
7ddc475794d846646261f6b12015d44ac361d070Kris De Gussem
1667116521643e2475184b048e0abb77a2aa9735miklosh // various helpers
1667116521643e2475184b048e0abb77a2aa9735miklosh void _createInternalClipboard();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh void _discardInternalClipboard();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::XML::Node *_createClipNode();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Geom::Scale _getScale(SPDesktop *desktop, Geom::Point const &min, Geom::Point const &max, Geom::Rect const &obj_rect, bool apply_x, bool apply_y);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Glib::ustring _getBestTarget();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh void _setClipboardTargets();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh void _setClipboardColor(guint32);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh void _userWarn(SPDesktop *, char const *);
68664e00e2372534b4df2fdc5f54f836bafece18miklosh
68664e00e2372534b4df2fdc5f54f836bafece18miklosh void _inkscape_wait_for_targets(std::list<Glib::ustring> &);
68664e00e2372534b4df2fdc5f54f836bafece18miklosh
68664e00e2372534b4df2fdc5f54f836bafece18miklosh // private properites
68664e00e2372534b4df2fdc5f54f836bafece18miklosh SPDocument *_clipboardSPDoc; ///< Document that stores the clipboard until someone requests it
68664e00e2372534b4df2fdc5f54f836bafece18miklosh Inkscape::XML::Node *_defs; ///< Reference to the clipboard document's defs node
68664e00e2372534b4df2fdc5f54f836bafece18miklosh Inkscape::XML::Node *_root; ///< Reference to the clipboard's root node
68664e00e2372534b4df2fdc5f54f836bafece18miklosh Inkscape::XML::Node *_clipnode; ///< The node that holds extra information
68664e00e2372534b4df2fdc5f54f836bafece18miklosh Inkscape::XML::Document *_doc; ///< Reference to the clipboard's Inkscape::XML::Document
68664e00e2372534b4df2fdc5f54f836bafece18miklosh
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh // we need a way to copy plain text AND remember its style;
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh // the standard _clipnode is only available in an SVG tree, hence this special storage
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh SPCSSAttr *_text_style; ///< Style copied along with plain text fragment
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh Glib::RefPtr<Gtk::Clipboard> _clipboard; ///< Handle to the system wide clipboard - for convenience
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh std::list<Glib::ustring> _preferred_targets; ///< List of supported clipboard targets
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh};
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emikloshClipboardManagerImpl::ClipboardManagerImpl()
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh : _clipboardSPDoc(NULL),
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh _defs(NULL),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _root(NULL),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _clipnode(NULL),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _doc(NULL),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _text_style(NULL),
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh _clipboard( Gtk::Clipboard::get() )
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh{
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // Clipboard Formats: http://msdn.microsoft.com/en-us/library/ms649013(VS.85).aspx
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh // On Windows, most graphical applications can handle CF_DIB/CF_BITMAP and/or CF_ENHMETAFILE
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // GTK automatically presents an "image/bmp" target as CF_DIB/CF_BITMAP
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // Presenting "image/x-emf" as CF_ENHMETAFILE must be done by Inkscape ?
1667116521643e2475184b048e0abb77a2aa9735miklosh
1667116521643e2475184b048e0abb77a2aa9735miklosh // push supported clipboard targets, in order of preference
1667116521643e2475184b048e0abb77a2aa9735miklosh _preferred_targets.push_back("image/x-inkscape-svg");
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _preferred_targets.push_back("image/svg+xml");
1667116521643e2475184b048e0abb77a2aa9735miklosh _preferred_targets.push_back("image/svg+xml-compressed");
1667116521643e2475184b048e0abb77a2aa9735miklosh _preferred_targets.push_back("image/x-emf");
1667116521643e2475184b048e0abb77a2aa9735miklosh _preferred_targets.push_back("CF_ENHMETAFILE");
1667116521643e2475184b048e0abb77a2aa9735miklosh _preferred_targets.push_back("WCF_ENHMETAFILE"); // seen on Wine
1667116521643e2475184b048e0abb77a2aa9735miklosh _preferred_targets.push_back("application/pdf");
1667116521643e2475184b048e0abb77a2aa9735miklosh _preferred_targets.push_back("image/x-adobe-illustrator");
1667116521643e2475184b048e0abb77a2aa9735miklosh}
1667116521643e2475184b048e0abb77a2aa9735miklosh
1667116521643e2475184b048e0abb77a2aa9735miklosh
1667116521643e2475184b048e0abb77a2aa9735mikloshClipboardManagerImpl::~ClipboardManagerImpl() {}
1667116521643e2475184b048e0abb77a2aa9735miklosh
1667116521643e2475184b048e0abb77a2aa9735miklosh
1667116521643e2475184b048e0abb77a2aa9735miklosh/**
1667116521643e2475184b048e0abb77a2aa9735miklosh * Copy selection contents to the clipboard.
1667116521643e2475184b048e0abb77a2aa9735miklosh */
1667116521643e2475184b048e0abb77a2aa9735mikloshvoid ClipboardManagerImpl::copy(SPDesktop *desktop)
1667116521643e2475184b048e0abb77a2aa9735miklosh{
1667116521643e2475184b048e0abb77a2aa9735miklosh if ( desktop == NULL ) {
1667116521643e2475184b048e0abb77a2aa9735miklosh return;
1667116521643e2475184b048e0abb77a2aa9735miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::Selection *selection = desktop->getSelection();
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh
68664e00e2372534b4df2fdc5f54f836bafece18miklosh // Special case for when the gradient dragger is active - copies gradient color
1cda9431ef400135f5e1bd899a94b921bdad0eafmiklosh if (desktop->event_context->get_drag()) {
68664e00e2372534b4df2fdc5f54f836bafece18miklosh GrDrag *drag = desktop->event_context->get_drag();
68664e00e2372534b4df2fdc5f54f836bafece18miklosh if (drag->hasSelection()) {
68664e00e2372534b4df2fdc5f54f836bafece18miklosh guint32 col = drag->getColor();
68664e00e2372534b4df2fdc5f54f836bafece18miklosh
68664e00e2372534b4df2fdc5f54f836bafece18miklosh // set the color as clipboard content (text in RRGGBBAA format)
68664e00e2372534b4df2fdc5f54f836bafece18miklosh _setClipboardColor(col);
68664e00e2372534b4df2fdc5f54f836bafece18miklosh
68664e00e2372534b4df2fdc5f54f836bafece18miklosh // create a style with this color on fill and opacity in master opacity, so it can be
68664e00e2372534b4df2fdc5f54f836bafece18miklosh // pasted on other stops or objects
13c1b2b6c3fc75e657813da1865541253a2b1dceapenner if (_text_style) {
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski sp_repr_css_attr_unref(_text_style);
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski _text_style = NULL;
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski }
13c1b2b6c3fc75e657813da1865541253a2b1dceapenner _text_style = sp_repr_css_attr_new();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // print and set properties
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh gchar color_str[16];
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh g_snprintf(color_str, 16, "#%06x", col >> 8);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sp_repr_css_set_property(_text_style, "fill", color_str);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh float opacity = SP_RGBA32_A_F(col);
1667116521643e2475184b048e0abb77a2aa9735miklosh if (opacity > 1.0) {
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh opacity = 1.0; // safeguard
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::CSSOStringStream opcss;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh opcss << opacity;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sp_repr_css_set_property(_text_style, "opacity", opcss.str().data());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _discardInternalClipboard();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
d9a7c806ee7f408ddb61ff4f233c9d96111ee2b5johanengelen // Special case for when the color picker ("dropper") is active - copies color under cursor
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (tools_isactive(desktop, TOOLS_DROPPER)) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //_setClipboardColor(sp_dropper_context_get_color(desktop->event_context));
fba63a357654d8b3e84c60007e40aa698cd45d19miklosh _setClipboardColor(SP_DROPPER_CONTEXT(desktop->event_context)->get_color());
d9a7c806ee7f408ddb61ff4f233c9d96111ee2b5johanengelen _discardInternalClipboard();
d9a7c806ee7f408ddb61ff4f233c9d96111ee2b5johanengelen return;
d9a7c806ee7f408ddb61ff4f233c9d96111ee2b5johanengelen }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // Special case for when the text tool is active - if some text is selected, copy plain text,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // not the object that holds it; also copy the style at cursor into
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (tools_isactive(desktop, TOOLS_TEXT)) {
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh _discardInternalClipboard();
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Glib::ustring selected_text = Inkscape::UI::Tools::sp_text_get_selected_text(desktop->event_context);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh _clipboard->set_text(selected_text);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (_text_style) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sp_repr_css_attr_unref(_text_style);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _text_style = NULL;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
b5b35fce2e3df933e5223ef6645d814eacf51cfamiklosh _text_style = Inkscape::UI::Tools::sp_text_get_style_at_cursor(desktop->event_context);
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen return;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (selection->isEmpty()) { // check whether something is selected
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _userWarn(desktop, _("Nothing was copied."));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _discardInternalClipboard();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _createInternalClipboard(); // construct a new clipboard document
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _copySelection(selection); // copy all items in the selection to the internal clipboard
0c6b51649b501e4e378921d918c6a113ab8e2bceJohan B. C. Engelen fit_canvas_to_drawing(_clipboardSPDoc);
0c6b51649b501e4e378921d918c6a113ab8e2bceJohan B. C. Engelen
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _setClipboardTargets();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh}
0c6b51649b501e4e378921d918c6a113ab8e2bceJohan B. C. Engelen
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh/**
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Copy a Live Path Effect path parameter to the clipboard.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * @param pp The path parameter to store in the clipboard.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh */
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshvoid ClipboardManagerImpl::copyPathParameter(Inkscape::LivePathEffect::PathParam *pp)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh{
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( pp == NULL ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh gchar *svgd = sp_svg_write_path( pp->get_pathvector() );
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( svgd == NULL || *svgd == '\0' ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _discardInternalClipboard();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _createInternalClipboard();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::XML::Node *pathnode = _doc->createElement("svg:path");
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh pathnode->setAttribute("d", svgd);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh g_free(svgd);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _root->appendChild(pathnode);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::GC::release(pathnode);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh fit_canvas_to_drawing(_clipboardSPDoc);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _setClipboardTargets();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh/**
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Copy a symbol from the symbol dialog.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * @param symbol The Inkscape::XML::Node for the symbol.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh */
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshvoid ClipboardManagerImpl::copySymbol(Inkscape::XML::Node* symbol, gchar const* style, bool user_symbol)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh{
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //std::cout << "ClipboardManagerImpl::copySymbol" << std::endl;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( symbol == NULL ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _discardInternalClipboard();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _createInternalClipboard();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // We add "_duplicate" to have a well defined symbol name that
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // bypasses the "prevent_id_classes" routine. We'll get rid of it
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // when we paste.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::XML::Node *repr = symbol->duplicate(_doc);
1ac9ddf51315777a429c1083a3fee7eba89f400dKrzysztof KosiƄski Glib::ustring symbol_name = repr->attribute("id");
1ac9ddf51315777a429c1083a3fee7eba89f400dKrzysztof KosiƄski
1ac9ddf51315777a429c1083a3fee7eba89f400dKrzysztof KosiƄski symbol_name += "_inkscape_duplicate";
1ac9ddf51315777a429c1083a3fee7eba89f400dKrzysztof KosiƄski repr->setAttribute("id", symbol_name.c_str());
1ac9ddf51315777a429c1083a3fee7eba89f400dKrzysztof KosiƄski _defs->appendChild(repr);
1ac9ddf51315777a429c1083a3fee7eba89f400dKrzysztof KosiƄski
1ac9ddf51315777a429c1083a3fee7eba89f400dKrzysztof KosiƄski Glib::ustring id("#");
1ac9ddf51315777a429c1083a3fee7eba89f400dKrzysztof KosiƄski id += symbol->attribute("id");
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh gdouble scale_units = 1; // scale from "px" to "document-units"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::XML::Node *nv_repr = SP_ACTIVE_DESKTOP->getNamedView()->getRepr();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (nv_repr->attribute("inkscape:document-units"))
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh scale_units = Inkscape::Util::Quantity::convert(1, "px", nv_repr->attribute("inkscape:document-units"));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPObject *cmobj = _clipboardSPDoc->getObjectByRepr(repr);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (cmobj && !user_symbol) { // convert only stock symbols
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!Geom::are_near(scale_units, 1.0, Geom::EPSILON)) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh dynamic_cast<SPGroup *>(cmobj)->scaleChildItemsRec(Geom::Scale(scale_units),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Point(0, SP_ACTIVE_DESKTOP->getDocument()->getHeight().value("px")),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh false);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::XML::Node *use = _doc->createElement("svg:use");
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh use->setAttribute("xlink:href", id.c_str() );
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // Set a default style in <use> rather than <symbol> so it can be changed.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh use->setAttribute("style", style );
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!Geom::are_near(scale_units, 1.0, Geom::EPSILON)) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh gchar *transform_str = sp_svg_transform_write(Geom::Scale(1.0/scale_units));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh use->setAttribute("transform", transform_str);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh g_free(transform_str);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _root->appendChild(use);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // This min and max sets offsets, we don't have any so set to zero.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sp_repr_set_point(_clipnode, "min", Geom::Point(0,0));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sp_repr_set_point(_clipnode, "max", Geom::Point(0,0));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh fit_canvas_to_drawing(_clipboardSPDoc);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _setClipboardTargets();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh}
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh/**
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Paste from the system clipboard into the active desktop.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * @param in_place Whether to put the contents where they were when copied.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh */
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshbool ClipboardManagerImpl::paste(SPDesktop *desktop, bool in_place)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // do any checking whether we really are able to paste before requesting the contents
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( desktop == NULL ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return false;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( Inkscape::have_viable_layer(desktop, desktop->messageStack()) == false ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return false;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Glib::ustring target = _getBestTarget();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // Special cases of clipboard content handling go here
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // Note that target priority is determined in _getBestTarget.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // TODO: Handle x-special/gnome-copied-files and text/uri-list to support pasting files
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // if there is an image on the clipboard, paste it
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( target == CLIPBOARD_GDK_PIXBUF_TARGET ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return _pasteImage(desktop->doc());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // if there's only text, paste it into a selected text object or create a new one
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( target == CLIPBOARD_TEXT_TARGET ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return _pasteText(desktop);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // otherwise, use the import extensions
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPDocument *tempdoc = _retrieveClipboard(target);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( tempdoc == NULL ) {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh _userWarn(desktop, _("Nothing on the clipboard."));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return false;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sp_import_document(desktop, tempdoc, in_place);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh tempdoc->doUnref();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return true;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh}
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh/**
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Returns the id of the first visible copied object.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh */
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshconst gchar *ClipboardManagerImpl::getFirstObjectID()
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh{
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPDocument *tempdoc = _retrieveClipboard("image/x-inkscape-svg");
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( tempdoc == NULL ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return NULL;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::XML::Node *root = tempdoc->getReprRoot();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!root) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return NULL;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::XML::Node *ch = root->firstChild();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh while (ch != NULL &&
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh strcmp(ch->name(), "svg:g") &&
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh strcmp(ch->name(), "svg:path") &&
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh strcmp(ch->name(), "svg:use") &&
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh strcmp(ch->name(), "svg:text") &&
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh strcmp(ch->name(), "svg:image") &&
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh strcmp(ch->name(), "svg:rect")
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh ch = ch->next();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (ch) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return ch->attribute("id");
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return NULL;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh}
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh/**
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Implements the Paste Style action.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh */
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshbool ClipboardManagerImpl::pasteStyle(SPDesktop *desktop)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (desktop == NULL) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return false;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // check whether something is selected
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::Selection *selection = desktop->getSelection();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (selection->isEmpty()) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _userWarn(desktop, _("Select <b>object(s)</b> to paste style to."));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return false;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPDocument *tempdoc = _retrieveClipboard("image/x-inkscape-svg");
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( tempdoc == NULL ) {
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh // no document, but we can try _text_style
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh if (_text_style) {
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh sp_desktop_set_style(desktop, _text_style);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh return true;
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh } else {
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh _userWarn(desktop, _("No style on the clipboard."));
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh return false;
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh }
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh }
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh Inkscape::XML::Node *root = tempdoc->getReprRoot();
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh Inkscape::XML::Node *clipnode = sp_repr_lookup_name(root, "inkscape:clipboard", 1);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh bool pasted = false;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh if (clipnode) {
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh desktop->doc()->importDefs(tempdoc);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh SPCSSAttr *style = sp_repr_css_attr(clipnode, "style");
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh sp_desktop_set_style(desktop, style);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh pasted = true;
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh }
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh else {
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh _userWarn(desktop, _("No style on the clipboard."));
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh }
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh tempdoc->doUnref();
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh return pasted;
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh}
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh/**
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh * Resize the selection or each object in the selection to match the clipboard's size.
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh * @param separately Whether to scale each object in the selection separately
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh * @param apply_x Whether to scale the width of objects / selection
1db439af43130c9695dbbb661e893d56006bb072miklosh * @param apply_y Whether to scale the height of objects / selection
1db439af43130c9695dbbb661e893d56006bb072miklosh */
1db439af43130c9695dbbb661e893d56006bb072mikloshbool ClipboardManagerImpl::pasteSize(SPDesktop *desktop, bool separately, bool apply_x, bool apply_y)
1db439af43130c9695dbbb661e893d56006bb072miklosh{
1db439af43130c9695dbbb661e893d56006bb072miklosh if (!apply_x && !apply_y) {
1db439af43130c9695dbbb661e893d56006bb072miklosh return false; // pointless parameters
1db439af43130c9695dbbb661e893d56006bb072miklosh }
1db439af43130c9695dbbb661e893d56006bb072miklosh
1db439af43130c9695dbbb661e893d56006bb072miklosh if ( desktop == NULL ) {
1db439af43130c9695dbbb661e893d56006bb072miklosh return false;
1db439af43130c9695dbbb661e893d56006bb072miklosh }
1db439af43130c9695dbbb661e893d56006bb072miklosh Inkscape::Selection *selection = desktop->getSelection();
1db439af43130c9695dbbb661e893d56006bb072miklosh if (selection->isEmpty()) {
1db439af43130c9695dbbb661e893d56006bb072miklosh _userWarn(desktop, _("Select <b>object(s)</b> to paste size to."));
1db439af43130c9695dbbb661e893d56006bb072miklosh return false;
1db439af43130c9695dbbb661e893d56006bb072miklosh }
1db439af43130c9695dbbb661e893d56006bb072miklosh
1db439af43130c9695dbbb661e893d56006bb072miklosh // FIXME: actually, this should accept arbitrary documents
1db439af43130c9695dbbb661e893d56006bb072miklosh SPDocument *tempdoc = _retrieveClipboard("image/x-inkscape-svg");
1db439af43130c9695dbbb661e893d56006bb072miklosh if ( tempdoc == NULL ) {
1db439af43130c9695dbbb661e893d56006bb072miklosh _userWarn(desktop, _("No size on the clipboard."));
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh return false;
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // retrieve size ifomration from the clipboard
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::XML::Node *root = tempdoc->getReprRoot();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::XML::Node *clipnode = sp_repr_lookup_name(root, "inkscape:clipboard", 1);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh bool pasted = false;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (clipnode) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Point min, max;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sp_repr_get_point(clipnode, "min", &min);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sp_repr_get_point(clipnode, "max", &max);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // resize each object in the selection
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (separately) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh std::vector<SPItem*> itemlist=selection->itemList();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPItem *item = *i;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (item) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::OptRect obj_size = item->desktopVisualBounds();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( obj_size ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sp_item_scale_rel(item, _getScale(desktop, min, max, *obj_size, apply_x, apply_y));
920fbbf5386a5d3b1d0a1304cb71eb48112abe0dmiklosh }
920fbbf5386a5d3b1d0a1304cb71eb48112abe0dmiklosh } else {
920fbbf5386a5d3b1d0a1304cb71eb48112abe0dmiklosh g_assert_not_reached();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
07b7f1aaaf1087716e784a50cf574a059f7018d3Jon A. Cruz // resize the selection as a whole
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh else {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::OptRect sel_size = selection->visualBounds();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( sel_size ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sp_selection_scale_relative(selection, sel_size->midpoint(),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _getScale(desktop, min, max, *sel_size, apply_x, apply_y));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh pasted = true;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh tempdoc->doUnref();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return pasted;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh}
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh/**
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Applies a path effect from the clipboard to the selected path.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh */
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshbool ClipboardManagerImpl::pastePathEffect(SPDesktop *desktop)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh{
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh /** @todo FIXME: pastePathEffect crashes when moving the path with the applied effect,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh segfaulting in fork_private_if_necessary(). */
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( desktop == NULL ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return false;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::Selection *selection = desktop->getSelection();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (selection && selection->isEmpty()) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _userWarn(desktop, _("Select <b>object(s)</b> to paste live path effect to."));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return false;
f9325af537ca5517eb50ef95f432a3204616f6b3apenner }
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski SPDocument *tempdoc = _retrieveClipboard("image/x-inkscape-svg");
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski if ( tempdoc ) {
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski Inkscape::XML::Node *root = tempdoc->getReprRoot();
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski Inkscape::XML::Node *clipnode = sp_repr_lookup_name(root, "inkscape:clipboard", 1);
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski if ( clipnode ) {
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski gchar const *effectstack = clipnode->attribute("inkscape:path-effect");
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski if ( effectstack ) {
f9325af537ca5517eb50ef95f432a3204616f6b3apenner desktop->doc()->importDefs(tempdoc);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // make sure all selected items are converted to paths first (i.e. rectangles)
dd6d813ffad339352c39dc0645a792bdd9d8315cmiklosh sp_selected_to_lpeitems(desktop);
dd6d813ffad339352c39dc0645a792bdd9d8315cmiklosh std::vector<SPItem*> itemlist=selection->itemList();
dd6d813ffad339352c39dc0645a792bdd9d8315cmiklosh for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){
dd6d813ffad339352c39dc0645a792bdd9d8315cmiklosh SPItem *item = *i;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _applyPathEffect(item, effectstack);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return true;
6d9c1b595cc989472a475874007760800d11e6b8pjrm }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // no_effect:
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _userWarn(desktop, _("No effect on the clipboard."));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return false;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh}
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh/**
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh * Get LPE path data from the clipboard.
f8d5f6dc1f2af1841ce5df731eb121151810e43dKris * @return The retrieved path data (contents of the d attribute), or "" if no path was found
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh */
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshGlib::ustring ClipboardManagerImpl::getPathParameter(SPDesktop* desktop)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPDocument *tempdoc = _retrieveClipboard(); // any target will do here
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( tempdoc == NULL ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _userWarn(desktop, _("Nothing on the clipboard."));
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return "";
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::XML::Node *root = tempdoc->getReprRoot();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::XML::Node *path = sp_repr_lookup_name(root, "svg:path", -1); // unlimited search depth
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( path == NULL ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _userWarn(desktop, _("Clipboard does not contain a path."));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh tempdoc->doUnref();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return "";
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh gchar const *svgd = path->attribute("d");
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return svgd;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh}
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh/**
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Get object id of a shape or text item from the clipboard.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh * @return The retrieved id string (contents of the id attribute), or "" if no shape or text item was found.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh */
f8d5f6dc1f2af1841ce5df731eb121151810e43dKrisGlib::ustring ClipboardManagerImpl::getShapeOrTextObjectId(SPDesktop *desktop)
f9325af537ca5517eb50ef95f432a3204616f6b3apenner{
f9325af537ca5517eb50ef95f432a3204616f6b3apenner // https://bugs.launchpad.net/inkscape/+bug/1293979
f9325af537ca5517eb50ef95f432a3204616f6b3apenner // basically, when we do a depth-first search, we're stopping
f9325af537ca5517eb50ef95f432a3204616f6b3apenner // at the first object to be <svg:path> or <svg:text>.
f9325af537ca5517eb50ef95f432a3204616f6b3apenner // but that could then return the id of the object's
f9325af537ca5517eb50ef95f432a3204616f6b3apenner // clip path or mask, not the original path!
f9325af537ca5517eb50ef95f432a3204616f6b3apenner
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski SPDocument *tempdoc = _retrieveClipboard(); // any target will do here
f9325af537ca5517eb50ef95f432a3204616f6b3apenner if ( tempdoc == NULL ) {
d2ac881b8a3bc4613547b9173681ff1752eaa0e2Kris _userWarn(desktop, _("Nothing on the clipboard."));
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski return "";
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski }
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski Inkscape::XML::Node *root = tempdoc->getReprRoot();
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski // 1293979: strip out the defs of the document
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski root->removeChild(tempdoc->getDefs()->getRepr());
f9325af537ca5517eb50ef95f432a3204616f6b3apenner
f9325af537ca5517eb50ef95f432a3204616f6b3apenner Inkscape::XML::Node *repr = sp_repr_lookup_name(root, "svg:path", -1); // unlimited search depth
f9325af537ca5517eb50ef95f432a3204616f6b3apenner if ( repr == NULL ) {
f9325af537ca5517eb50ef95f432a3204616f6b3apenner repr = sp_repr_lookup_name(root, "svg:text", -1);
f9325af537ca5517eb50ef95f432a3204616f6b3apenner }
f9325af537ca5517eb50ef95f432a3204616f6b3apenner
f9325af537ca5517eb50ef95f432a3204616f6b3apenner if ( repr == NULL ) {
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh _userWarn(desktop, _("Clipboard does not contain a path."));
f9325af537ca5517eb50ef95f432a3204616f6b3apenner tempdoc->doUnref();
52df193b5d1e7bf4f7fbfbb457248c8d13f2007ebuliabyak return "";
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
f8d5f6dc1f2af1841ce5df731eb121151810e43dKris gchar const *svgd = repr->attribute("id");
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return svgd;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh}
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh/**
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Iterate over a list of items and copy them to the clipboard.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh */
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshvoid ClipboardManagerImpl::_copySelection(Inkscape::Selection *selection)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh{
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh // copy the defs used by all items
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh std::vector<SPItem*> itemlist=selection->itemList();
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh SPItem *item = *i;
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh if (item) {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh _copyUsedDefs(item);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh } else {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh g_assert_not_reached();
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh }
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh }
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
23f9b0c75abbaa8364a61ffaa103a9b0ef871e56apenner // copy the representation of the items
23f9b0c75abbaa8364a61ffaa103a9b0ef871e56apenner std::vector<SPItem*> sorted_items(itemlist);
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski sort(sorted_items.begin(),sorted_items.end(),sp_object_compare_position_bool);
23f9b0c75abbaa8364a61ffaa103a9b0ef871e56apenner
23f9b0c75abbaa8364a61ffaa103a9b0ef871e56apenner for(std::vector<SPItem*>::const_iterator i=sorted_items.begin();i!=sorted_items.end();i++){
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski SPItem *item = *i;
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski if (item) {
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski Inkscape::XML::Node *obj = item->getRepr();
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski Inkscape::XML::Node *obj_copy = _copyNode(obj, _doc, _root);
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski
1c03744513f6db77018fe703507fe04011c20b09Krzysztof KosiƄski // copy complete inherited style
23f9b0c75abbaa8364a61ffaa103a9b0ef871e56apenner SPCSSAttr *css = sp_repr_css_attr_inherited(obj, "style");
23f9b0c75abbaa8364a61ffaa103a9b0ef871e56apenner sp_repr_css_set(obj_copy, css, "style");
23f9b0c75abbaa8364a61ffaa103a9b0ef871e56apenner sp_repr_css_attr_unref(css);
23f9b0c75abbaa8364a61ffaa103a9b0ef871e56apenner
23f9b0c75abbaa8364a61ffaa103a9b0ef871e56apenner Geom::Affine transform=item->i2doc_affine();
23f9b0c75abbaa8364a61ffaa103a9b0ef871e56apenner
23f9b0c75abbaa8364a61ffaa103a9b0ef871e56apenner // write the complete accumulated transform passed to us
23f9b0c75abbaa8364a61ffaa103a9b0ef871e56apenner // (we're dealing with unattached representations, so we write to their attributes
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh // instead of using sp_item_set_transform)
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh SPUse *use=dynamic_cast<SPUse *>(item);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh if( use && selection->includes(use->get_original()) ){//we are copying something whose parent is also copied (!)
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh transform = ((SPItem*)(use->get_original()->parent))->i2doc_affine().inverse() * transform;
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh }
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh gchar *transform_str = sp_svg_transform_write(transform );
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh obj_copy->setAttribute("transform", transform_str);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh g_free(transform_str);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh }
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh }
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh // copy style for Paste Style action
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh if (!sorted_items.empty()) {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh SPObject *object = sorted_items[0];
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh SPItem *item = dynamic_cast<SPItem *>(object);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh if (item) {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh SPCSSAttr *style = take_style_from_item(item);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh sp_repr_css_set(_clipnode, style, "style");
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh sp_repr_css_attr_unref(style);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh }
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh // copy path effect from the first path
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh if (object) {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh gchar const *effect =object->getRepr()->attribute("inkscape:path-effect");
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh if (effect) {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh _clipnode->setAttribute("inkscape:path-effect", effect);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh }
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh }
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh }
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh Geom::OptRect size = selection->visualBounds();
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh if (size) {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh sp_repr_set_point(_clipnode, "min", size->min());
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh sp_repr_set_point(_clipnode, "max", size->max());
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh }
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh}
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh/**
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh * Recursively copy all the definitions used by a given item to the clipboard defs.
07b7f1aaaf1087716e784a50cf574a059f7018d3Jon A. Cruz */
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7mikloshvoid ClipboardManagerImpl::_copyUsedDefs(SPItem *item)
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh{
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh // copy fill and stroke styles (patterns and gradients)
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh SPStyle *style = item->style;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (style && (style->fill.isPaintserver())) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPPaintServer *server = item->style->getFillPaintServer();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( dynamic_cast<SPLinearGradient *>(server) || dynamic_cast<SPRadialGradient *>(server) ) {
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh _copyGradient(dynamic_cast<SPGradient *>(server));
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh SPPattern *pattern = dynamic_cast<SPPattern *>(server);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( pattern ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _copyPattern(pattern);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (style && (style->stroke.isPaintserver())) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPPaintServer *server = item->style->getStrokePaintServer();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( dynamic_cast<SPLinearGradient *>(server) || dynamic_cast<SPRadialGradient *>(server) ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _copyGradient(dynamic_cast<SPGradient *>(server));
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh SPPattern *pattern = dynamic_cast<SPPattern *>(server);
f8d5f6dc1f2af1841ce5df731eb121151810e43dKris if ( pattern ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _copyPattern(pattern);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // For shapes, copy all of the shape's markers
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPShape *shape = dynamic_cast<SPShape *>(item);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (shape) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh for (int i = 0 ; i < SP_MARKER_LOC_QTY ; i++) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (shape->_marker[i]) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _copyNode(shape->_marker[i]->getRepr(), _doc, _defs);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
f8d5f6dc1f2af1841ce5df731eb121151810e43dKris }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // For lpe items, copy lpe stack if applicable
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (lpeitem) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (lpeitem->hasPathEffect()) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh for (PathEffectList::iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); ++it)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh LivePathEffectObject *lpeobj = (*it)->lpeobject;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (lpeobj) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _copyNode(lpeobj->getRepr(), _doc, _defs);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // For 3D boxes, copy perspectives
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh {
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh SPBox3D *box = dynamic_cast<SPBox3D *>(item);
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen if (box) {
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh _copyNode(box3d_get_perspective(box)->getRepr(), _doc, _defs);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
35636e0c762d50c37515a072b12bdc0197afd24cMatthew Petroff }
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh // Copy text paths
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh {
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh SPText *text = dynamic_cast<SPText *>(item);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh SPTextPath *textpath = (text) ? dynamic_cast<SPTextPath *>(text->firstChild()) : NULL;
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh if (textpath) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _copyTextPath(textpath);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // Copy clipping objects
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh if (item->clip_ref){
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (item->clip_ref->getObject()) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _copyNode(item->clip_ref->getObject()->getRepr(), _doc, _defs);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
07b7f1aaaf1087716e784a50cf574a059f7018d3Jon A. Cruz // Copy mask objects
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (item->mask_ref){
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (item->mask_ref->getObject()) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPObject *mask = item->mask_ref->getObject();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _copyNode(mask->getRepr(), _doc, _defs);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // recurse into the mask for its gradients etc.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh for (SPObject *o = mask->children ; o != NULL ; o = o->next) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPItem *childItem = dynamic_cast<SPItem *>(o);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (childItem) {
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh _copyUsedDefs(childItem);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh // Copy filters
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh if (style->getFilter()) {
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh SPObject *filter = style->getFilter();
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh if (dynamic_cast<SPFilter *>(filter)) {
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh _copyNode(filter->getRepr(), _doc, _defs);
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh }
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh }
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh // recurse
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh for (SPObject *o = item->children ; o != NULL ; o = o->next) {
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh SPItem *childItem = dynamic_cast<SPItem *>(o);
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh if (childItem) {
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh _copyUsedDefs(childItem);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh}
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh/**
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh * Copy a single gradient to the clipboard's defs element.
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh */
d27f5758e12c3107ee69e66702043931e0756f6bmikloshvoid ClipboardManagerImpl::_copyGradient(SPGradient *gradient)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh{
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh while (gradient) {
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh // climb up the refs, copying each one in the chain
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh _copyNode(gradient->getRepr(), _doc, _defs);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh if (gradient->ref){
f8d5f6dc1f2af1841ce5df731eb121151810e43dKris gradient = gradient->ref->getObject();
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
f8d5f6dc1f2af1841ce5df731eb121151810e43dKris else {
8ec52d39f409ecf67125cd4d878b844e9391e7e8miklosh gradient = NULL;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
8ec52d39f409ecf67125cd4d878b844e9391e7e8miklosh }
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh}
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
8ec52d39f409ecf67125cd4d878b844e9391e7e8miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh/**
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Copy a single pattern to the clipboard document's defs element.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh */
d27f5758e12c3107ee69e66702043931e0756f6bmikloshvoid ClipboardManagerImpl::_copyPattern(SPPattern *pattern)
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh{
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh // climb up the references, copying each one in the chain
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh while (pattern) {
8ec52d39f409ecf67125cd4d878b844e9391e7e8miklosh _copyNode(pattern->getRepr(), _doc, _defs);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh // items in the pattern may also use gradients and other patterns, so recurse
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh for ( SPObject *child = pattern->firstChild() ; child ; child = child->getNext() ) {
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh SPItem *childItem = dynamic_cast<SPItem *>(child);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh if (childItem) {
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh _copyUsedDefs(childItem);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (pattern->ref){
f8d5f6dc1f2af1841ce5df731eb121151810e43dKris pattern = pattern->ref->getObject();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner else{
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh pattern = NULL;
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner }
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner}
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh/**
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner * Copy a text path to the clipboard's defs element.
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh */
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apennervoid ClipboardManagerImpl::_copyTextPath(SPTextPath *tp)
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner{
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner SPItem *path = sp_textpath_get_path_item(tp);
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner if (!path) {
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner return;
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner }
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner Inkscape::XML::Node *path_node = path->getRepr();
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner // Do not copy the text path to defs if it's already copied
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner if (sp_repr_lookup_child(_root, "id", path_node->attribute("id"))) {
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh return;
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner }
0b849742fd99bcacdccf85aa8dfe4e10e9269b52apenner _copyNode(path_node, _doc, _defs);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh}
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh/**
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Copy a single XML node from one document to another.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * @param node The node to be copied
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * @param target_doc The document to which the node is to be copied
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * @param parent The node in the target document which will become the parent of the copied node
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh * @return Pointer to the copied node
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh */
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshInkscape::XML::Node *ClipboardManagerImpl::_copyNode(Inkscape::XML::Node *node, Inkscape::XML::Document *target_doc, Inkscape::XML::Node *parent)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::XML::Node *dup = node->duplicate(target_doc);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh parent->appendChild(dup);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::GC::release(dup);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return dup;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
75b857d473541532819bd791105cb352c9a43214buliabyak/**
75b857d473541532819bd791105cb352c9a43214buliabyak * Retrieve a bitmap image from the clipboard and paste it into the active document.
75b857d473541532819bd791105cb352c9a43214buliabyak */
75b857d473541532819bd791105cb352c9a43214buliabyakbool ClipboardManagerImpl::_pasteImage(SPDocument *doc)
75b857d473541532819bd791105cb352c9a43214buliabyak{
75b857d473541532819bd791105cb352c9a43214buliabyak if ( doc == NULL ) {
6d88281c43eaaa66f863d9634632174b0848ea99Jon A. Cruz return false;
75b857d473541532819bd791105cb352c9a43214buliabyak }
6d88281c43eaaa66f863d9634632174b0848ea99Jon A. Cruz
6d88281c43eaaa66f863d9634632174b0848ea99Jon A. Cruz // retrieve image data
75b857d473541532819bd791105cb352c9a43214buliabyak Glib::RefPtr<Gdk::Pixbuf> img = _clipboard->wait_for_image();
75b857d473541532819bd791105cb352c9a43214buliabyak if (!img) {
75b857d473541532819bd791105cb352c9a43214buliabyak return false;
75b857d473541532819bd791105cb352c9a43214buliabyak }
75b857d473541532819bd791105cb352c9a43214buliabyak
75b857d473541532819bd791105cb352c9a43214buliabyak // TODO unify with interface.cpp's sp_ui_drag_data_received()
75b857d473541532819bd791105cb352c9a43214buliabyak // AARGH stupid
75b857d473541532819bd791105cb352c9a43214buliabyak Inkscape::Extension::DB::InputList o;
75b857d473541532819bd791105cb352c9a43214buliabyak Inkscape::Extension::db.get_input_list(o);
75b857d473541532819bd791105cb352c9a43214buliabyak Inkscape::Extension::DB::InputList::const_iterator i = o.begin();
75b857d473541532819bd791105cb352c9a43214buliabyak while (i != o.end() && strcmp( (*i)->get_mimetype(), "image/png" ) != 0) {
75b857d473541532819bd791105cb352c9a43214buliabyak ++i;
75b857d473541532819bd791105cb352c9a43214buliabyak }
6d88281c43eaaa66f863d9634632174b0848ea99Jon A. Cruz Inkscape::Extension::Extension *png = *i;
75b857d473541532819bd791105cb352c9a43214buliabyak Inkscape::Preferences *prefs = Inkscape::Preferences::get();
75b857d473541532819bd791105cb352c9a43214buliabyak Glib::ustring attr_saved = prefs->getString("/dialogs/import/link");
75b857d473541532819bd791105cb352c9a43214buliabyak bool ask_saved = prefs->getBool("/dialogs/import/ask");
75b857d473541532819bd791105cb352c9a43214buliabyak prefs->setString("/dialogs/import/link", "embed");
75b857d473541532819bd791105cb352c9a43214buliabyak prefs->setBool("/dialogs/import/ask", false);
75b857d473541532819bd791105cb352c9a43214buliabyak png->set_gui(false);
75b857d473541532819bd791105cb352c9a43214buliabyak
75b857d473541532819bd791105cb352c9a43214buliabyak gchar *filename = g_build_filename( g_get_tmp_dir(), "inkscape-clipboard-import", NULL );
75b857d473541532819bd791105cb352c9a43214buliabyak img->save(filename, "png");
75b857d473541532819bd791105cb352c9a43214buliabyak file_import(doc, filename, png);
75b857d473541532819bd791105cb352c9a43214buliabyak g_free(filename);
75b857d473541532819bd791105cb352c9a43214buliabyak prefs->setString("/dialogs/import/link", attr_saved);
75b857d473541532819bd791105cb352c9a43214buliabyak prefs->setBool("/dialogs/import/ask", ask_saved);
75b857d473541532819bd791105cb352c9a43214buliabyak png->set_gui(true);
75b857d473541532819bd791105cb352c9a43214buliabyak
75b857d473541532819bd791105cb352c9a43214buliabyak return true;
6d88281c43eaaa66f863d9634632174b0848ea99Jon A. Cruz}
75b857d473541532819bd791105cb352c9a43214buliabyak
75b857d473541532819bd791105cb352c9a43214buliabyak/**
75b857d473541532819bd791105cb352c9a43214buliabyak * Paste text into the selected text object or create a new one to hold it.
75b857d473541532819bd791105cb352c9a43214buliabyak */
6d88281c43eaaa66f863d9634632174b0848ea99Jon A. Cruzbool ClipboardManagerImpl::_pasteText(SPDesktop *desktop)
75b857d473541532819bd791105cb352c9a43214buliabyak{
75b857d473541532819bd791105cb352c9a43214buliabyak if ( desktop == NULL ) {
75b857d473541532819bd791105cb352c9a43214buliabyak return false;
75b857d473541532819bd791105cb352c9a43214buliabyak }
75b857d473541532819bd791105cb352c9a43214buliabyak
75b857d473541532819bd791105cb352c9a43214buliabyak // if the text editing tool is active, paste the text into the active text object
75b857d473541532819bd791105cb352c9a43214buliabyak if (tools_isactive(desktop, TOOLS_TEXT)) {
75b857d473541532819bd791105cb352c9a43214buliabyak return Inkscape::UI::Tools::sp_text_paste_inline(desktop->event_context);
75b857d473541532819bd791105cb352c9a43214buliabyak }
75b857d473541532819bd791105cb352c9a43214buliabyak
75b857d473541532819bd791105cb352c9a43214buliabyak // try to parse the text as a color and, if successful, apply it as the current style
75b857d473541532819bd791105cb352c9a43214buliabyak SPCSSAttr *css = sp_repr_css_attr_parse_color_to_fill(_clipboard->wait_for_text());
75b857d473541532819bd791105cb352c9a43214buliabyak if (css) {
75b857d473541532819bd791105cb352c9a43214buliabyak sp_desktop_set_style(desktop, css);
75b857d473541532819bd791105cb352c9a43214buliabyak return true;
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh }
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh return false;
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh}
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues/**
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues * Applies a pasted path effect to a given item.
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues */
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBluesvoid ClipboardManagerImpl::_applyPathEffect(SPItem *item, gchar const *effectstack)
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues{
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues if ( item == NULL ) {
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues return;
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues }
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues if ( dynamic_cast<SPRect *>(item) ) {
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues return;
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues }
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item);
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues if (lpeitem)
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh {
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh // for each effect in the stack, check if we need to fork it before adding it to the item
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh lpeitem->forkPathEffectsIfNecessary(1);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh std::istringstream iss(effectstack);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh std::string href;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh while (std::getline(iss, href, ';'))
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh SPObject *obj = sp_uri_reference_resolve(_clipboardSPDoc, href.c_str());
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh if (!obj) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh LivePathEffectObject *lpeobj = LIVEPATHEFFECT(obj);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh lpeitem->addPathEffect(lpeobj);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
eff8fb9acfee4431530d9bf8e4e038c8516fd369Luca Bruno
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
082cac3fb4c7fc60e92bbd4de269550801dcea6bmiklosh/**
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues * Retrieve the clipboard contents as a document.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh * @return Clipboard contents converted to SPDocument, or NULL if no suitable content was present
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh */
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshSPDocument *ClipboardManagerImpl::_retrieveClipboard(Glib::ustring required_target)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Glib::ustring best_target;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( required_target == "" ) {
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh best_target = _getBestTarget();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh } else {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh best_target = required_target;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( best_target == "" ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return NULL;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
77364929ced3ec0bc5c9f47440606615c559084emiklosh
77364929ced3ec0bc5c9f47440606615c559084emiklosh // FIXME: Temporary hack until we add memory input.
77364929ced3ec0bc5c9f47440606615c559084emiklosh // Save the clipboard contents to some file, then read it
77364929ced3ec0bc5c9f47440606615c559084emiklosh gchar *filename = g_build_filename( g_get_tmp_dir(), "inkscape-clipboard-import", NULL );
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh
77364929ced3ec0bc5c9f47440606615c559084emiklosh bool file_saved = false;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Glib::ustring target = best_target;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#ifdef WIN32
75b857d473541532819bd791105cb352c9a43214buliabyak if (best_target == "CF_ENHMETAFILE" || best_target == "WCF_ENHMETAFILE")
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh { // Try to save clipboard data as en emf file (using win32 api)
75b857d473541532819bd791105cb352c9a43214buliabyak if (OpenClipboard(NULL)) {
75b857d473541532819bd791105cb352c9a43214buliabyak HGLOBAL hglb = GetClipboardData(CF_ENHMETAFILE);
75b857d473541532819bd791105cb352c9a43214buliabyak if (hglb) {
75b857d473541532819bd791105cb352c9a43214buliabyak HENHMETAFILE hemf = CopyEnhMetaFile((HENHMETAFILE) hglb, filename);
75b857d473541532819bd791105cb352c9a43214buliabyak if (hemf) {
75b857d473541532819bd791105cb352c9a43214buliabyak file_saved = true;
75b857d473541532819bd791105cb352c9a43214buliabyak target = "image/x-emf";
75b857d473541532819bd791105cb352c9a43214buliabyak DeleteEnhMetaFile(hemf);
75b857d473541532819bd791105cb352c9a43214buliabyak }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh CloseClipboard();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#endif
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh if (!file_saved) {
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh if ( !_clipboard->wait_is_target_available(best_target) ) {
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh return NULL;
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh }
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh // doing this synchronously makes better sense
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // TODO: use another method because this one is badly broken imo.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // from documentation: "Returns: A SelectionData object, which will be invalid if retrieving the given target failed."
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // I don't know how to check whether an object is 'valid' or not, unusable if that's not possible...
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Gtk::SelectionData sel = _clipboard->wait_for_contents(best_target);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh target = sel.get_target(); // this can crash if the result was invalid of last function. No way to check for this :(
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // FIXME: Temporary hack until we add memory input.
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh // Save the clipboard contents to some file, then read it
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh g_file_set_contents(filename, (const gchar *) sel.get_data(), sel.get_length(), NULL);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // there is no specific plain SVG input extension, so if we can paste the Inkscape SVG format,
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues // we use the image/svg+xml mimetype to look up the input extension
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (target == "image/x-inkscape-svg") {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh target = "image/svg+xml";
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // Use the EMF extension to import metafiles
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (target == "CF_ENHMETAFILE" || target == "WCF_ENHMETAFILE") {
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh target = "image/x-emf";
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh }
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh Inkscape::Extension::DB::InputList inlist;
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh Inkscape::Extension::db.get_input_list(inlist);
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh Inkscape::Extension::DB::InputList::const_iterator in = inlist.begin();
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh for (; in != inlist.end() && target != (*in)->get_mimetype() ; ++in) {
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh };
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh if ( in == inlist.end() ) {
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues return NULL; // this shouldn't happen unless _getBestTarget returns something bogus
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh }
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh SPDocument *tempdoc = NULL;
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh try {
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh tempdoc = (*in)->open(filename);
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh } catch (...) {
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh g_unlink(filename);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh g_free(filename);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return tempdoc;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues/**
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh * Callback called when some other application requests data from Inkscape.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh *
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues * Finds a suitable output extension to save the internal clipboard document,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh * then saves it to memory and sets the clipboard contents.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh */
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBluesvoid ClipboardManagerImpl::_onGet(Gtk::SelectionData &sel, guint /*info*/)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh g_assert( _clipboardSPDoc != NULL );
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Glib::ustring target = sel.get_target();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (target == "") {
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues return; // this shouldn't happen
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues if (target == CLIPBOARD_TEXT_TARGET) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh target = "image/x-inkscape-svg";
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::Extension::DB::OutputList outlist;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::Extension::db.get_output_list(outlist);
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues Inkscape::Extension::DB::OutputList::const_iterator out = outlist.begin();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh for ( ; out != outlist.end() && target != (*out)->get_mimetype() ; ++out) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh };
0e14f9e966c4b6012538d30cd0db7a775b879760JucaBlues if ( out == outlist.end() && target != "image/png") {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return; // this also shouldn't happen
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // FIXME: Temporary hack until we add support for memory output.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // Save to a temporary file, read it back and then set the clipboard contents
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh gchar *filename = g_build_filename( g_get_tmp_dir(), "inkscape-clipboard-export", NULL );
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh gsize len; gchar *data;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh try {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (out == outlist.end() && target == "image/png")
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh {
fd39535b3a5276f8962a3f99072668f3e63421edmiklosh gdouble dpi = Inkscape::Util::Quantity::convert(1, "in", "px");
fd39535b3a5276f8962a3f99072668f3e63421edmiklosh guint32 bgcolor = 0x00000000;
fd39535b3a5276f8962a3f99072668f3e63421edmiklosh
fd39535b3a5276f8962a3f99072668f3e63421edmiklosh Geom::Point origin (_clipboardSPDoc->getRoot()->x.computed, _clipboardSPDoc->getRoot()->y.computed);
fd39535b3a5276f8962a3f99072668f3e63421edmiklosh Geom::Rect area = Geom::Rect(origin, origin + _clipboardSPDoc->getDimensions());
fd39535b3a5276f8962a3f99072668f3e63421edmiklosh
77364929ced3ec0bc5c9f47440606615c559084emiklosh unsigned long int width = (unsigned long int) (Inkscape::Util::Quantity::convert(area.width(), "px", "in") * dpi + 0.5);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh unsigned long int height = (unsigned long int) (Inkscape::Util::Quantity::convert(area.height(), "in", "px") * dpi + 0.5);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // read from namedview
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::XML::Node *nv = sp_repr_lookup_name (_clipboardSPDoc->rroot, "sodipodi:namedview");
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (nv && nv->attribute("pagecolor")) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (nv && nv->attribute("inkscape:pageopacity")) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh double opacity = 1.0;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh sp_repr_get_double(nv, "inkscape:pageopacity", &opacity);
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh bgcolor |= SP_COLOR_F_TO_U(opacity);
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh }
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh std::vector<SPItem*> x;
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh sp_export_png_file(_clipboardSPDoc, filename, area, width, height, dpi, dpi, bgcolor, NULL, NULL, true, x);
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh }
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh else
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh {
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh if (!(*out)->loaded()) {
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh // Need to load the extension.
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh (*out)->set_state(Inkscape::Extension::Extension::STATE_LOADED);
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh }
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh (*out)->save(_clipboardSPDoc, filename);
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh }
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh g_file_get_contents(filename, &data, &len, NULL);
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh sel.set(8, (guint8 const *) data, len);
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh } catch (...) {
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh }
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh
17d87f5698f5c2958d38c6a6207c7b322a7adaf9johanengelen g_unlink(filename); // delete the temporary file
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh g_free(filename);
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh}
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh/**
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh * Callback when someone else takes the clipboard.
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh *
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh * When the clipboard owner changes, this callback clears the internal clipboard document
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh * to reduce memory usage.
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh */
03e63790ef0fa2919fc5f9f3e0d018adf317919dmikloshvoid ClipboardManagerImpl::_onClear()
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh{
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh // why is this called before _onGet???
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh //_discardInternalClipboard();
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh}
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh/**
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh * Creates an internal clipboard document from scratch.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen */
03e63790ef0fa2919fc5f9f3e0d018adf317919dmikloshvoid ClipboardManagerImpl::_createInternalClipboard()
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh{
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh if ( _clipboardSPDoc == NULL ) {
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh _clipboardSPDoc = SPDocument::createNewDoc(NULL, false, true);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh //g_assert( _clipboardSPDoc != NULL );
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh _defs = _clipboardSPDoc->getDefs()->getRepr();
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh _doc = _clipboardSPDoc->getReprDoc();
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh _root = _clipboardSPDoc->getReprRoot();
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh _clipnode = _doc->createElement("inkscape:clipboard");
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh _root->appendChild(_clipnode);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh Inkscape::GC::release(_clipnode);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // once we create a SVG document, style will be stored in it, so flush _text_style
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (_text_style) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh sp_repr_css_attr_unref(_text_style);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _text_style = NULL;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
d2ac881b8a3bc4613547b9173681ff1752eaa0e2Kris}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh/**
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh * Deletes the internal clipboard document.
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh */
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid ClipboardManagerImpl::_discardInternalClipboard()
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( _clipboardSPDoc != NULL ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _clipboardSPDoc->doUnref();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _clipboardSPDoc = NULL;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _defs = NULL;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _doc = NULL;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _root = NULL;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _clipnode = NULL;
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen }
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh}
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh/**
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh * Get the scale to resize an item, based on the command and desktop state.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh */
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshGeom::Scale ClipboardManagerImpl::_getScale(SPDesktop *desktop, Geom::Point const &min, Geom::Point const &max, Geom::Rect const &obj_rect, bool apply_x, bool apply_y)
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh{
17d87f5698f5c2958d38c6a6207c7b322a7adaf9johanengelen double scale_x = 1.0;
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh double scale_y = 1.0;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (apply_x) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh scale_x = (max[Geom::X] - min[Geom::X]) / obj_rect[Geom::X].extent();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (apply_y) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh scale_y = (max[Geom::Y] - min[Geom::Y]) / obj_rect[Geom::Y].extent();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // If the "lock aspect ratio" button is pressed and we paste only a single coordinate,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // resize the second one by the same ratio too
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (desktop->isToolboxButtonActive("lock")) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (apply_x && !apply_y) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh scale_y = scale_x;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (apply_y && !apply_x) {
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh scale_x = scale_y;
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh }
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh }
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return Geom::Scale(scale_x, scale_y);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh/**
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh * Find the most suitable clipboard target.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh */
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshGlib::ustring ClipboardManagerImpl::_getBestTarget()
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh{
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh // GTKmm's wait_for_targets() is broken, see the comment in _inkscape_wait_for_targets()
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh std::list<Glib::ustring> targets; // = _clipboard->wait_for_targets();
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh _inkscape_wait_for_targets(targets);
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh // clipboard target debugging snippet
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh /*
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh g_message("Begin clipboard targets");
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh for ( std::list<Glib::ustring>::iterator x = targets.begin() ; x != targets.end(); ++x )
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh g_message("Clipboard target: %s", (*x).data());
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh g_message("End clipboard targets\n");
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh //*/
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh for (std::list<Glib::ustring>::iterator i = _preferred_targets.begin() ;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh i != _preferred_targets.end() ; ++i)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( std::find(targets.begin(), targets.end(), *i) != targets.end() ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return *i;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#ifdef WIN32
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (OpenClipboard(NULL))
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh { // If both bitmap and metafile are present, pick the one that was exported first.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh UINT format = EnumClipboardFormats(0);
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh while (format) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (format == CF_ENHMETAFILE || format == CF_DIB || format == CF_BITMAP) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh break;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh format = EnumClipboardFormats(format);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh CloseClipboard();
5834db43b21308e958a2fdbbec082b1a4f019a38bryce
5834db43b21308e958a2fdbbec082b1a4f019a38bryce if (format == CF_ENHMETAFILE) {
5834db43b21308e958a2fdbbec082b1a4f019a38bryce return "CF_ENHMETAFILE";
5834db43b21308e958a2fdbbec082b1a4f019a38bryce }
5834db43b21308e958a2fdbbec082b1a4f019a38bryce if (format == CF_DIB || format == CF_BITMAP) {
5834db43b21308e958a2fdbbec082b1a4f019a38bryce return CLIPBOARD_GDK_PIXBUF_TARGET;
5834db43b21308e958a2fdbbec082b1a4f019a38bryce }
75b857d473541532819bd791105cb352c9a43214buliabyak }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
b9504ebb935416bcb115c17697e49fe9f61aa406apenner if (IsClipboardFormatAvailable(CF_ENHMETAFILE)) {
b9504ebb935416bcb115c17697e49fe9f61aa406apenner return "CF_ENHMETAFILE";
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh }
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh#endif
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (_clipboard->wait_is_image_available()) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return CLIPBOARD_GDK_PIXBUF_TARGET;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (_clipboard->wait_is_text_available()) {
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh return CLIPBOARD_TEXT_TARGET;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh return "";
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh}
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh/**
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh * Set the clipboard targets to reflect the mimetypes Inkscape can output.
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh */
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid ClipboardManagerImpl::_setClipboardTargets()
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
17d87f5698f5c2958d38c6a6207c7b322a7adaf9johanengelen Inkscape::Extension::DB::OutputList outlist;
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh Inkscape::Extension::db.get_output_list(outlist);
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh#if WITH_GTKMM_3_0
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh std::vector<Gtk::TargetEntry> target_list;
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh#else
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh std::list<Gtk::TargetEntry> target_list;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#endif
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh bool plaintextSet = false;
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh for (Inkscape::Extension::DB::OutputList::const_iterator out = outlist.begin() ; out != outlist.end() ; ++out) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( !(*out)->deactivated() ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Glib::ustring mime = (*out)->get_mimetype();
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz if (mime != CLIPBOARD_TEXT_TARGET) {
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz if ( !plaintextSet && (mime.find("svg") == Glib::ustring::npos) ) {
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould target_list.push_back(Gtk::TargetEntry(CLIPBOARD_TEXT_TARGET));
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh plaintextSet = true;
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh }
84d6d1f7365e49f2936df9df890ce49d2c000ce2Kris target_list.push_back(Gtk::TargetEntry(mime));
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // Add PNG export explicitly since there is no extension for this...
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // On Windows, GTK will also present this as a CF_DIB/CF_BITMAP
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh target_list.push_back(Gtk::TargetEntry( "image/png" ));
c0d6314019bde0047778d2cabb7ec2bf4083f5fcJon A. Cruz
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _clipboard->set(target_list,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh sigc::mem_fun(*this, &ClipboardManagerImpl::_onGet),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh sigc::mem_fun(*this, &ClipboardManagerImpl::_onClear));
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#ifdef WIN32
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // If the "image/x-emf" target handled by the emf extension would be
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // presented as a CF_ENHMETAFILE automatically (just like an "image/bmp"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // is presented as a CF_BITMAP) this code would not be needed.. ???
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // Or maybe there is some other way to achieve the same?
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // Note: Metafile is the only format that is rendered and stored in clipboard
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // on Copy, all other formats are rendered only when needed by a Paste command.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // FIXME: This should at least be rewritten to use "delayed rendering".
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // If possible make it delayed rendering by using GTK API only.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (OpenClipboard(NULL)) {
c0d6314019bde0047778d2cabb7ec2bf4083f5fcJon A. Cruz if ( _clipboardSPDoc != NULL ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh const Glib::ustring target = "image/x-emf";
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::Extension::DB::OutputList outlist;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::Extension::db.get_output_list(outlist);
405079a6cf76f81a583a9b8556c1ca49840abc6eKris Inkscape::Extension::DB::OutputList::const_iterator out = outlist.begin();
17d87f5698f5c2958d38c6a6207c7b322a7adaf9johanengelen for ( ; out != outlist.end() && target != (*out)->get_mimetype() ; ++out) {
797add969622b3786436365fdd275aff9a9a6373miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( out != outlist.end() ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // FIXME: Temporary hack until we add support for memory output.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // Save to a temporary file, read it back and then set the clipboard contents
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz gchar *filename = g_build_filename( g_get_tmp_dir(), "inkscape-clipboard-export.emf", NULL );
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz
17d87f5698f5c2958d38c6a6207c7b322a7adaf9johanengelen try {
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh (*out)->save(_clipboardSPDoc, filename);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh HENHMETAFILE hemf = GetEnhMetaFileA(filename);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (hemf) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh SetClipboardData(CF_ENHMETAFILE, hemf);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh DeleteEnhMetaFile(hemf);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
17d87f5698f5c2958d38c6a6207c7b322a7adaf9johanengelen } catch (...) {
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh }
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh g_unlink(filename); // delete the temporary file
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh g_free(filename);
17d87f5698f5c2958d38c6a6207c7b322a7adaf9johanengelen }
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh CloseClipboard();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz#endif
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz}
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz/**
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz * Set the string representation of a 32-bit RGBA color as the clipboard contents.
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz */
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruzvoid ClipboardManagerImpl::_setClipboardColor(guint32 color)
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz{
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz gchar colorstr[16];
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz g_snprintf(colorstr, 16, "%08x", color);
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz _clipboard->set_text(colorstr);
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz}
e454b92b3d16b0909892cddef064b745898c924dJon A. Cruz
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh/**
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh * Put a notification on the mesage stack.
405079a6cf76f81a583a9b8556c1ca49840abc6eKris */
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid ClipboardManagerImpl::_userWarn(SPDesktop *desktop, char const *msg)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, msg);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh// GTKMM's clipboard::wait_for_targets is buggy and might return bogus, see
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh//
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh// https://bugs.launchpad.net/inkscape/+bug/296778
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh// http://mail.gnome.org/archives/gtk-devel-list/2009-June/msg00062.html
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh//
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh// for details. Until this has been fixed upstream we will use our own implementation
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh// of this method, as copied from /gtkmm-2.16.0/gtk/gtkmm/clipboard.cc.
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid ClipboardManagerImpl::_inkscape_wait_for_targets(std::list<Glib::ustring> &listTargets)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Get a newly-allocated array of atoms:
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh GdkAtom* targets = NULL;
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh gint n_targets = 0;
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh gboolean test = gtk_clipboard_wait_for_targets( gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), &targets, &n_targets );
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (!test || (targets == NULL)) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
c0d6314019bde0047778d2cabb7ec2bf4083f5fcJon A. Cruz
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Add the targets to the C++ container:
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh for (int i = 0; i < n_targets; i++)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Convert the atom to a string:
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh gchar* const atom_name = gdk_atom_name(targets[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Glib::ustring target;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (atom_name) {
c0d6314019bde0047778d2cabb7ec2bf4083f5fcJon A. Cruz target = Glib::ScopedPtr<char>(atom_name).get(); //This frees the gchar*.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh listTargets.push_back(target);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh/* #######################################
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh ClipboardManager class
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh ####################################### */
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshClipboardManager *ClipboardManager::_instance = NULL;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshClipboardManager::ClipboardManager() {}
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshClipboardManager::~ClipboardManager() {}
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshClipboardManager *ClipboardManager::get()
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( _instance == NULL ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _instance = new ClipboardManagerImpl;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return _instance;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh} // namespace Inkscape
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh} // namespace IO
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh/*
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Local Variables:
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh mode:c++
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh c-file-style:"stroustrup"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh indent-tabs-mode:nil
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh fill-column:99
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh End:
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh*/
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh