Code

Split SPCanvasItem and SPCanvasGroup to individual .h files. Removed forward header.
[inkscape.git] / src / interface.cpp
index 9c187001986ecb616ebaa5f614cd0797777706a5..551e2bf9147dc8a6acaeb36cfbe33769c831142d 100644 (file)
@@ -1,5 +1,3 @@
-#define __SP_INTERFACE_C__
-
 /** @file
  * @brief Main UI stuff
  */
@@ -7,7 +5,10 @@
  *   Lauris Kaplinski <lauris@kaplinski.com>
  *   Frank Felfe <innerspace@iname.com>
  *   bulia byak <buliabyak@users.sf.net>
+ *   Jon A. Cruz <jon@joncruz.org>
+ *   Abhishek Sharma
  *
+ * Copyright (C) 2010 authors
  * Copyright (C) 1999-2005 authors
  * Copyright (C) 2001-2002 Ximian, Inc.
  * Copyright (C) 2004 David Turner
@@ -23,7 +24,9 @@
 #include <glib.h>
 
 #include "inkscape-private.h"
+#include "extension/db.h"
 #include "extension/effect.h"
+#include "extension/input.h"
 #include "widgets/icon.h"
 #include "preferences.h"
 #include "path-prefix.h"
@@ -51,6 +54,7 @@
 #include "io/sys.h"
 #include "dialogs/dialog-events.h"
 #include "message-context.h"
+#include "ui/uxmanager.h"
 
 // Added for color drag-n-drop
 #if ENABLE_LCMS
@@ -70,6 +74,8 @@
 #include "ige-mac-menu.h"
 #endif
 
+using Inkscape::DocumentUndo;
+
 /* Drag and Drop */
 typedef enum {
     URI_LIST,
@@ -131,6 +137,8 @@ static void sp_ui_menu_item_set_name(SPAction *action,
                                      void *data);
 static void sp_recent_open(GtkRecentChooser *, gpointer);
 
+static void injectRenamedIcons();
+
 SPActionEventVector menu_item_event_vector = {
     {NULL},
     NULL,
@@ -265,7 +273,9 @@ sp_create_window(SPViewWidget *vw, gboolean editable)
     win->show();
 
     // needed because the first ACTIVATE_DESKTOP was sent when there was no window yet
-    inkscape_reactivate_desktop(SP_DESKTOP_WIDGET(vw)->desktop);
+    if ( SP_IS_DESKTOP_WIDGET(vw) ) {
+        inkscape_reactivate_desktop(SP_DESKTOP_WIDGET(vw)->desktop);
+    }
 }
 
 void
@@ -287,20 +297,16 @@ sp_ui_new_view()
 
 /* TODO: not yet working */
 /* To be re-enabled (by adding to menu) once it works. */
-void
-sp_ui_new_view_preview()
+void sp_ui_new_view_preview()
 {
-    SPDocument *document;
-    SPViewWidget *dtw;
-
-    document = SP_ACTIVE_DOCUMENT;
-    if (!document) return;
-
-    dtw = (SPViewWidget *) sp_svg_view_widget_new(document);
-    g_return_if_fail(dtw != NULL);
-    sp_svg_view_widget_set_resize(SP_SVG_VIEW_WIDGET(dtw), TRUE, 400.0, 400.0);
+    SPDocument *document = SP_ACTIVE_DOCUMENT;
+    if ( document ) {
+        SPViewWidget *dtw = reinterpret_cast<SPViewWidget *>(sp_svg_view_widget_new(document));
+        g_return_if_fail(dtw != NULL);
+        SP_SVG_VIEW_WIDGET(dtw)->setResize(true, 400.0, 400.0);
 
-    sp_create_window(dtw, FALSE);
+        sp_create_window(dtw, FALSE);
+    }
 }
 
 /**
@@ -405,6 +411,11 @@ sp_ui_menu_deselect(gpointer object)
 void
 sp_ui_menuitem_add_icon( GtkWidget *item, gchar *icon_name )
 {
+    static bool iconsInjected = false;
+    if ( !iconsInjected ) {
+        iconsInjected = true;
+        injectRenamedIcons();
+    }
     GtkWidget *icon;
 
     icon = sp_icon_new( Inkscape::ICON_SIZE_MENU, icon_name );
@@ -453,85 +464,12 @@ sp_ui_menu_append_item( GtkMenu *menu, gchar const *stock,
 
 } // end of sp_ui_menu_append_item()
 
-/**
-\brief  a wrapper around gdk_keyval_name producing (when possible) characters, not names
- */
-static gchar const *
-sp_key_name(guint keyval)
-{
-    /* TODO: Compare with the definition of gtk_accel_label_refetch in gtk/gtkaccellabel.c (or
-       simply use GtkAccelLabel as the TODO comment in sp_ui_shortcut_string suggests). */
-    gchar const *n = gdk_keyval_name(gdk_keyval_to_upper(keyval));
-
-    if      (!strcmp(n, "asciicircum"))  return "^";
-    else if (!strcmp(n, "parenleft"  ))  return "(";
-    else if (!strcmp(n, "parenright" ))  return ")";
-    else if (!strcmp(n, "plus"       ))  return "+";
-    else if (!strcmp(n, "minus"      ))  return "-";
-    else if (!strcmp(n, "asterisk"   ))  return "*";
-    else if (!strcmp(n, "KP_Multiply"))  return "*";
-    else if (!strcmp(n, "Delete"     ))  return "Del";
-    else if (!strcmp(n, "Page_Up"    ))  return "PgUp";
-    else if (!strcmp(n, "Page_Down"  ))  return "PgDn";
-    else if (!strcmp(n, "grave"      ))  return "`";
-    else if (!strcmp(n, "numbersign" ))  return "#";
-    else if (!strcmp(n, "bar"        ))  return "|";
-    else if (!strcmp(n, "slash"      ))  return "/";
-    else if (!strcmp(n, "exclam"     ))  return "!";
-    else if (!strcmp(n, "percent"    ))  return "%";
-    else return n;
-}
-
-
-/**
- * \param shortcut A GDK keyval OR'd with SP_SHORTCUT_blah_MASK values.
- * \param c Points to a buffer at least 256 bytes long.
- */
-void
-sp_ui_shortcut_string(unsigned const shortcut, gchar *const c)
-{
-    /* TODO: This function shouldn't exist.  Our callers should use GtkAccelLabel instead of
-     * a generic GtkLabel containing this string, and should call gtk_widget_add_accelerator.
-     * Will probably need to change sp_shortcut_invoke callers.
-     *
-     * The existing gtk_label_new_with_mnemonic call can be replaced with
-     * g_object_new(GTK_TYPE_ACCEL_LABEL, NULL) followed by
-     * gtk_label_set_text_with_mnemonic(lbl, str).
-     */
-    static GtkAccelLabelClass const &accel_lbl_cls
-        = *(GtkAccelLabelClass const *) g_type_class_peek_static(GTK_TYPE_ACCEL_LABEL);
-
-    struct { unsigned test; char const *name; } const modifier_tbl[] = {
-        { SP_SHORTCUT_SHIFT_MASK,   accel_lbl_cls.mod_name_shift   },
-        { SP_SHORTCUT_CONTROL_MASK, accel_lbl_cls.mod_name_control },
-        { SP_SHORTCUT_ALT_MASK,     accel_lbl_cls.mod_name_alt     }
-    };
-
-    gchar *p = c;
-    gchar *end = p + 256;
-
-    for (unsigned i = 0; i < G_N_ELEMENTS(modifier_tbl); ++i) {
-        if ((shortcut & modifier_tbl[i].test)
-            && (p < end))
-        {
-            p += g_snprintf(p, end - p, "%s%s",
-                            modifier_tbl[i].name,
-                            accel_lbl_cls.mod_separator);
-        }
-    }
-    if (p < end) {
-        p += g_snprintf(p, end - p, "%s", sp_key_name(shortcut & 0xffffff));
-    }
-    end[-1] = '\0';  // snprintf doesn't guarantee to nul-terminate the string.
-}
-
 void
 sp_ui_dialog_title_string(Inkscape::Verb *verb, gchar *c)
 {
     SPAction     *action;
     unsigned int shortcut;
     gchar        *s;
-    gchar        key[256];
     gchar        *atitle;
 
     action = verb->get_action(NULL);
@@ -545,11 +483,12 @@ sp_ui_dialog_title_string(Inkscape::Verb *verb, gchar *c)
     g_free(atitle);
 
     shortcut = sp_shortcut_get_primary(verb);
-    if (shortcut) {
+    if (shortcut!=GDK_VoidSymbol) {
+        gchar* key = sp_shortcut_get_label(shortcut);
         s = g_stpcpy(s, " (");
-        sp_ui_shortcut_string(shortcut, key);
         s = g_stpcpy(s, key);
         s = g_stpcpy(s, ")");
+        g_free(key);
     }
 }
 
@@ -579,9 +518,8 @@ sp_ui_menu_append_item_from_verb(GtkMenu *menu, Inkscape::Verb *verb, Inkscape::
         if (!action) return NULL;
 
         shortcut = sp_shortcut_get_primary(verb);
-        if (shortcut) {
-            gchar c[256];
-            sp_ui_shortcut_string(shortcut, c);
+        if (shortcut!=GDK_VoidSymbol) {
+            gchar* c = sp_shortcut_get_label(shortcut);
             GtkWidget *const hb = gtk_hbox_new(FALSE, 16);
             GtkWidget *const name_lbl = gtk_label_new("");
             gtk_label_set_markup_with_mnemonic(GTK_LABEL(name_lbl), action->name);
@@ -597,6 +535,7 @@ sp_ui_menu_append_item_from_verb(GtkMenu *menu, Inkscape::Verb *verb, Inkscape::
                 item = gtk_image_menu_item_new();
             }
             gtk_container_add((GtkContainer *) item, hb);
+            g_free(c);
         } else {
             if (radio) {
                 item = gtk_radio_menu_item_new (group);
@@ -632,20 +571,28 @@ sp_ui_menu_append_item_from_verb(GtkMenu *menu, Inkscape::Verb *verb, Inkscape::
 } // end of sp_ui_menu_append_item_from_verb
 
 
-static void
-checkitem_toggled(GtkCheckMenuItem *menuitem, gpointer user_data)
+static Glib::ustring getLayoutPrefPath( Inkscape::UI::View::View *view )
 {
-    gchar const *pref = (gchar const *) user_data;
-    Inkscape::UI::View::View *view = (Inkscape::UI::View::View *) g_object_get_data(G_OBJECT(menuitem), "view");
+    Glib::ustring prefPath;
 
-    Glib::ustring pref_path;
     if (reinterpret_cast<SPDesktop*>(view)->is_focusMode()) {
-        pref_path = "/focus/";
+        prefPath = "/focus/";
     } else if (reinterpret_cast<SPDesktop*>(view)->is_fullscreen()) {
-        pref_path = "/fullscreen/";
+        prefPath = "/fullscreen/";
     } else {
-        pref_path = "/window/";
+        prefPath = "/window/";
     }
+
+    return prefPath;
+}
+
+static void
+checkitem_toggled(GtkCheckMenuItem *menuitem, gpointer user_data)
+{
+    gchar const *pref = (gchar const *) user_data;
+    Inkscape::UI::View::View *view = (Inkscape::UI::View::View *) g_object_get_data(G_OBJECT(menuitem), "view");
+
+    Glib::ustring pref_path = getLayoutPrefPath( view );
     pref_path += pref;
     pref_path += "/state";
 
@@ -664,16 +611,12 @@ checkitem_update(GtkWidget *widget, GdkEventExpose */*event*/, gpointer user_dat
     gchar const *pref = (gchar const *) user_data;
     Inkscape::UI::View::View *view = (Inkscape::UI::View::View *) g_object_get_data(G_OBJECT(menuitem), "view");
 
-    Glib::ustring pref_path;
-    if ((static_cast<SPDesktop*>(view))->is_fullscreen()) {
-        pref_path = "/fullscreen/";
-    } else {
-        pref_path = "/window/";
-    }
+    Glib::ustring pref_path = getLayoutPrefPath( view );
     pref_path += pref;
+    pref_path += "/state";
 
     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-    bool ison = prefs->getBool(pref_path + "/state", true);
+    bool ison = prefs->getBool(pref_path, true);
 
     g_signal_handlers_block_by_func(G_OBJECT(menuitem), (gpointer)(GCallback)checkitem_toggled, user_data);
     gtk_check_menu_item_set_active(menuitem, ison);
@@ -682,6 +625,20 @@ checkitem_update(GtkWidget *widget, GdkEventExpose */*event*/, gpointer user_dat
     return FALSE;
 }
 
+static void taskToggled(GtkCheckMenuItem *menuitem, gpointer userData)
+{
+    if ( gtk_check_menu_item_get_active(menuitem) ) {
+        gint taskNum = GPOINTER_TO_INT(userData);
+        taskNum = (taskNum < 0) ? 0 : (taskNum > 2) ? 2 : taskNum;
+
+        Inkscape::UI::View::View *view = (Inkscape::UI::View::View *) g_object_get_data(G_OBJECT(menuitem), "view");
+
+        // note: this will change once more options are in the task set support:
+        Inkscape::UI::UXManager::getInstance()->setTask( dynamic_cast<SPDesktop*>(view), taskNum );
+    }
+}
+
+
 /**
  *  \brief Callback function to update the status of the radio buttons in the View -> Display mode menu (Normal, No Filters, Outline)
  */
@@ -729,19 +686,12 @@ sp_ui_menu_append_check_item_from_verb(GtkMenu *menu, Inkscape::UI::View::View *
                                        gboolean (*callback_update)(GtkWidget *widget, GdkEventExpose *event, gpointer user_data),
                                        Inkscape::Verb *verb)
 {
-    GtkWidget *item;
+    unsigned int shortcut = (verb) ? sp_shortcut_get_primary(verb) : 0;
+    SPAction *action = (verb) ? verb->get_action(view) : 0;
+    GtkWidget *item = gtk_check_menu_item_new();
 
-    unsigned int shortcut = 0;
-    SPAction *action = NULL;
-
-    if (verb) {
-        shortcut = sp_shortcut_get_primary(verb);
-        action = verb->get_action(view);
-    }
-
-    if (verb && shortcut) {
-        gchar c[256];
-        sp_ui_shortcut_string(shortcut, c);
+    if (verb && shortcut!=GDK_VoidSymbol) {
+        gchar* c = sp_shortcut_get_label(shortcut);
 
         GtkWidget *hb = gtk_hbox_new(FALSE, 16);
 
@@ -759,12 +709,11 @@ sp_ui_menu_append_check_item_from_verb(GtkMenu *menu, Inkscape::UI::View::View *
 
         gtk_widget_show_all(hb);
 
-        item = gtk_check_menu_item_new();
         gtk_container_add((GtkContainer *) item, hb);
+        g_free(c);
     } else {
         GtkWidget *l = gtk_label_new_with_mnemonic(action ? action->name : label);
         gtk_misc_set_alignment((GtkMisc *) l, 0.0, 0.5);
-        item = gtk_check_menu_item_new();
         gtk_container_add((GtkContainer *) item, l);
     }
 #if 0
@@ -885,6 +834,39 @@ sp_ui_checkboxes_menus(GtkMenu *m, Inkscape::UI::View::View *view)
                                            checkitem_toggled, checkitem_update, 0);
 }
 
+
+void addTaskMenuItems(GtkMenu *menu, Inkscape::UI::View::View *view)
+{
+    gchar const* data[] = {
+        _("Default"), _("Default interface setup"),
+        _("Custom"), _("Set the custom task"),
+        _("Wide"), _("Setup for widescreen work"),
+        0, 0
+    };
+
+    GSList *group = 0;
+    int count = 0;
+    gint active = Inkscape::UI::UXManager::getInstance()->getDefaultTask( dynamic_cast<SPDesktop*>(view) );
+    for (gchar const **strs = data; strs[0]; strs += 2, count++)
+    {
+        GtkWidget *item = gtk_radio_menu_item_new_with_label( group, strs[0] );
+        group = gtk_radio_menu_item_get_group( GTK_RADIO_MENU_ITEM(item) );
+        if ( count == active )
+        {
+            gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(item), TRUE );
+        }
+
+        g_object_set_data( G_OBJECT(item), "view", view );
+        g_signal_connect( G_OBJECT(item), "toggled", reinterpret_cast<GCallback>(taskToggled), GINT_TO_POINTER(count) );
+        g_signal_connect( G_OBJECT(item), "select", G_CALLBACK(sp_ui_menu_select), const_cast<gchar*>(strs[1]) );
+        g_signal_connect( G_OBJECT(item), "deselect", G_CALLBACK(sp_ui_menu_deselect), 0 );
+
+        gtk_widget_show( item );
+        gtk_menu_shell_append( GTK_MENU_SHELL(menu), item );
+    }
+}
+
+
 /** @brief Observer that updates the recent list's max document count */
 class MaxRecentObserver : public Inkscape::Preferences::Observer {
 public:
@@ -1010,6 +992,10 @@ sp_ui_build_dyn_menus(Inkscape::XML::Node *menus, GtkWidget *menu, Inkscape::UI:
             sp_ui_checkboxes_menus(GTK_MENU(menu), view);
             continue;
         }
+        if (!strcmp(menu_pntr->name(), "task-checkboxes")) {
+            addTaskMenuItems(GTK_MENU(menu), view);
+            continue;
+        }
     }
 }
 
@@ -1142,7 +1128,7 @@ sp_ui_drag_data_received(GtkWidget *widget,
             gtk_widget_translate_coordinates( widget, &(desktop->canvas->widget), x, y, &destX, &destY );
             Geom::Point where( sp_canvas_window_to_world( desktop->canvas, Geom::Point( destX, destY ) ) );
 
-            SPItem *item = desktop->item_at_point( where, true );
+            SPItem *item = desktop->getItemAtPoint( where, true );
             if ( item )
             {
                 bool fillnotstroke = (drag_context->action != GDK_ACTION_MOVE);
@@ -1181,7 +1167,7 @@ sp_ui_drag_data_received(GtkWidget *widget,
                             g_free(str);
                             str = 0;
 
-                            sp_object_setAttribute( SP_OBJECT(item),
+                            SP_OBJECT(item)->setAttribute( 
                                                     fillnotstroke ? "inkscape:x-fill-tag":"inkscape:x-stroke-tag",
                                                     palName.c_str(),
                                                     false );
@@ -1199,7 +1185,7 @@ sp_ui_drag_data_received(GtkWidget *widget,
                     sp_desktop_apply_css_recursive( item, css, true );
                     item->updateRepr();
 
-                    sp_document_done( doc , SP_VERB_NONE,
+                    SPDocumentUndo::done( doc , SP_VERB_NONE,
                                       _("Drop color"));
 
                     if ( srgbProf ) {
@@ -1233,13 +1219,13 @@ sp_ui_drag_data_received(GtkWidget *widget,
                                         //0x0ff & (data->data[3] >> 8),
                                         ));
 
-                SPItem *item = desktop->item_at_point( where, true );
+                SPItem *item = desktop->getItemAtPoint( where, true );
 
                 bool consumed = false;
                 if (desktop->event_context && desktop->event_context->get_drag()) {
                     consumed = desktop->event_context->get_drag()->dropColor(item, colorspec, button_dt);
                     if (consumed) {
-                        sp_document_done( doc , SP_VERB_NONE, _("Drop color on gradient"));
+                        DocumentUndo::done( doc , SP_VERB_NONE, _("Drop color on gradient") );
                         desktop->event_context->get_drag()->updateDraggers();
                     }
                 }
@@ -1247,7 +1233,7 @@ sp_ui_drag_data_received(GtkWidget *widget,
                 //if (!consumed && tools_active(desktop, TOOLS_TEXT)) {
                 //    consumed = sp_text_context_drop_color(c, button_doc);
                 //    if (consumed) {
-                //        sp_document_done( doc , SP_VERB_NONE, _("Drop color on gradient stop"));
+                //        SPDocumentUndo::done( doc , SP_VERB_NONE, _("Drop color on gradient stop"));
                 //    }
                 //}
 
@@ -1268,7 +1254,7 @@ sp_ui_drag_data_received(GtkWidget *widget,
                                 ( !SP_OBJECT_STYLE(item)->stroke.isNone() ?
                                   desktop->current_zoom() *
                                   SP_OBJECT_STYLE (item)->stroke_width.computed *
-                                  to_2geom(sp_item_i2d_affine(item)).descrim() * 0.5
+                                  to_2geom(item->i2d_affine()).descrim() * 0.5
                                   : 0.0)
                                 + prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
 
@@ -1285,8 +1271,8 @@ sp_ui_drag_data_received(GtkWidget *widget,
                     sp_desktop_apply_css_recursive( item, css, true );
                     item->updateRepr();
 
-                    sp_document_done( doc , SP_VERB_NONE,
-                                      _("Drop color"));
+                    DocumentUndo::done( doc , SP_VERB_NONE,
+                                        _("Drop color") );
                 }
             }
         }
@@ -1313,11 +1299,11 @@ sp_ui_drag_data_received(GtkWidget *widget,
                         unsigned int b = color.getB();
 
                         SPGradient* matches = 0;
-                        const GSList *gradients = sp_document_get_resource_list(doc, "gradient");
+                        const GSList *gradients = doc->getResourceList("gradient");
                         for (const GSList *item = gradients; item; item = item->next) {
                             SPGradient* grad = SP_GRADIENT(item->data);
                             if ( color.descr == grad->getId() ) {
-                                if ( grad->has_stops ) {
+                                if ( grad->hasStops() ) {
                                     matches = grad;
                                     break;
                                 }
@@ -1343,13 +1329,13 @@ sp_ui_drag_data_received(GtkWidget *widget,
                 Geom::Point const button_dt(desktop->w2d(where));
                 Geom::Point const button_doc(desktop->dt2doc(button_dt));
 
-                SPItem *item = desktop->item_at_point( where, true );
+                SPItem *item = desktop->getItemAtPoint( where, true );
 
                 bool consumed = false;
                 if (desktop->event_context && desktop->event_context->get_drag()) {
                     consumed = desktop->event_context->get_drag()->dropColor(item, colorspec.c_str(), button_dt);
                     if (consumed) {
-                        sp_document_done( doc , SP_VERB_NONE, _("Drop color on gradient"));
+                        DocumentUndo::done( doc , SP_VERB_NONE, _("Drop color on gradient") );
                         desktop->event_context->get_drag()->updateDraggers();
                     }
                 }
@@ -1371,7 +1357,7 @@ sp_ui_drag_data_received(GtkWidget *widget,
                                 ( !SP_OBJECT_STYLE(item)->stroke.isNone() ?
                                   desktop->current_zoom() *
                                   SP_OBJECT_STYLE (item)->stroke_width.computed *
-                                  to_2geom(sp_item_i2d_affine(item)).descrim() * 0.5
+                                  to_2geom(item->i2d_affine()).descrim() * 0.5
                                   : 0.0)
                                 + prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
 
@@ -1388,8 +1374,8 @@ sp_ui_drag_data_received(GtkWidget *widget,
                     sp_desktop_apply_css_recursive( item, css, true );
                     item->updateRepr();
 
-                    sp_document_done( doc , SP_VERB_NONE,
-                                      _("Drop color"));
+                    DocumentUndo::done( doc , SP_VERB_NONE,
+                                        _("Drop color") );
                 }
             }
         }
@@ -1412,7 +1398,7 @@ sp_ui_drag_data_received(GtkWidget *widget,
             Inkscape::XML::Node *newgroup = rnewdoc->createElement("svg:g");
             newgroup->setAttribute("style", style);
 
-            Inkscape::XML::Document * xml_doc =  sp_document_repr_doc(doc);
+            Inkscape::XML::Document * xml_doc =  doc->getReprDoc();
             for (Inkscape::XML::Node *child = repr->firstChild(); child != NULL; child = child->next()) {
                 Inkscape::XML::Node *newchild = child->duplicate(xml_doc);
                 newgroup->appendChild(newchild);
@@ -1431,7 +1417,7 @@ sp_ui_drag_data_received(GtkWidget *widget,
 
             // move to mouse pointer
             {
-                sp_document_ensure_up_to_date(sp_desktop_document(desktop));
+                sp_desktop_document(desktop)->ensureUpToDate();
                 Geom::OptRect sel_bbox = selection->bounds();
                 if (sel_bbox) {
                     Geom::Point m( desktop->point() - sel_bbox->midpoint() );
@@ -1440,8 +1426,8 @@ sp_ui_drag_data_received(GtkWidget *widget,
             }
 
             Inkscape::GC::release(newgroup);
-            sp_document_done(doc, SP_VERB_NONE,
-                             _("Drop SVG"));
+            DocumentUndo::done( doc, SP_VERB_NONE,
+                             _("Drop SVG") );
             break;
         }
 
@@ -1454,50 +1440,28 @@ sp_ui_drag_data_received(GtkWidget *widget,
         case PNG_DATA:
         case JPEG_DATA:
         case IMAGE_DATA: {
-            Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
-            Inkscape::XML::Node *newImage = xml_doc->createElement("svg:image");
-            gchar *atom_name = gdk_atom_name(data->type);
-
-            // this formula taken from Glib docs
-            guint needed_size = data->length * 4 / 3 + data->length * 4 / (3 * 72) + 7;
-            needed_size += 5 + 8 + strlen(atom_name); // 5 bytes for data:, 8 for ;base64,
-
-            gchar *buffer = (gchar *) g_malloc(needed_size), *buf_work = buffer;
-            buf_work += g_sprintf(buffer, "data:%s;base64,", atom_name);
-
-            gint state = 0, save = 0;
-            g_base64_encode_step(data->data, data->length, TRUE, buf_work, &state, &save);
-            g_base64_encode_close(TRUE, buf_work, &state, &save);
-
-            newImage->setAttribute("xlink:href", buffer);
-            g_free(buffer);
-
-            GError *error = NULL;
-            GdkPixbufLoader *loader = gdk_pixbuf_loader_new_with_mime_type( gdk_atom_name(data->type), &error );
-            if ( loader ) {
-                error = NULL;
-                if ( gdk_pixbuf_loader_write( loader, data->data, data->length, &error) ) {
-                    GdkPixbuf *pbuf = gdk_pixbuf_loader_get_pixbuf(loader);
-                    if ( pbuf ) {
-                        char tmp[1024];
-                        int width = gdk_pixbuf_get_width(pbuf);
-                        int height = gdk_pixbuf_get_height(pbuf);
-                        snprintf( tmp, sizeof(tmp), "%d", width );
-                        newImage->setAttribute("width", tmp);
-
-                        snprintf( tmp, sizeof(tmp), "%d", height );
-                        newImage->setAttribute("height", tmp);
-                    }
-                }
-            }
-            g_free(atom_name);
-
-            // Add it to the current layer
-            desktop->currentLayer()->appendChildRepr(newImage);
+            const char *mime = (info == JPEG_DATA ? "image/jpeg" : "image/png");
 
-            Inkscape::GC::release(newImage);
-            sp_document_done( doc , SP_VERB_NONE,
-                              _("Drop bitmap image"));
+            Inkscape::Extension::DB::InputList o;
+            Inkscape::Extension::db.get_input_list(o);
+            Inkscape::Extension::DB::InputList::const_iterator i = o.begin();
+            while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
+                ++i;
+            }
+            Inkscape::Extension::Extension *ext = *i;
+            bool save = (strcmp(ext->get_param_optiongroup("link"), "embed") == 0);
+            ext->set_param_optiongroup("link", "embed");
+            ext->set_gui(false);
+
+            gchar *filename = g_build_filename( g_get_tmp_dir(), "inkscape-dnd-import", NULL );
+            g_file_set_contents(filename, reinterpret_cast<gchar const *>(data->data), data->length, NULL);
+            file_import(doc, filename, ext);
+            g_free(filename);
+
+            ext->set_param_optiongroup("link", save ? "embed" : "link");
+            ext->set_gui(true);
+            DocumentUndo::done( doc , SP_VERB_NONE,
+                                _("Drop bitmap image") );
             break;
         }
     }
@@ -1639,6 +1603,32 @@ sp_ui_menu_item_set_name(SPAction */*action*/, Glib::ustring name, void *data)
     //a menu item in yet another way...
 }
 
+void injectRenamedIcons()
+{
+    Glib::RefPtr<Gtk::IconTheme> iconTheme = Gtk::IconTheme::get_default();
+
+    std::vector< std::pair<Glib::ustring, Glib::ustring> > renamed;
+    renamed.push_back(std::make_pair("gtk-file", "document-x-generic"));
+    renamed.push_back(std::make_pair("gtk-directory", "folder"));
+
+    for ( std::vector< std::pair<Glib::ustring, Glib::ustring> >::iterator it = renamed.begin(); it < renamed.end(); ++it ) {
+        bool hasIcon = iconTheme->has_icon(it->first);
+        bool hasSecondIcon = iconTheme->has_icon(it->second);
+
+        if ( !hasIcon && hasSecondIcon ) {
+            Glib::ArrayHandle<int> sizes = iconTheme->get_icon_sizes(it->second);
+            for ( Glib::ArrayHandle<int>::iterator it2 = sizes.begin(); it2 < sizes.end(); ++it2 ) {
+                Glib::RefPtr<Gdk::Pixbuf> pb = iconTheme->load_icon( it->second, *it2 );
+                if ( pb ) {
+                    // install a private copy of the pixbuf to avoid pinning a theme
+                    Glib::RefPtr<Gdk::Pixbuf> pbCopy = pb->copy();
+                    Gtk::IconTheme::add_builtin_icon( it->first, *it2, pbCopy );
+                }
+            }
+        }
+    }
+}
+
 
 /*
   Local Variables:
@@ -1649,4 +1639,4 @@ sp_ui_menu_item_set_name(SPAction */*action*/, Glib::ustring name, void *data)
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :