=== modified file 'src/ui/dialog/find.cpp' --- src/ui/dialog/find.cpp 2011-10-27 04:55:51 +0000 +++ src/ui/dialog/find.cpp 2012-01-02 13:37:01 +0000 @@ -50,6 +50,8 @@ #include "sp-offset.h" #include "sp-root.h" #include "xml/repr.h" +#include "xml/node-iterators.h" +#include "xml/attribute-record.h" namespace Inkscape { @@ -58,77 +60,156 @@ Find::Find() : UI::Widget::Panel("", "/dialogs/find", SP_VERB_DIALOG_FIND), - _entry_text(_("_Text:"), _("Find objects by their text content (exact or partial match)")), - _entry_id(_("_ID:"), _("Find objects by the value of the id attribute (exact or partial match)")), - _entry_style(_("_Style:"), _("Find objects by the value of the style attribute (exact or partial match)")), - _entry_attribute(_("_Attribute:"), _("Find objects by the name of an attribute (exact or partial match)")), - _check_search_selection(_("Search in s_election"), _("Limit search to the current selection")), - _check_search_layer(_("Search in current _layer"), _("Limit search to the current layer")), - _check_include_hidden(_("Include _hidden"), _("Include hidden objects in search")), - _check_include_locked(_("Include l_ocked"), _("Include locked objects in search")), - - _check_all(_("All types"), _("Search in all object types")), - _check_all_shapes(_("All shapes"), _("Search all shapes")), - _check_rects(_("Rectangles"), _("Search rectangles")), - _check_ellipses(_("Ellipses"), _("Search ellipses, arcs, circles")), - _check_stars(_("Stars"), _("Search stars and polygons")), - _check_spirals(_("Spirals"), _("Search spirals")), - _check_paths(_("Paths"), _("Search paths, lines, polylines")), - _check_texts(_("Texts"), _("Search text objects")), - _check_groups(_("Groups"), _("Search groups")), + + _entry_find(_("F_ind:"), _("Find objects by their content (exact or partial match)")), + _entry_replace(_("Re_place:"), _("Replace found objects with this value ")), + + _check_scope_all(_("_All"), _("Search in all layers")), + _check_scope_layer(_("Current _layer"), _("Limit search to the current layer")), + _check_scope_selection(_("S_election"), _("Limit search to the current selection")), + _check_searchin_text(_("Te_xt"), _("Search in text objects")), + _check_searchin_property(_("_Properties"), _("Search in object properties, styles, attributes and IDs")), + + _check_case_sensitive(_("Case sensiti_ve"), _("Match upper/lower case"), false), + _check_exact_match(_("E_xact match"), _("Match whole objects only"), false), + _check_include_hidden(_("Include _hidden"), _("Include hidden objects in search"), false), + _check_include_locked(_("Include loc_ked"), _("Include locked objects in search"), false), + + _check_ids(_("ID"), _("Search id name"), true), + _check_attributename(_("Attribute Name"), _("Search attribute name"), false), + _check_attributevalue(_("Attribute Value"), _("Search attribute value"), true), + _check_style(_("Style"), _("Search style"), true), + _check_font(_("Font"), _("Search fonts"), false), + + _check_alltypes(_("All types"), _("Check all/none"), true), + _check_rects(_("Rectangles"), _("Search rectangles"), false), + _check_ellipses(_("Ellipses"), _("Search ellipses, arcs, circles"), false), + _check_stars(_("Stars"), _("Search stars and polygons"), false), + _check_spirals(_("Spirals"), _("Search spirals"), false), + _check_paths(_("Paths"), _("Search paths, lines, polylines"), false), + _check_texts(_("Texts"), _("Search text objects"), false), + _check_groups(_("Groups"), _("Search groups"), false), _check_clones( //TRANSLATORS: "Clones" is a noun indicating type of object to find - C_("Find dialog", "Clones"), _("Search clones")), - _check_images(_("Images"), _("Search images")), - _check_offsets(_("Offsets"), _("Search offset objects")), - - _button_clear(_("_Clear"), _("Clear values")), - _button_find(_("_Find"), _("Select objects matching all of the fields you filled in")) + C_("Find dialog", "Clones"), _("Search clones"), false), + + _check_images(_("Images"), _("Search images"), false), + _check_offsets(_("Offsets"), _("Search offset objects"), false), + + _expander_options(_("Options ...")), + + _frame_searchin(_("Search for text in")), + _frame_scope(_("Scope")), + _frame_options(_("General")), + _frame_properties(_("Properties")), + _frame_types(_("Object Types")), + + _status(""), + _button_find(_("_Find"), _("Select all objects matching the selected fields ")), + _button_replace(_("_Replace"), _("Replace all the matching objects")), + _action_replace(false) + { + _entry_find.getEntry()->set_width_chars(25); + _entry_replace.getEntry()->set_width_chars(25); + + Gtk::RadioButtonGroup grp_searchin = _check_searchin_text.get_group(); + _check_searchin_property.set_group(grp_searchin); + _vbox_searchin.pack_start(_check_searchin_text, true, true); + _vbox_searchin.pack_start(_check_searchin_property, true, true); + _frame_searchin.add(_vbox_searchin); + + Gtk::RadioButtonGroup grp_scope = _check_scope_all.get_group(); + _check_scope_layer.set_group(grp_scope); + _check_scope_selection.set_group(grp_scope); + _vbox_scope.pack_start(_check_scope_all, true, true); + _vbox_scope.pack_start(_check_scope_layer, true, true); + _vbox_scope.pack_start(_check_scope_selection, true, true); + _frame_scope.add(_vbox_scope); + + _hbox_searchin.set_spacing(4); + _hbox_searchin.pack_start(_frame_searchin, true, true); + _hbox_searchin.pack_start(_frame_scope, true, true); + + _vbox_options1.pack_start(_check_case_sensitive, true, true); + _vbox_options1.pack_start(_check_include_hidden, true, true); + _vbox_options2.pack_start(_check_exact_match, true, true); + _vbox_options2.pack_start(_check_include_locked, true, true); + _hbox_options.pack_start(_vbox_options1, true, true, 4); + _hbox_options.pack_start(_vbox_options2, true, true, 4); + _frame_options.add(_hbox_options); + + _hbox_properties1.set_homogeneous(false); + _hbox_properties1.pack_start(_check_ids, false, false, 4 ); + _hbox_properties1.pack_start(_check_style, false, false, 8); + _hbox_properties1.pack_start(_check_font, false, false, 8); + _hbox_properties2.set_homogeneous(false); + _hbox_properties2.pack_start(_check_attributevalue, false, false, 4); + _hbox_properties2.pack_start(_check_attributename, false, false, 4); + _vbox_properties.pack_start(_hbox_properties1, true, true, 6); + _vbox_properties.pack_start(_hbox_properties2, true, true, 4); + _frame_properties.add(_vbox_properties); + + _vbox_types1.pack_start(_check_alltypes, true, true); + _vbox_types1.pack_start(_check_paths, true, true); + _vbox_types1.pack_start(_check_texts, true, true); + _vbox_types1.pack_start(_check_groups, true, true); + _vbox_types1.pack_start(_check_clones, true, true); + _vbox_types1.pack_start(_check_images, true, true); + _vbox_types2.pack_start(_check_offsets, true, true); + _vbox_types2.pack_start(_check_rects, true, true); + _vbox_types2.pack_start(_check_ellipses, true, true); + _vbox_types2.pack_start(_check_stars, true, true); + _vbox_types2.pack_start(_check_spirals, true, true); + _hbox_types.pack_start(_vbox_types1, true, true, 4); + _hbox_types.pack_start(_vbox_types2, true, true, 4); + _frame_types.add(_hbox_types); + + _vbox_expander.pack_start(_frame_options, true, true, 4); + _vbox_expander.pack_start(_frame_properties, true, true, 4); + _vbox_expander.pack_start(_frame_types, true, true, 4); + + _expander_options.set_use_underline(); + _expander_options.add(_vbox_expander); + + _box_buttons.set_layout(Gtk::BUTTONBOX_END); + _box_buttons.set_spacing(4); + _box_buttons.pack_start(_button_find, true, true, 6); + _box_buttons.pack_start(_button_replace, true, true, 6); + _hbox_button_row.pack_start(_status, true, true, 6); + _hbox_button_row.pack_end(_box_buttons, true, true); + Gtk::Box *contents = _getContents(); - contents->set_spacing(4); - - contents->pack_start(_entry_text, true, true); - contents->pack_start(_entry_id, true, true); - contents->pack_start(_entry_style, true, true); - contents->pack_start(_entry_attribute, true, true); - - contents->pack_start(_check_all, true, true); - contents->pack_start(_check_all_shapes, true, true); - contents->pack_start(_check_rects, true, true); - contents->pack_start(_check_ellipses, true, true); - contents->pack_start(_check_stars, true, true); - contents->pack_start(_check_spirals, true, true); - contents->pack_start(_check_paths, true, true); - contents->pack_start(_check_texts, true, true); - contents->pack_start(_check_groups, true, true); - contents->pack_start(_check_clones, true, true); - contents->pack_start(_check_images, true, true); - contents->pack_start(_check_offsets, true, true); - - contents->pack_start(_check_search_selection, true, true); - contents->pack_start(_check_search_layer, true, true); - contents->pack_start(_check_include_hidden, true, true); - contents->pack_start(_check_include_locked, true, true); - - contents->pack_start(_button_clear, true, true); - contents->pack_start(_button_find, true, true); + contents->set_spacing(6); + contents->pack_start(_entry_find, false, false); + contents->pack_start(_entry_replace, false, false); + contents->pack_start(_hbox_searchin, false, false); + //contents->pack_start(_frame_options, false, false); + contents->pack_start(_expander_options, false, false); + contents->pack_end(_hbox_button_row, false, false); // set signals to handle clicks - _check_all.signal_clicked().connect(sigc::mem_fun(*this, &Find::onToggleAlltypes)); - _check_all_shapes.signal_clicked().connect(sigc::mem_fun(*this, &Find::onToggleShapes)); - _button_clear.signal_clicked().connect(sigc::mem_fun(*this, &Find::onClear)); + _expander_options.property_expanded().signal_changed().connect(sigc::mem_fun(*this, &Find::onExpander)); _button_find.signal_clicked().connect(sigc::mem_fun(*this, &Find::onFind)); + _button_replace.signal_clicked().connect(sigc::mem_fun(*this, &Find::onReplace)); + _check_alltypes.signal_clicked().connect(sigc::mem_fun(*this, &Find::onToggleAlltypes)); + + _check_searchin_text.signal_clicked().connect(sigc::mem_fun(*this, &Find::onSearchinText)); + _check_searchin_property.signal_clicked().connect(sigc::mem_fun(*this, &Find::onSearchinProperty)); + _check_attributename.signal_clicked().connect(sigc::mem_fun(*this, &Find::onAttributeName)); + _button_find.set_flags(Gtk::CAN_DEFAULT); - // set_default (_button_find); // activatable by Enter - _entry_text.getEntry()->grab_focus(); + //_button_find.grab_default(); // activatable by Enter + _entry_find.getEntry()->grab_focus(); + onSearchinText(); + onToggleAlltypes(); show_all_children(); - onClear(); + } -Find::~Find() +Find::~Find() { } @@ -137,9 +218,9 @@ # FIND helper functions ########################################################################*/ - + bool -Find::item_id_match (SPItem *item, const gchar *id, bool exact) +Find::item_id_match (SPItem *item, const gchar *id, bool exact, bool casematch, bool replace/*=false*/) { if (item->getRepr() == NULL) { return false; @@ -153,17 +234,32 @@ if (item_id == NULL) { return false; } - + bool ret = false; if (exact) { - return ((bool) !strcmp(item_id, id)); + ret = ((bool) !strcmp(item_id, id)); } else { -// g_print ("strstr: %s %s: %s\n", item_id, id, strstr(item_id, id) != NULL? "yes":"no"); - return ((bool) (strstr(item_id, id) != NULL)); - } + if (casematch) { + ret = ((bool) (strstr(item_id, id) != NULL)); + } + else { + ret = ((bool) (strcasestr(item_id, id) != NULL)); + } + } + if (ret && replace) { + const gchar * replace_text = _entry_replace.get_text().c_str(); + Glib::ustring new_item_style = item_id; + gsize n = new_item_style.find(id); + if (n != std::string::npos) { + new_item_style.replace(n, strlen(id), replace_text); + item->getRepr()->setAttribute("style", new_item_style.data()); + } + } + + return ret; } bool -Find::item_text_match (SPItem *item, const gchar *text, bool exact) +Find::item_text_match (SPItem *item, const gchar *text, bool exact, bool casematch, bool replace/*=false*/) { if (item->getRepr() == NULL) { return false; @@ -175,105 +271,299 @@ return false; bool ret; if (exact) { - ret = ((bool) !strcasecmp(item_text, text)); + if (casematch) { + ret = ((bool) !strcmp(item_text, text)); + } + else { + ret = ((bool) !strcasecmp(item_text, text)); + } } else { - //FIXME: strcasestr - ret = ((bool) (strstr(item_text, text) != NULL)); - } + if (casematch) { + ret = ((bool) (strstr(item_text, text) != NULL)); + } + else { + ret = ((bool) (strcasestr(item_text, text) != NULL)); + } + } + if (ret && replace) { + Inkscape::Text::Layout const *layout = te_get_layout (item); + if (layout) { + const gchar* replace_text = g_strdup(_entry_replace.get_text().c_str()); + static Inkscape::Text::Layout::iterator _begin_w; + static Inkscape::Text::Layout::iterator _end_w; + const char *p = strstr(item_text, text); + int start = p-item_text; + if (start < 0) + start = 0; + int end = start + strlen(text); + _begin_w = layout->charIndexToIterator(start); + _end_w = layout->charIndexToIterator(end); + sp_te_replace(item, _begin_w, _end_w, replace_text); + } + } + g_free ((void*) item_text); + return ret; } return false; } bool -Find::item_style_match (SPItem *item, const gchar *text, bool exact) +Find::item_style_match (SPItem *item, const gchar *text, bool exact, bool casematch, bool replace/*=false*/) { if (item->getRepr() == NULL) { return false; } - const gchar *item_text = item->getRepr()->attribute("style"); - if (item_text == NULL) { + const gchar *item_style = g_strdup(item->getRepr()->attribute("style")); + if (item_style == NULL) { return false; } + bool ret = false; if (exact) { - return ((bool) !strcmp(item_text, text)); + ret = ((bool) !strcmp(item_style, text)); } else { - return ((bool) (strstr(item_text, text) != NULL)); - } + if (casematch) { + ret = ((bool) (strstr(item_style, text) != NULL)); + } + else { + ret = ((bool) (strcasestr(item_style, text) != NULL)); + } + } + + if (ret && replace) { + const gchar * replace_text = _entry_replace.get_text().c_str(); + Glib::ustring new_item_style = item_style; + gsize n = new_item_style.find(text); + if (n != std::string::npos) { + new_item_style.replace(n, strlen(text), replace_text); + item->getRepr()->setAttribute("style", new_item_style.data()); + } + } + + return ret; } -bool Find::item_attr_match(SPItem *item, const gchar *name, bool exact) +bool Find::item_attr_match(SPItem *item, const gchar *text, bool exact, bool casematch, bool replace/*=false*/) { bool result = false; if (item->getRepr()) { + const gchar *attr_value = g_strdup(item->getRepr()->attribute(text)); if (exact) { - const gchar *attr_value = item->getRepr()->attribute(name); result = (attr_value != NULL); } else { - result = item->getRepr()->matchAttributeName(name); - } - } - return result; + result = item->getRepr()->matchAttributeName(text); + } + + // TODO - Rename attribute ? + if (result && replace) { + result = false; + } + } + return result; +} + +bool Find::item_attrvalue_match(SPItem *item, const gchar *text, bool exact, bool casematch, bool replace/*=false*/) +{ + bool result = false; + if (item->getRepr()) { + + Inkscape::Util::List iter = item->getRepr()->attributeList(); + for (; iter; ++iter) { + const gchar* key = g_quark_to_string(iter->key); + const gchar *attr_value = g_strdup(item->getRepr()->attribute(key)); + if (exact) { + result = ((bool) !strcmp(attr_value , text)); + } else { + if (casematch) { + result = ((bool) (strstr(attr_value , text) != NULL)); + } + else { + result = ((bool) (strcasestr(attr_value , text) != NULL)); + } + } + if (result && replace) { + const gchar * replace_text = _entry_replace.get_text().c_str(); + Glib::ustring new_item_style = attr_value; + gsize n = new_item_style.find(text); + if (n != std::string::npos) { + new_item_style.replace(n, strlen(text), replace_text); + item->getRepr()->setAttribute(key, new_item_style.data()); + //DocumentUndo::done(sp_desktop_document(getDesktop()), SP_VERB_CONTEXT_TEXT, _("Text replace")); + } + } + if (result) { + return result; + } + } + } + return result; +} + + +bool Find::item_font_match(SPItem *item, const gchar *text, bool exact, bool casematch, bool replace/*=false*/) +{ + if (item->getRepr() == NULL) { + return false; + } + + const gchar *item_style = item->getRepr()->attribute("style"); + if (item_style == NULL) { + return false; + } + + bool ret = false; + + std::vector vTokens = Glib::Regex::split_simple(";", item_style); + for(size_t i=0; igetRepr()->setAttribute("style", new_item_style.data()); + } + + return ret; } GSList * -Find::filter_fields (GSList *l, bool exact) +Find::filter_fields (GSList *l, bool exact, bool casematch) { - const gchar* text = _entry_text.getEntry()->get_text().c_str(); - const gchar* id = _entry_id.getEntry()->get_text().c_str(); - const gchar* style = _entry_style.getEntry()->get_text().c_str(); - const gchar* attr = _entry_attribute.getEntry()->get_text().c_str(); - + + const gchar* text = g_strdup(_entry_find.get_text().c_str()); + GSList *in = l; GSList *out = NULL; - if (strlen (text) != 0) { - for (GSList *i = in; i != NULL; i = i->next) { - if (item_text_match (SP_ITEM(i->data), text, exact)) { - out = g_slist_prepend (out, i->data); - } - } - } else { - out = in; - } - - in = out; - out = NULL; - if (strlen (id) != 0) { - for (GSList *i = in; i != NULL; i = i->next) { - if (item_id_match (SP_ITEM(i->data), id, exact)) { - out = g_slist_prepend (out, i->data); - } - } - } else { - out = in; - } - - in = out; - out = NULL; - if (strlen (style) != 0) { - for (GSList *i = in; i != NULL; i = i->next) { - if (item_style_match (SP_ITEM(i->data), style, exact)) { - out = g_slist_prepend (out, i->data); - } - } - } else { - out = in; - } - - in = out; - out = NULL; - if (strlen (attr) != 0) { - for (GSList *i = in; i != NULL; i = i->next) { - if (item_attr_match (SP_ITEM(i->data), attr, exact)) { - out = g_slist_prepend (out, i->data); - } - } - } else { - out = in; + + if (strlen (text) == 0) { + return in; + } + + if (_check_searchin_text.get_active()) { + for (GSList *i = in; i != NULL; i = i->next) { + if (item_text_match (SP_ITEM(i->data), text, exact, casematch)) { + if (!g_slist_find(out, i->data)) { + out = g_slist_prepend (out, i->data); + if (_action_replace) { + item_text_match (SP_ITEM(i->data), text, exact, casematch, _action_replace); + } + } + } + } + } + else if (_check_searchin_property.get_active()) { + + bool ids = _check_ids.get_active(); + bool style = _check_style.get_active(); + bool font = _check_font.get_active(); + bool attrname = _check_attributename.get_active(); + bool attrvalue = _check_attributevalue.get_active(); + + if (ids) { + for (GSList *i = in; i != NULL; i = i->next) { + if (item_id_match (SP_ITEM(i->data), text, exact, casematch)) { + if (!g_slist_find(out, i->data)) { + out = g_slist_prepend (out, i->data); + if (_action_replace) { + item_id_match (SP_ITEM(i->data), text, exact, casematch, _action_replace); + } + } + } + } + } + + + if (style) { + for (GSList *i = in; i != NULL; i = i->next) { + if (item_style_match (SP_ITEM(i->data), text, exact, casematch)) { + if (!g_slist_find(out, i->data)) + if (!g_slist_find(out, i->data)) { + out = g_slist_prepend (out, i->data); + if (_action_replace) { + item_style_match (SP_ITEM(i->data), text, exact, casematch, _action_replace); + } + } + } + } + } + + + if (attrname) { + for (GSList *i = in; i != NULL; i = i->next) { + if (item_attr_match (SP_ITEM(i->data), text, exact, casematch)) { + if (!g_slist_find(out, i->data)) { + out = g_slist_prepend (out, i->data); + if (_action_replace) { + item_attr_match (SP_ITEM(i->data), text, exact, casematch, _action_replace); + } + } + } + } + } + + + if (attrvalue) { + for (GSList *i = in; i != NULL; i = i->next) { + if (item_attrvalue_match (SP_ITEM(i->data), text, exact, casematch)) { + if (!g_slist_find(out, i->data)) { + out = g_slist_prepend (out, i->data); + if (_action_replace) { + item_attrvalue_match (SP_ITEM(i->data), text, exact, casematch, _action_replace); + } + } + } + } + } + + + if (font) { + for (GSList *i = in; i != NULL; i = i->next) { + if (item_font_match (SP_ITEM(i->data), text, exact, casematch)) { + if (!g_slist_find(out, i->data)) { + out = g_slist_prepend (out, i->data); + if (_action_replace) { + item_font_match (SP_ITEM(i->data), text, exact, casematch, _action_replace); + } + } + } + } + } + } return out; @@ -284,36 +574,37 @@ Find::item_type_match (SPItem *item) { SPDesktop *desktop = getDesktop(); + bool all =_check_alltypes.get_active(); - if (SP_IS_RECT(item)) { - return (_check_all_shapes.get_active() || _check_rects.get_active()); + if ( SP_IS_RECT(item)) { + return ( all ||_check_rects.get_active()); } else if (SP_IS_GENERICELLIPSE(item) || SP_IS_ELLIPSE(item) || SP_IS_ARC(item) || SP_IS_CIRCLE(item)) { - return (_check_all_shapes.get_active() || _check_ellipses.get_active()); + return ( all || _check_ellipses.get_active()); } else if (SP_IS_STAR(item) || SP_IS_POLYGON(item)) { - return (_check_all_shapes.get_active() || _check_stars.get_active()); + return ( all || _check_stars.get_active()); } else if (SP_IS_SPIRAL(item)) { - return (_check_all_shapes.get_active() || _check_spirals.get_active()); + return ( all || _check_spirals.get_active()); } else if (SP_IS_PATH(item) || SP_IS_LINE(item) || SP_IS_POLYLINE(item)) { - return (_check_paths.get_active()); + return (all || _check_paths.get_active()); } else if (SP_IS_TEXT(item) || SP_IS_TSPAN(item) || SP_IS_TREF(item) || SP_IS_STRING(item)) { - return (_check_texts.get_active()); + return (all || _check_texts.get_active()); } else if (SP_IS_GROUP(item) && !desktop->isLayer(item) ) { // never select layers! - return (_check_groups.get_active()); + return (all || _check_groups.get_active()); } else if (SP_IS_USE(item)) { - return (_check_clones.get_active()); + return (all || _check_clones.get_active()); } else if (SP_IS_IMAGE(item)) { - return (_check_images.get_active()); + return (all || _check_images.get_active()); } else if (SP_IS_OFFSET(item)) { - return (_check_offsets.get_active()); + return (all || _check_offsets.get_active()); } return false; @@ -322,8 +613,6 @@ GSList * Find::filter_types (GSList *l) { - if (_check_all.get_active()) return l; - GSList *n = NULL; for (GSList *i = l; i != NULL; i = i->next) { if (item_type_match (SP_ITEM(i->data))) { @@ -335,10 +624,10 @@ GSList * -Find::filter_list (GSList *l, bool exact) +Find::filter_list (GSList *l, bool exact, bool casematch) { - l = filter_fields (l, exact); l = filter_types (l); + l = filter_fields (l, exact, casematch); return l; } @@ -387,43 +676,60 @@ } return l; } - - + + /*######################################################################## # BUTTON CLICK HANDLERS (callbacks) ########################################################################*/ void -Find::onClear() -{ - _entry_text.getEntry()->set_text(Glib::ustring("")); - _entry_id.getEntry()->set_text(Glib::ustring("")); - _entry_style.getEntry()->set_text(Glib::ustring("")); - _entry_attribute.getEntry()->set_text(Glib::ustring("")); - - _check_all.set_active(); -} - - - -void Find::onFind() -{ +{ + _action_replace = false; + onAction(); +} + +void +Find::onReplace() +{ + if (_entry_find.get_text().length() < 1) { + _status.set_text(_("Nothing to replace")); + return; + } + _action_replace = true; + onAction(); +} + +void +Find::onAction() +{ + SPDesktop *desktop = getDesktop(); bool hidden = _check_include_hidden.get_active(); bool locked = _check_include_locked.get_active(); + bool exact = _check_exact_match.get_active(); + bool casematch = _check_case_sensitive.get_active(); + + // Add find/replace text to combobox list + _entry_find.remove_text(_entry_find.get_text()); + _entry_find.prepend_text(_entry_find.get_text().c_str()); + + if (_action_replace) { + _entry_replace.remove_text(_entry_replace.get_text()); + _entry_replace.prepend_text(_entry_replace.get_text().c_str()); + } GSList *l = NULL; - if (_check_search_selection.get_active()) { - if (_check_search_layer.get_active()) { + if (_check_scope_selection.get_active()) { + if (_check_scope_layer.get_active()) { l = all_selection_items (desktop->selection, l, desktop->currentLayer(), hidden, locked); } else { l = all_selection_items (desktop->selection, l, NULL, hidden, locked); } } else { - if (_check_search_layer.get_active()) { + if (_check_scope_layer.get_active()) { l = all_items (desktop->currentLayer(), l, hidden, locked); } else { l = all_items(sp_desktop_document(desktop)->getRoot(), l, hidden, locked); @@ -431,13 +737,7 @@ } guint all = g_slist_length (l); - bool exact = true; - GSList *n = NULL; - n = filter_list (l, exact); - if (n == NULL) { - exact = false; - n = filter_list (l, exact); - } + GSList *n = filter_list (l, exact, casematch); if (n != NULL) { int count = g_slist_length (n); @@ -447,12 +747,19 @@ "%d objects found (out of %d), %s match.", count), count, all, exact? _("exact") : _("partial")); + _status.set_text(Glib::ustring::compose("%1 %2 %3", count, _("items"), _action_replace? _("replaced") : _("found") )); Inkscape::Selection *selection = sp_desktop_selection (desktop); selection->clear(); selection->setList(n); scroll_to_show_item (desktop, SP_ITEM(n->data)); + + if (_action_replace) { + DocumentUndo::done(sp_desktop_document(getDesktop()), SP_VERB_CONTEXT_TEXT, _("Text Replace")); + } + } else { + _status.set_text(_("Not found")); desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No objects found")); } } @@ -460,75 +767,70 @@ void Find::onToggleAlltypes () { - if (_check_all.get_active()) { - // explicit toggle to make sure its handler gets called, no matter what was the original state - _check_all_shapes.toggled(); - _check_all_shapes.set_active(); - _check_all_shapes.hide(); - _check_paths.hide(); - _check_texts.hide(); - _check_groups.hide(); - _check_clones.hide(); - _check_images.hide(); - _check_offsets.hide(); - } else { - // explicit toggle to make sure its handler gets called, no matter what was the original state - _check_all_shapes.toggled(); - _check_all_shapes.set_active(); - _check_all_shapes.show(); - - _check_paths.set_active(); - _check_paths.show(); - _check_texts.set_active(); - _check_texts.show(); - _check_groups.set_active(); - _check_groups.show(); - _check_clones.set_active(); - _check_clones.show(); - _check_images.set_active(); - _check_images.show(); - _check_offsets.set_active(); - _check_offsets.show(); - } - squeeze_window(); -} - -void -Find::onToggleShapes () -{ - if (_check_all_shapes.get_active()) { - _check_rects.hide(); - _check_ellipses.hide(); - _check_stars.hide(); - _check_spirals.hide(); - } else { - _check_rects.set_active(); - _check_rects.show(); - _check_ellipses.set_active(); - _check_ellipses.show(); - _check_stars.set_active(); - _check_stars.show(); - _check_spirals.set_active(); - _check_spirals.show(); - } - squeeze_window(); -} - + bool all =_check_alltypes.get_active(); + + _check_paths.set_sensitive(!all); + _check_texts.set_sensitive(!all); + _check_groups.set_sensitive(!all); + _check_clones.set_sensitive(!all); + _check_images.set_sensitive(!all); + _check_offsets.set_sensitive(!all); + _check_rects.set_sensitive(!all); + _check_ellipses.set_sensitive(!all); + _check_stars.set_sensitive(!all); + _check_spirals.set_sensitive(!all); + _check_offsets.set_sensitive(!all); + +} + +void +Find::onSearchinText () +{ + searchinToggle(false); +} + +void +Find::onSearchinProperty () +{ + searchinToggle(true); +} + +void +Find::searchinToggle(bool on) +{ + _check_ids.set_sensitive(on); + _check_attributename.set_sensitive(on); + _check_attributevalue.set_sensitive(on); + _check_style.set_sensitive(on); + _check_font.set_sensitive(on); + +} + +void +Find::onAttributeName () +{ + // Can't replace attribute names + _button_replace.set_sensitive(!_check_attributename.get_active()); +} + +void +Find::onExpander () +{ + if (!_expander_options.get_expanded()) + squeeze_window(); +} /*######################################################################## # UTILITY ########################################################################*/ - - void Find::squeeze_window() { - // TO DO: make window as small as possible + // TODO: make window as small as possible + //set_size_request(0, 0); } - - } // namespace Dialog } // namespace UI } // namespace Inkscape === modified file 'src/ui/dialog/find.h' --- src/ui/dialog/find.h 2010-11-17 02:12:56 +0000 +++ src/ui/dialog/find.h 2012-01-02 10:29:21 +0000 @@ -19,6 +19,7 @@ #include "ui/widget/entry.h" #include #include +#include class SPItem; class SPObject; @@ -38,19 +39,28 @@ protected: // Widgets: - Inkscape::UI::Widget::Entry _entry_text; - Inkscape::UI::Widget::Entry _entry_id; - Inkscape::UI::Widget::Entry _entry_style; - Inkscape::UI::Widget::Entry _entry_attribute; - - Inkscape::UI::Widget::CheckButton _check_search_selection; - Inkscape::UI::Widget::CheckButton _check_search_layer; + Inkscape::UI::Widget::ComboBoxEntryText _entry_find; + Inkscape::UI::Widget::ComboBoxEntryText _entry_replace; + + Inkscape::UI::Widget::RadioButton _check_scope_all; + Inkscape::UI::Widget::RadioButton _check_scope_layer; + Inkscape::UI::Widget::RadioButton _check_scope_selection; + Inkscape::UI::Widget::RadioButton _check_searchin_text; + Inkscape::UI::Widget::RadioButton _check_searchin_property; + + // Type checkbutton widgets... + Inkscape::UI::Widget::CheckButton _check_case_sensitive; + Inkscape::UI::Widget::CheckButton _check_exact_match; Inkscape::UI::Widget::CheckButton _check_include_hidden; Inkscape::UI::Widget::CheckButton _check_include_locked; - - // Type checkbutton widgets... - Inkscape::UI::Widget::CheckButton _check_all; - Inkscape::UI::Widget::CheckButton _check_all_shapes; + + Inkscape::UI::Widget::CheckButton _check_ids; + Inkscape::UI::Widget::CheckButton _check_attributename; + Inkscape::UI::Widget::CheckButton _check_attributevalue; + Inkscape::UI::Widget::CheckButton _check_style; + Inkscape::UI::Widget::CheckButton _check_font; + + Inkscape::UI::Widget::CheckButton _check_alltypes; Inkscape::UI::Widget::CheckButton _check_rects; Inkscape::UI::Widget::CheckButton _check_ellipses; Inkscape::UI::Widget::CheckButton _check_stars; @@ -61,23 +71,29 @@ Inkscape::UI::Widget::CheckButton _check_clones; Inkscape::UI::Widget::CheckButton _check_images; Inkscape::UI::Widget::CheckButton _check_offsets; - + // Button-click handlers - void onClear(); void onFind(); + void onReplace(); + void onExpander(); + void onAction(); void onToggleAlltypes(); - void onToggleShapes(); - + void onSearchinText(); + void onSearchinProperty(); + void searchinToggle(bool on); + void onAttributeName (); // onFind helper functions - bool item_id_match (SPItem *item, const gchar *id, bool exact); - bool item_text_match (SPItem *item, const gchar *text, bool exact); - bool item_style_match (SPItem *item, const gchar *text, bool exact); - bool item_attr_match (SPItem *item, const gchar *name, bool exact); - GSList * filter_fields (GSList *l, bool exact); + bool item_id_match (SPItem *item, const gchar *id, bool exact, bool casematch, bool replace=false); + bool item_text_match (SPItem *item, const gchar *text, bool exact, bool casematch, bool replace=false); + bool item_style_match (SPItem *item, const gchar *text, bool exact, bool casematch, bool replace=false); + bool item_attr_match (SPItem *item, const gchar *name, bool exact, bool casematch, bool replace=false); + bool item_attrvalue_match (SPItem *item, const gchar *name, bool exact, bool casematch, bool replace=false); + bool item_font_match (SPItem *item, const gchar *name, bool exact, bool casematch, bool replace=false); + GSList * filter_fields (GSList *l, bool exact, bool casematch); bool item_type_match (SPItem *item); GSList * filter_types (GSList *l); - GSList * filter_list (GSList *l, bool exact); + GSList * filter_list (GSList *l, bool exact, bool casematch); GSList * all_items (SPObject *r, GSList *l, bool hidden, bool locked); GSList * all_selection_items (Inkscape::Selection *s, GSList *l, SPObject *ancestor, bool hidden, bool locked); @@ -86,9 +102,37 @@ private: Find(Find const &d); Find& operator=(Find const &d); - - Inkscape::UI::Widget::Button _button_clear; - Inkscape::UI::Widget::Button _button_find; + + Gtk::HBox _hbox_text; + Gtk::HBox _hbox_searchin; + Gtk::HBox _hbox_options; + Gtk::HBox _hbox_types; + Gtk::HBox _hbox_properties1; + Gtk::HBox _hbox_properties2; + Gtk::HBox _hbox_button_row; + Gtk::VBox _vbox_scope; + Gtk::VBox _vbox_searchin; + Gtk::VBox _vbox_options1; + Gtk::VBox _vbox_options2; + Gtk::VBox _vbox_properties; + Gtk::VBox _vbox_types1; + Gtk::VBox _vbox_types2; + Gtk::VBox _vbox_expander; + Gtk::Expander _expander_options; + + Gtk::Frame _frame_searchin; + Gtk::Frame _frame_scope; + Gtk::Frame _frame_options; + Gtk::Frame _frame_properties; + Gtk::Frame _frame_types; + + Gtk::Label _status; + Inkscape::UI::Widget::Button _button_find; + Inkscape::UI::Widget::Button _button_replace; + Gtk::HButtonBox _box_buttons; + + bool _action_replace; + }; } // namespace Dialog === modified file 'src/ui/widget/button.cpp' --- src/ui/widget/button.cpp 2011-10-27 04:55:51 +0000 +++ src/ui/widget/button.cpp 2012-01-02 07:17:22 +0000 @@ -25,12 +25,32 @@ _tooltips.set_tip(*this, tooltip); } + CheckButton::CheckButton(Glib::ustring const &label, Glib::ustring const &tooltip) : _tooltips() { set_use_underline (true); set_label (label); _tooltips.set_tip(*this, tooltip); + +} + +CheckButton::CheckButton(Glib::ustring const &label, Glib::ustring const &tooltip, bool checked) + : _tooltips() +{ + set_use_underline (true); + set_label (label); + _tooltips.set_tip(*this, tooltip); + set_active(checked); + +} + +RadioButton::RadioButton(Glib::ustring const &label, Glib::ustring const &tooltip) + : _tooltips() +{ + set_use_underline (true); + set_label (label); + _tooltips.set_tip(*this, tooltip); } } // namespace Widget === modified file 'src/ui/widget/button.h' --- src/ui/widget/button.h 2011-10-25 07:45:35 +0000 +++ src/ui/widget/button.h 2012-01-02 07:17:22 +0000 @@ -12,6 +12,7 @@ #include #include +#include #include namespace Inkscape { @@ -38,6 +39,19 @@ public: CheckButton(); CheckButton(Glib::ustring const &label, Glib::ustring const &tooltip); + CheckButton(Glib::ustring const &label, Glib::ustring const &tooltip, bool checked); +protected: + Gtk::Tooltips _tooltips; +}; + +/** + * RadioButtons widget. + */ +class RadioButton : public Gtk::RadioButton +{ +public: + RadioButton(); + RadioButton(Glib::ustring const &label, Glib::ustring const &tooltip); protected: Gtk::Tooltips _tooltips; }; === modified file 'src/ui/widget/entry.cpp' --- src/ui/widget/entry.cpp 2011-10-27 04:55:51 +0000 +++ src/ui/widget/entry.cpp 2012-01-02 07:17:22 +0000 @@ -24,7 +24,14 @@ : Labelled(label, tooltip, new Gtk::Entry(), suffix, icon, mnemonic) { } - + +ComboBoxEntryText::ComboBoxEntryText( Glib::ustring const &label, Glib::ustring const &tooltip, + Glib::ustring const &suffix, + Glib::ustring const &icon, + bool mnemonic) + : Labelled(label, tooltip, new Gtk::ComboBoxEntryText(), suffix, icon, mnemonic) +{ +} } // namespace Widget } // namespace UI === modified file 'src/ui/widget/entry.h' --- src/ui/widget/entry.h 2011-10-25 07:45:35 +0000 +++ src/ui/widget/entry.h 2012-01-02 07:17:22 +0000 @@ -15,6 +15,7 @@ #include #include #include "labelled.h" +#include namespace Inkscape { namespace UI { @@ -37,6 +38,26 @@ Gtk::Entry* getEntry() {return (Gtk::Entry*)(_widget);}; }; +class ComboBoxEntryText : public Labelled +{ +public: + ComboBoxEntryText( Glib::ustring const &label, + Glib::ustring const &tooltip, + Glib::ustring const &suffix = "", + Glib::ustring const &icon = "", + bool mnemonic = true); + + Gtk::ComboBoxEntryText* getWidget() { return (Gtk::ComboBoxEntryText *)_widget; }; + Gtk::Entry* getEntry() { return (Gtk::Entry *)getWidget()->get_child(); }; + Glib::ustring get_text() { return getEntry()->get_text(); }; + void prepend_text(const Glib::ustring& text) { getWidget()->prepend_text(text); }; + void append_text(const Glib::ustring& text) { getWidget()->append_text(text); }; + void insert_text(gint position, const Glib::ustring& text) { getWidget()->insert_text(position, text); }; + void remove_text(const Glib::ustring& text) { getWidget()->remove_text(text); }; + void clear_items() { getWidget()->clear_items(); }; + +}; + } // namespace Widget } // namespace UI } // namespace Inkscape === modified file 'src/verbs.cpp' --- src/verbs.cpp 2011-10-03 03:44:17 +0000 +++ src/verbs.cpp 2012-01-02 07:17:22 +0000 @@ -1818,9 +1818,9 @@ sp_xml_tree_dialog(); break; case SP_VERB_DIALOG_FIND: - sp_find_dialog(); + //sp_find_dialog(); // Please test the new find dialog if you have time: -// dt->_dlg_mgr->showDialog("Find"); + dt->_dlg_mgr->showDialog("Find"); break; case SP_VERB_DIALOG_FINDREPLACE: // not implemented yet