summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKris De Gussem <kris.degussem@gmail.com>2012-04-05 05:06:43 +0000
committerKris <Kris.De.Gussem@hotmail.com>2012-04-05 05:06:43 +0000
commit9ff6ffd913086ac953e79231c2a3345f997589fe (patch)
treeca090d1c76e439a0f704de753e8789f2df071b51 /src
parentc++ification: GHashTable > std::map (bug #970237 ; patch by Samuel Chase + so... (diff)
downloadinkscape-9ff6ffd913086ac953e79231c2a3345f997589fe.tar.gz
inkscape-9ff6ffd913086ac953e79231c2a3345f997589fe.zip
Clipboard code cleaning (patch for bug #964852 by Romain, see devmail thread "Some clipboard functions")
(bzr r11153)
Diffstat (limited to 'src')
-rw-r--r--src/document.cpp22
-rw-r--r--src/document.h2
-rw-r--r--src/file.cpp84
-rw-r--r--src/file.h2
-rw-r--r--src/ui/clipboard.cpp185
-rw-r--r--src/xml/repr-css.cpp71
-rw-r--r--src/xml/repr.h1
7 files changed, 187 insertions, 180 deletions
diff --git a/src/document.cpp b/src/document.cpp
index 18d714bad..7b68dd499 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -48,6 +48,7 @@
#include "document-private.h"
#include "document-undo.h"
#include "helper/units.h"
+#include "id-clash.h"
#include "inkscape-private.h"
#include "inkscape-version.h"
#include "libavoid/router.h"
@@ -1432,6 +1433,27 @@ void SPDocument::setModifiedSinceSave(bool modified) {
dtw->updateTitle( this->getName() );
}
+
+/**
+ * Paste SVG defs from the document retrieved from the clipboard into the active document.
+ * @param clipdoc The document to paste.
+ * @pre @c clipdoc != NULL and pasting into the active document is possible.
+ */
+void SPDocument::importDefs(SPDocument *source)
+{
+ Inkscape::XML::Node *root = source->getReprRoot();
+ Inkscape::XML::Node *defs = sp_repr_lookup_name(root, "svg:defs", 1);
+ Inkscape::XML::Node *target_defs = this->getDefs()->getRepr();
+
+ prevent_id_clashes(source, this);
+
+ for (Inkscape::XML::Node *def = defs->firstChild() ; def ; def = def->next()) {
+ Inkscape::XML::Node * dup = def->duplicate(this->getReprDoc());
+ target_defs->appendChild(dup);
+ Inkscape::GC::release(dup);
+ }
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/document.h b/src/document.h
index e41ec4d59..ca709a8b6 100644
--- a/src/document.h
+++ b/src/document.h
@@ -247,6 +247,8 @@ public:
unsigned int vacuumDocument();
+ void importDefs(SPDocument *source);
+
private:
void do_change_uri(gchar const *const filename, bool const rebase);
void setupViewport(SPItemCtx *ctx);
diff --git a/src/file.cpp b/src/file.cpp
index dbf8fc7d4..88fbc542d 100644
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -36,6 +36,7 @@
#include "dir-util.h"
#include "document-private.h"
#include "document-undo.h"
+#include "event-context.h"
#include "extension/db.h"
#include "extension/input.h"
#include "extension/output.h"
@@ -974,6 +975,89 @@ sp_file_save_a_copy(Gtk::Window &parentWindow, gpointer /*object*/, gpointer /*d
######################*/
/**
+ * Paste the contents of a document into the active desktop.
+ * @param clipdoc The document to paste
+ * @param in_place Whether to paste the selection where it was when copied
+ * @pre @c clipdoc is not empty and items can be added to the current layer
+ */
+void sp_import_document(SPDesktop *desktop, SPDocument *clipdoc, bool in_place)
+{
+ //TODO: merge with file_import()
+
+ SPDocument *target_document = sp_desktop_document(desktop);
+ Inkscape::XML::Node *root = clipdoc->getReprRoot();
+ Inkscape::XML::Node *target_parent = desktop->currentLayer()->getRepr();
+
+ // copy definitions
+ desktop->doc()->importDefs(clipdoc);
+
+ // copy objects
+ GSList *pasted_objects = NULL;
+ for (Inkscape::XML::Node *obj = root->firstChild() ; obj ; obj = obj->next()) {
+ // Don't copy metadata, defs, named views and internal clipboard contents to the document
+ if (!strcmp(obj->name(), "svg:defs")) {
+ continue;
+ }
+ if (!strcmp(obj->name(), "svg:metadata")) {
+ continue;
+ }
+ if (!strcmp(obj->name(), "sodipodi:namedview")) {
+ continue;
+ }
+ if (!strcmp(obj->name(), "inkscape:clipboard")) {
+ continue;
+ }
+ Inkscape::XML::Node *obj_copy = obj->duplicate(target_document->getReprDoc());
+ target_parent->appendChild(obj_copy);
+ Inkscape::GC::release(obj_copy);
+
+ pasted_objects = g_slist_prepend(pasted_objects, (gpointer) obj_copy);
+ }
+
+ // Change the selection to the freshly pasted objects
+ Inkscape::Selection *selection = sp_desktop_selection(desktop);
+ selection->setReprList(pasted_objects);
+
+ // invers apply parent transform
+ Geom::Affine doc2parent = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
+ sp_selection_apply_affine(selection, desktop->dt2doc() * doc2parent * desktop->doc2dt(), true, false);
+
+ // Update (among other things) all curves in paths, for bounds() to work
+ target_document->ensureUpToDate();
+
+ // move selection either to original position (in_place) or to mouse pointer
+ Geom::OptRect sel_bbox = selection->visualBounds();
+ if (sel_bbox) {
+ // get offset of selection to original position of copied elements
+ Geom::Point pos_original;
+ Inkscape::XML::Node *clipnode = sp_repr_lookup_name(root, "inkscape:clipboard", 1);
+ if (clipnode) {
+ Geom::Point min, max;
+ sp_repr_get_point(clipnode, "min", &min);
+ sp_repr_get_point(clipnode, "max", &max);
+ pos_original = Geom::Point(min[Geom::X], max[Geom::Y]);
+ }
+ Geom::Point offset = pos_original - sel_bbox->corner(3);
+
+ if (!in_place) {
+ SnapManager &m = desktop->namedview->snap_manager;
+ m.setup(desktop);
+ sp_event_context_discard_delayed_snap_event(desktop->event_context);
+
+ // get offset from mouse pointer to bbox center, snap to grid if enabled
+ Geom::Point mouse_offset = desktop->point() - sel_bbox->midpoint();
+ offset = m.multipleOfGridPitch(mouse_offset - offset, sel_bbox->midpoint() + offset) + offset;
+ m.unSetup();
+ }
+
+ sp_selection_move_relative(selection, offset);
+ }
+
+ g_slist_free(pasted_objects);
+}
+
+
+/**
* Import a resource. Called by sp_file_import()
*/
SPObject *
diff --git a/src/file.h b/src/file.h
index cd6de2eb1..4d28e57d8 100644
--- a/src/file.h
+++ b/src/file.h
@@ -117,6 +117,8 @@ bool sp_file_save_dialog (Gtk::Window &parentWindow, SPDocument *doc, Inkscape::
## I M P O R T
######################*/
+void sp_import_document(SPDesktop *desktop, SPDocument *clipdoc, bool in_place);
+
/**
* Displays a file selector dialog, to allow the
* user to import data into the current document.
diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp
index b9d6e0c6b..b972997e2 100644
--- a/src/ui/clipboard.cpp
+++ b/src/ui/clipboard.cpp
@@ -70,12 +70,11 @@
#include "live_effects/lpeobject-reference.h"
#include "live_effects/parameter/path.h"
#include "svg/svg.h" // for sp_svg_transform_write, used in _copySelection
-#include "svg/css-ostringstream.h" // used in _parseColor
+#include "svg/css-ostringstream.h" // used in copy
#include "text-context.h"
#include "text-editing.h"
#include "tools-switch.h"
#include "path-chemistry.h"
-#include "id-clash.h"
#include "unit-constants.h"
#include "helper/png-write.h"
#include "svg/svg-color.h"
@@ -129,11 +128,8 @@ private:
void _copyTextPath(SPTextPath *);
Inkscape::XML::Node *_copyNode(Inkscape::XML::Node *, Inkscape::XML::Document *, Inkscape::XML::Node *);
- void _pasteDocument(SPDesktop *desktop, SPDocument *clipdoc, bool in_place);
- void _pasteDefs(SPDesktop *desktop, SPDocument *clipdoc);
bool _pasteImage(SPDocument *doc);
bool _pasteText(SPDesktop *desktop);
- SPCSSAttr *_parseColor(const Glib::ustring &);
void _applyPathEffect(SPItem *, gchar const *);
SPDocument *_retrieveClipboard(Glib::ustring = "");
@@ -334,7 +330,7 @@ bool ClipboardManagerImpl::paste(SPDesktop *desktop, bool in_place)
return false;
}
- _pasteDocument(desktop, tempdoc, in_place);
+ sp_import_document(desktop, tempdoc, in_place);
tempdoc->doUnref();
return true;
@@ -410,7 +406,7 @@ bool ClipboardManagerImpl::pasteStyle(SPDesktop *desktop)
bool pasted = false;
if (clipnode) {
- _pasteDefs(desktop, tempdoc);
+ desktop->doc()->importDefs(tempdoc);
SPCSSAttr *style = sp_repr_css_attr(clipnode, "style");
sp_desktop_set_style(desktop, style);
pasted = true;
@@ -512,7 +508,7 @@ bool ClipboardManagerImpl::pastePathEffect(SPDesktop *desktop)
if ( clipnode ) {
gchar const *effectstack = clipnode->attribute("inkscape:path-effect");
if ( effectstack ) {
- _pasteDefs(desktop, tempdoc);
+ desktop->doc()->importDefs(tempdoc);
// make sure all selected items are converted to paths first (i.e. rectangles)
sp_selected_to_lpeitems(desktop);
for (GSList *itemptr = const_cast<GSList *>(selection->itemList()) ; itemptr ; itemptr = itemptr->next) {
@@ -803,107 +799,6 @@ Inkscape::XML::Node *ClipboardManagerImpl::_copyNode(Inkscape::XML::Node *node,
/**
- * Paste the contents of a document into the active desktop.
- * @param clipdoc The document to paste
- * @param in_place Whether to paste the selection where it was when copied
- * @pre @c clipdoc is not empty and items can be added to the current layer
- */
-void ClipboardManagerImpl::_pasteDocument(SPDesktop *desktop, SPDocument *clipdoc, bool in_place)
-{
- SPDocument *target_document = sp_desktop_document(desktop);
- Inkscape::XML::Node *root = clipdoc->getReprRoot();
- Inkscape::XML::Node *target_parent = desktop->currentLayer()->getRepr();
- Inkscape::XML::Document *target_xmldoc = target_document->getReprDoc();
-
- // copy definitions
- _pasteDefs(desktop, clipdoc);
-
- // copy objects
- GSList *pasted_objects = NULL;
- for (Inkscape::XML::Node *obj = root->firstChild() ; obj ; obj = obj->next()) {
- // Don't copy metadata, defs, named views and internal clipboard contents to the document
- if (!strcmp(obj->name(), "svg:defs")) {
- continue;
- }
- if (!strcmp(obj->name(), "svg:metadata")) {
- continue;
- }
- if (!strcmp(obj->name(), "sodipodi:namedview")) {
- continue;
- }
- if (!strcmp(obj->name(), "inkscape:clipboard")) {
- continue;
- }
- Inkscape::XML::Node *obj_copy = _copyNode(obj, target_xmldoc, target_parent);
- pasted_objects = g_slist_prepend(pasted_objects, (gpointer) obj_copy);
- }
-
- // Change the selection to the freshly pasted objects
- Inkscape::Selection *selection = sp_desktop_selection(desktop);
- selection->setReprList(pasted_objects);
-
- // invers apply parent transform
- Geom::Affine doc2parent = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
- sp_selection_apply_affine(selection, desktop->dt2doc() * doc2parent * desktop->doc2dt(), true, false);
-
- // Update (among other things) all curves in paths, for bounds() to work
- target_document->ensureUpToDate();
-
- // move selection either to original position (in_place) or to mouse pointer
- Geom::OptRect sel_bbox = selection->visualBounds();
- if (sel_bbox) {
- // get offset of selection to original position of copied elements
- Geom::Point pos_original;
- Inkscape::XML::Node *clipnode = sp_repr_lookup_name(root, "inkscape:clipboard", 1);
- if (clipnode) {
- Geom::Point min, max;
- sp_repr_get_point(clipnode, "min", &min);
- sp_repr_get_point(clipnode, "max", &max);
- pos_original = Geom::Point(min[Geom::X], max[Geom::Y]);
- }
- Geom::Point offset = pos_original - sel_bbox->corner(3);
-
- if (!in_place) {
- SnapManager &m = desktop->namedview->snap_manager;
- m.setup(desktop);
- sp_event_context_discard_delayed_snap_event(desktop->event_context);
-
- // get offset from mouse pointer to bbox center, snap to grid if enabled
- Geom::Point mouse_offset = desktop->point() - sel_bbox->midpoint();
- offset = m.multipleOfGridPitch(mouse_offset - offset, sel_bbox->midpoint() + offset) + offset;
- m.unSetup();
- }
-
- sp_selection_move_relative(selection, offset);
- }
-
- g_slist_free(pasted_objects);
-}
-
-
-/**
- * Paste SVG defs from the document retrieved from the clipboard into the active document.
- * @param clipdoc The document to paste.
- * @pre @c clipdoc != NULL and pasting into the active document is possible.
- */
-void ClipboardManagerImpl::_pasteDefs(SPDesktop *desktop, SPDocument *clipdoc)
-{
- // boilerplate vars copied from _pasteDocument
- SPDocument *target_document = sp_desktop_document(desktop);
- Inkscape::XML::Node *root = clipdoc->getReprRoot();
- Inkscape::XML::Node *defs = sp_repr_lookup_name(root, "svg:defs", 1);
- Inkscape::XML::Node *target_defs = target_document->getDefs()->getRepr();
- Inkscape::XML::Document *target_xmldoc = target_document->getReprDoc();
-
- prevent_id_clashes(clipdoc, target_document);
-
- for (Inkscape::XML::Node *def = defs->firstChild() ; def ; def = def->next()) {
- _copyNode(def, target_xmldoc, target_defs);
- }
-}
-
-
-/**
* Retrieve a bitmap image from the clipboard and paste it into the active document.
*/
bool ClipboardManagerImpl::_pasteImage(SPDocument *doc)
@@ -957,7 +852,7 @@ bool ClipboardManagerImpl::_pasteText(SPDesktop *desktop)
}
// try to parse the text as a color and, if successful, apply it as the current style
- SPCSSAttr *css = _parseColor(_clipboard->wait_for_text());
+ SPCSSAttr *css = sp_repr_css_attr_parse_color_to_fill(_clipboard->wait_for_text());
if (css) {
sp_desktop_set_style(desktop, css);
return true;
@@ -968,76 +863,6 @@ bool ClipboardManagerImpl::_pasteText(SPDesktop *desktop)
/**
- * Attempt to parse the passed string as a hexadecimal RGB or RGBA color.
- * @param text The Glib::ustring to parse
- * @return New CSS style representation if the parsing was successful, NULL otherwise
- */
-SPCSSAttr *ClipboardManagerImpl::_parseColor(const Glib::ustring &text)
-{
-// TODO reuse existing code instead of replicating here.
- Glib::ustring::size_type len = text.bytes();
- char *str = const_cast<char *>(text.data());
- bool attempt_alpha = false;
- if ( !str || ( *str == '\0' ) ) {
- return NULL; // this is OK due to boolean short-circuit
- }
-
- // those conditionals guard against parsing e.g. the string "fab" as "fab000"
- // (incomplete color) and "45fab71" as "45fab710" (incomplete alpha)
- if ( *str == '#' ) {
- if ( len < 7 ) {
- return NULL;
- }
- if ( len >= 9 ) {
- attempt_alpha = true;
- }
- } else {
- if ( len < 6 ) {
- return NULL;
- }
- if ( len >= 8 ) {
- attempt_alpha = true;
- }
- }
-
- unsigned int color = 0, alpha = 0xff;
-
- // skip a leading #, if present
- if ( *str == '#' ) {
- ++str;
- }
-
- // try to parse first 6 digits
- int res = sscanf(str, "%6x", &color);
- if ( res && ( res != EOF ) ) {
- if (attempt_alpha) {// try to parse alpha if there's enough characters
- sscanf(str + 6, "%2x", &alpha);
- if ( !res || res == EOF ) {
- alpha = 0xff;
- }
- }
-
- SPCSSAttr *color_css = sp_repr_css_attr_new();
-
- // print and set properties
- gchar color_str[16];
- g_snprintf(color_str, 16, "#%06x", color);
- sp_repr_css_set_property(color_css, "fill", color_str);
-
- float opacity = static_cast<float>(alpha)/static_cast<float>(0xff);
- if (opacity > 1.0) {
- opacity = 1.0; // safeguard
- }
- Inkscape::CSSOStringStream opcss;
- opcss << opacity;
- sp_repr_css_set_property(color_css, "fill-opacity", opcss.str().data());
- return color_css;
- }
- return NULL;
-}
-
-
-/**
* Applies a pasted path effect to a given item.
*/
void ClipboardManagerImpl::_applyPathEffect(SPItem *item, gchar const *effectstack)
diff --git a/src/xml/repr-css.cpp b/src/xml/repr-css.cpp
index 4fb1223de..19f3f1d6c 100644
--- a/src/xml/repr-css.cpp
+++ b/src/xml/repr-css.cpp
@@ -89,6 +89,77 @@ SPCSSAttr *sp_repr_css_attr(Node *repr, gchar const *attr)
return css;
}
+
+/**
+ * Attempt to parse the passed string as a hexadecimal RGB or RGBA color.
+ * @param text The Glib::ustring to parse
+ * @return New CSS style representation if the parsing was successful, NULL otherwise
+ */
+SPCSSAttr *sp_repr_css_attr_parse_color_to_fill(const Glib::ustring &text)
+{
+// TODO reuse existing code instead of replicating here.
+ Glib::ustring::size_type len = text.bytes();
+ char *str = const_cast<char *>(text.data());
+ bool attempt_alpha = false;
+ if ( !str || ( *str == '\0' ) ) {
+ return NULL; // this is OK due to boolean short-circuit
+ }
+
+ // those conditionals guard against parsing e.g. the string "fab" as "fab000"
+ // (incomplete color) and "45fab71" as "45fab710" (incomplete alpha)
+ if ( *str == '#' ) {
+ if ( len < 7 ) {
+ return NULL;
+ }
+ if ( len >= 9 ) {
+ attempt_alpha = true;
+ }
+ } else {
+ if ( len < 6 ) {
+ return NULL;
+ }
+ if ( len >= 8 ) {
+ attempt_alpha = true;
+ }
+ }
+
+ unsigned int color = 0, alpha = 0xff;
+
+ // skip a leading #, if present
+ if ( *str == '#' ) {
+ ++str;
+ }
+
+ // try to parse first 6 digits
+ int res = sscanf(str, "%6x", &color);
+ if ( res && ( res != EOF ) ) {
+ if (attempt_alpha) {// try to parse alpha if there's enough characters
+ sscanf(str + 6, "%2x", &alpha);
+ if ( !res || res == EOF ) {
+ alpha = 0xff;
+ }
+ }
+
+ SPCSSAttr *color_css = sp_repr_css_attr_new();
+
+ // print and set properties
+ gchar color_str[16];
+ g_snprintf(color_str, 16, "#%06x", color);
+ sp_repr_css_set_property(color_css, "fill", color_str);
+
+ float opacity = static_cast<float>(alpha)/static_cast<float>(0xff);
+ if (opacity > 1.0) {
+ opacity = 1.0; // safeguard
+ }
+ Inkscape::CSSOStringStream opcss;
+ opcss << opacity;
+ sp_repr_css_set_property(color_css, "fill-opacity", opcss.str().data());
+ return color_css;
+ }
+ return NULL;
+}
+
+
/**
* Adds an attribute to an existing SPCSAttr with the cascaded value including all parents.
*/
diff --git a/src/xml/repr.h b/src/xml/repr.h
index 3eee45385..86a798e3e 100644
--- a/src/xml/repr.h
+++ b/src/xml/repr.h
@@ -70,6 +70,7 @@ bool sp_repr_save_rebased_file(Inkscape::XML::Document *doc, gchar const *filena
SPCSSAttr *sp_repr_css_attr_new(void);
void sp_repr_css_attr_unref(SPCSSAttr *css);
SPCSSAttr *sp_repr_css_attr(Inkscape::XML::Node *repr, gchar const *attr);
+SPCSSAttr *sp_repr_css_attr_parse_color_to_fill(const Glib::ustring &text);
SPCSSAttr *sp_repr_css_attr_inherited(Inkscape::XML::Node *repr, gchar const *attr);
gchar const *sp_repr_css_property(SPCSSAttr *css, gchar const *name, gchar const *defval);