/* * Unser-interface related object extension * * Authors: * Lauris Kaplinski * Jon A. Cruz * Abhishek Sharma * * This code is in public domain */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "ui/dialog/dialog-manager.h" #include "context-menu.h" #include "../xml/repr.h" #include "desktop.h" #include "document.h" #include "document-undo.h" #include "helper/action.h" //sp_action_perform #include "inkscape.h" #include "message-stack.h" #include "preferences.h" #include "verbs.h" using Inkscape::DocumentUndo; static void sp_object_type_menu(GType type, SPObject *object, SPDesktop *desktop, GtkMenu *menu); /* Append object-specific part to context menu */ void sp_object_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu) { GObjectClass *klass; klass = G_OBJECT_GET_CLASS(object); while (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_OBJECT)) { GType type; type = G_TYPE_FROM_CLASS(klass); sp_object_type_menu(type, object, desktop, menu); klass = (GObjectClass*)g_type_class_peek_parent(klass); } } /* Implementation */ #include #include #include "selection.h" #include "selection-chemistry.h" #include "sp-anchor.h" #include "sp-clippath.h" #include "sp-image.h" #include "sp-mask.h" #include "sp-path.h" #include "sp-text.h" #include "desktop-handles.h" #include "ui/dialog/object-attributes.h" #include "ui/dialog/object-properties.h" #include "ui/dialog/spellcheck.h" static void sp_item_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu); static void sp_group_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu); static void sp_anchor_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu); static void sp_image_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu); static void sp_shape_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu); static void sp_text_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu); static void sp_object_type_menu(GType type, SPObject *object, SPDesktop *desktop, GtkMenu *menu) { static GHashTable *t2m = NULL; void (* handler)(SPObject *object, SPDesktop *desktop, GtkMenu *menu); if (!t2m) { t2m = g_hash_table_new(NULL, NULL); g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_ITEM), (void*)sp_item_menu); g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_GROUP), (void*)sp_group_menu); g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_ANCHOR), (void*)sp_anchor_menu); g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_IMAGE), (void*)sp_image_menu); g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_SHAPE), (void*)sp_shape_menu); g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_TEXT), (void*)sp_text_menu); } handler = (void (*)(SPObject*, SPDesktop*, GtkMenu*))g_hash_table_lookup(t2m, GUINT_TO_POINTER(type)); if (handler) handler(object, desktop, menu); } /* SPItem */ static void sp_item_properties(GtkMenuItem *menuitem, SPItem *item); static void sp_item_select_this(GtkMenuItem *menuitem, SPItem *item); static void sp_item_create_link(GtkMenuItem *menuitem, SPItem *item); static void sp_set_mask(GtkMenuItem *menuitem, SPItem *item); static void sp_release_mask(GtkMenuItem *menuitem, SPItem *item); static void sp_set_clip(GtkMenuItem *menuitem, SPItem *item); static void sp_release_clip(GtkMenuItem *menuitem, SPItem *item); /* Generate context menu item section */ static void sp_item_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m) { SPItem *item; GtkWidget *w; item = (SPItem *) object; /* Item dialog */ w = gtk_menu_item_new_with_mnemonic(_("_Object Properties...")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_item_properties), item); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); /* Separator */ w = gtk_menu_item_new(); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); /* Select item */ w = gtk_menu_item_new_with_mnemonic(_("_Select This")); if (sp_desktop_selection(desktop)->includes(item)) { gtk_widget_set_sensitive(w, FALSE); } else { g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_item_select_this), item); } gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); /* Create link */ w = gtk_menu_item_new_with_mnemonic(_("_Create Link")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_item_create_link), item); gtk_widget_set_sensitive(w, !SP_IS_ANCHOR(item)); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); /* Set mask */ w = gtk_menu_item_new_with_mnemonic(_("Set Mask")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_set_mask), item); if ((item && item->mask_ref && item->mask_ref->getObject()) || (item->clip_ref && item->clip_ref->getObject())) { gtk_widget_set_sensitive(w, FALSE); } else { gtk_widget_set_sensitive(w, TRUE); } gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); /* Release mask */ w = gtk_menu_item_new_with_mnemonic(_("Release Mask")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_release_mask), item); if (item && item->mask_ref && item->mask_ref->getObject()) { gtk_widget_set_sensitive(w, TRUE); } else { gtk_widget_set_sensitive(w, FALSE); } gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); /* Set Clip */ w = gtk_menu_item_new_with_mnemonic(_("Set _Clip")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_set_clip), item); if ((item && item->mask_ref && item->mask_ref->getObject()) || (item->clip_ref && item->clip_ref->getObject())) { gtk_widget_set_sensitive(w, FALSE); } else { gtk_widget_set_sensitive(w, TRUE); } gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); /* Release Clip */ w = gtk_menu_item_new_with_mnemonic(_("Release C_lip")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_release_clip), item); if (item && item->clip_ref && item->clip_ref->getObject()) { gtk_widget_set_sensitive(w, TRUE); } else { gtk_widget_set_sensitive(w, FALSE); } gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); } static void sp_item_properties(GtkMenuItem *menuitem, SPItem *item) { SPDesktop *desktop; g_assert(SP_IS_ITEM(item)); desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); sp_desktop_selection(desktop)->set(item); // sp_item_dialog(); desktop->_dlg_mgr->showDialog("ObjectProperties"); } static void sp_set_mask(GtkMenuItem *menuitem, SPItem *item) { SPDesktop *desktop; g_assert(SP_IS_ITEM(item)); desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); sp_selection_set_mask(desktop, false, false); } static void sp_release_mask(GtkMenuItem *menuitem, SPItem *item) { SPDesktop *desktop; g_assert(SP_IS_ITEM(item)); desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); sp_selection_unset_mask(desktop, false); } static void sp_set_clip(GtkMenuItem *menuitem, SPItem *item) { SPDesktop *desktop; g_assert(SP_IS_ITEM(item)); desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); sp_selection_set_mask(desktop, true, false); } static void sp_release_clip(GtkMenuItem *menuitem, SPItem *item) { SPDesktop *desktop; g_assert(SP_IS_ITEM(item)); desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); sp_selection_unset_mask(desktop, true); } static void sp_item_select_this(GtkMenuItem *menuitem, SPItem *item) { SPDesktop *desktop; g_assert(SP_IS_ITEM(item)); desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); sp_desktop_selection(desktop)->set(item); } static void sp_item_create_link(GtkMenuItem *menuitem, SPItem *item) { g_assert(SP_IS_ITEM(item)); g_assert(!SP_IS_ANCHOR(item)); SPDesktop *desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:a"); item->parent->getRepr()->addChild(repr, item->getRepr()); SPObject *object = item->document->getObjectByRepr(repr); g_return_if_fail(SP_IS_ANCHOR(object)); const char *id = item->getRepr()->attribute("id"); Inkscape::XML::Node *child = item->getRepr()->duplicate(xml_doc); item->deleteObject(false); repr->addChild(child, NULL); child->setAttribute("id", id); Inkscape::GC::release(repr); Inkscape::GC::release(child); DocumentUndo::done(object->document, SP_VERB_NONE, _("Create link")); sp_desktop_selection(desktop)->set(SP_ITEM(object)); desktop->_dlg_mgr->showDialog("ObjectAttributes"); } /* SPGroup */ static void sp_item_group_ungroup_activate(GtkMenuItem *menuitem, SPGroup *group); static void sp_group_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu) { SPItem *item=SP_ITEM(object); GtkWidget *w; /* "Ungroup" */ w = gtk_menu_item_new_with_mnemonic(_("_Ungroup")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_item_group_ungroup_activate), item); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(menu), w); } static void sp_item_group_ungroup_activate(GtkMenuItem *menuitem, SPGroup *group) { SPDesktop *desktop; GSList *children; g_assert(SP_IS_GROUP(group)); desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); children = NULL; sp_item_group_ungroup(group, &children); sp_desktop_selection(desktop)->setList(children); g_slist_free(children); } /* SPAnchor */ static void sp_anchor_link_properties(GtkMenuItem *menuitem, SPAnchor *anchor); static void sp_anchor_link_follow(GtkMenuItem *menuitem, SPAnchor *anchor); static void sp_anchor_link_remove(GtkMenuItem *menuitem, SPAnchor *anchor); static void sp_anchor_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m) { SPItem *item; GtkWidget *w; item = (SPItem *) object; /* Link dialog */ w = gtk_menu_item_new_with_mnemonic(_("Link _Properties...")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_anchor_link_properties), item); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); /* Select item */ w = gtk_menu_item_new_with_mnemonic(_("_Follow Link")); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_anchor_link_follow), item); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); /* Reset transformations */ w = gtk_menu_item_new_with_mnemonic(_("_Remove Link")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_anchor_link_remove), item); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); } static void sp_anchor_link_properties(GtkMenuItem *menuitem, SPAnchor */*anchor*/) { SPDesktop *desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); desktop->_dlg_mgr->showDialog("ObjectAttributes"); } static void sp_anchor_link_follow(GtkMenuItem */*menuitem*/, SPAnchor *anchor) { g_return_if_fail(anchor != NULL); g_return_if_fail(SP_IS_ANCHOR(anchor)); /* shell out to an external browser here */ } static void sp_anchor_link_remove(GtkMenuItem */*menuitem*/, SPAnchor *anchor) { GSList *children; g_return_if_fail(anchor != NULL); g_return_if_fail(SP_IS_ANCHOR(anchor)); children = NULL; sp_item_group_ungroup(SP_GROUP(anchor), &children); g_slist_free(children); } /* Image */ static void sp_image_image_properties(GtkMenuItem *menuitem, SPAnchor *anchor); static void sp_image_image_edit(GtkMenuItem *menuitem, SPItem *item); static void sp_image_image_embed(GtkMenuItem *menuitem, SPItem *item); static void sp_image_image_extract(GtkMenuItem *menuitem, SPItem *item); static void sp_image_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m) { SPItem *item = SP_ITEM(object); GtkWidget *w; Inkscape::XML::Node *ir = object->getRepr(); const gchar *href = ir->attribute("xlink:href"); /* Image properties */ w = gtk_menu_item_new_with_mnemonic(_("Image _Properties...")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_image_image_properties), item); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); /* Edit externally */ w = gtk_menu_item_new_with_mnemonic(_("Edit Externally...")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_image_image_edit), item); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); if ( (!href) || ((strncmp(href, "data:", 5) == 0)) ) { gtk_widget_set_sensitive( w, FALSE ); } /* Embed image */ if (Inkscape::Verb::getbyid( "org.ekips.filter.embedselectedimages" )) { w = gtk_menu_item_new_with_mnemonic(C_("Context menu", "Embed Image")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_image_image_embed), item); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); if ( (!href) || ((strncmp(href, "data:", 5) == 0)) ) { gtk_widget_set_sensitive( w, FALSE ); } } /* Extract image */ if (Inkscape::Verb::getbyid( "org.ekips.filter.extractimage" )) { w = gtk_menu_item_new_with_mnemonic(C_("Context menu", "Extract Image...")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_image_image_extract), item); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); if ( (!href) || ((strncmp(href, "data:", 5) != 0)) ) { gtk_widget_set_sensitive( w, FALSE ); } } } /* Image Properties entry */ static void sp_image_image_properties(GtkMenuItem *menuitem, SPAnchor */*anchor*/) { SPDesktop *desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); desktop->_dlg_mgr->showDialog("ObjectAttributes"); } static gchar* getImageEditorName() { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); gchar* value = 0; Glib::ustring choices = prefs->getString("/options/bitmapeditor/value"); if (!choices.empty()) { value = g_strdup(choices.c_str()); } if (!value) { value = g_strdup("gimp"); } return value; } /* Edit Externally entry */ static void sp_image_image_edit(GtkMenuItem *menuitem, SPItem *item) { SPDesktop *desktop = NULL; g_assert(SP_IS_ITEM(item)); desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); if (sp_desktop_selection(desktop)->isEmpty()) { sp_desktop_selection(desktop)->set(item); } GSList const *selected = sp_desktop_selection(desktop)->itemList(); GError* errThing = 0; Glib::ustring cmdline = getImageEditorName(); Glib::ustring name; Glib::ustring fullname; #ifdef WIN32 // g_spawn_command_line_sync parsing is done according to Unix shell rules, // not Windows command interpreter rules. Thus we need to enclose the // executable path with sigle quotes. int index = cmdline.find(".exe"); if ( index < 0 ) index = cmdline.find(".bat"); if ( index < 0 ) index = cmdline.find(".com"); if ( index >= 0 ) { Glib::ustring editorBin = cmdline.substr(0, index + 4).c_str(); Glib::ustring args = cmdline.substr(index + 4, cmdline.length()).c_str(); editorBin.insert(0, "'"); editorBin.append("'"); cmdline = editorBin; cmdline.append(args); } else { // Enclose the whole command line if no executable path can be extracted. cmdline.insert(0, "'"); cmdline.append("'"); } #endif for (GSList const *iter = selected; iter != NULL; iter = iter->next) { Inkscape::XML::Node *ir = SP_ITEM(iter->data)->getRepr(); const gchar *href = ir->attribute("xlink:href"); if (strncmp (href,"file:",5) == 0) { // URI to filename conversion name = g_filename_from_uri(href, NULL, NULL); } else { name.append(href); } if (Glib::path_is_absolute(name)) { fullname = name; } else if (SP_ACTIVE_DOCUMENT->getBase()) { fullname = Glib::build_filename(SP_ACTIVE_DOCUMENT->getBase(), name); } else { fullname = Glib::build_filename(Glib::get_current_dir(), name); } cmdline.append(" '"); cmdline.append(fullname.c_str()); cmdline.append("'"); } //g_warning("##Command line: %s\n", cmdline.c_str()); g_spawn_command_line_async(cmdline.c_str(), &errThing); if ( errThing ) { g_warning("Problem launching editor (%d). %s", errThing->code, errThing->message); SPDesktop *desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, errThing->message); g_error_free(errThing); errThing = 0; } } /* Embed Image entry */ static void sp_image_image_embed(GtkMenuItem *menuitem, SPItem *item) { SPDesktop *desktop; g_assert(SP_IS_ITEM(item)); desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); if (sp_desktop_selection(desktop)->isEmpty()) { sp_desktop_selection(desktop)->set(item); } Inkscape::Verb *verb = Inkscape::Verb::getbyid( "org.ekips.filter.embedselectedimages" ); if (verb) { SPAction *action = verb->get_action(desktop); if (action) { sp_action_perform(action, NULL); } } } /* Extract Image entry */ static void sp_image_image_extract(GtkMenuItem *menuitem, SPItem *item) { SPDesktop *desktop; g_assert(SP_IS_ITEM(item)); desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); if (sp_desktop_selection(desktop)->isEmpty()) { sp_desktop_selection(desktop)->set(item); } Inkscape::Verb *verb = Inkscape::Verb::getbyid( "org.ekips.filter.extractimage" ); if (verb) { SPAction *action = verb->get_action(desktop); if (action) { sp_action_perform(action, NULL); } } } /* Fill and Stroke entry */ static void sp_fill_settings(GtkMenuItem *menuitem, SPItem *item) { SPDesktop *desktop; g_assert(SP_IS_ITEM(item)); desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); if (sp_desktop_selection(desktop)->isEmpty()) { sp_desktop_selection(desktop)->set(item); } desktop->_dlg_mgr->showDialog("FillAndStroke"); } /* SPShape */ static void sp_shape_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m) { SPItem *item; GtkWidget *w; item = (SPItem *) object; /* Item dialog */ w = gtk_menu_item_new_with_mnemonic(_("_Fill and Stroke...")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_fill_settings), item); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); } /* Edit Text entry */ static void sp_text_settings(GtkMenuItem *menuitem, SPItem *item) { SPDesktop *desktop; g_assert(SP_IS_ITEM(item)); desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); if (sp_desktop_selection(desktop)->isEmpty()) { sp_desktop_selection(desktop)->set(item); } desktop->_dlg_mgr->showDialog("TextFont"); } /* Spellcheck entry */ static void sp_spellcheck_settings(GtkMenuItem *menuitem, SPItem *item) { SPDesktop *desktop; g_assert(SP_IS_ITEM(item)); desktop = (SPDesktop*)g_object_get_data(G_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); if (sp_desktop_selection(desktop)->isEmpty()) { sp_desktop_selection(desktop)->set(item); } desktop->_dlg_mgr->showDialog("SpellCheck"); } /* SPText */ static void sp_text_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m) { SPItem *item; GtkWidget *w; item = (SPItem *) object; /* Fill and Stroke dialog */ w = gtk_menu_item_new_with_mnemonic(_("_Fill and Stroke...")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_fill_settings), item); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); /* Edit Text dialog */ w = gtk_menu_item_new_with_mnemonic(_("_Text and Font...")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_text_settings), item); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); /* Spellcheck dialog */ w = gtk_menu_item_new_with_mnemonic(_("Check Spellin_g...")); g_object_set_data(G_OBJECT(w), "desktop", desktop); g_signal_connect(G_OBJECT(w), "activate", G_CALLBACK(sp_spellcheck_settings), item); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m), w); } /* Local Variables: mode:c++ c-file-style:"stroustrup" c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :