summaryrefslogtreecommitdiffstats
path: root/src/ui/dialog/find.cpp
diff options
context:
space:
mode:
authorJohn Smith <john.smith7545@yahoo.com>2012-03-23 02:53:58 +0000
committerJohn Smith <removethis.john.q.public@bigmail.com>2012-03-23 02:53:58 +0000
commit924e671a1e5d76c1d25d4fcad9d0e9f015dc394e (patch)
treeb5edc420bece6f3a7227bdb1009af3fea51388b9 /src/ui/dialog/find.cpp
parentUI. Patch for Bug #666370 (Not all units in the Object Transform dialog are t... (diff)
downloadinkscape-924e671a1e5d76c1d25d4fcad9d0e9f015dc394e.tar.gz
inkscape-924e671a1e5d76c1d25d4fcad9d0e9f015dc394e.zip
Fix for 909328 : Dockable Find & Replace dialog
(bzr r11117)
Diffstat (limited to 'src/ui/dialog/find.cpp')
-rw-r--r--src/ui/dialog/find.cpp898
1 files changed, 661 insertions, 237 deletions
diff --git a/src/ui/dialog/find.cpp b/src/ui/dialog/find.cpp
index 9d3508c53..1652fbb16 100644
--- a/src/ui/dialog/find.cpp
+++ b/src/ui/dialog/find.cpp
@@ -24,12 +24,14 @@
#include "inkscape.h"
#include "desktop.h"
#include "document.h"
+#include "document-undo.h"
#include "selection.h"
#include "desktop-handles.h"
#include "dialogs/dialog-events.h"
#include "verbs.h"
#include "interface.h"
+#include "preferences.h"
#include "sp-text.h"
#include "sp-flowtext.h"
#include "text-editing.h"
@@ -50,6 +52,8 @@
#include "sp-offset.h"
#include "sp-root.h"
#include "xml/repr.h"
+#include "xml/node-iterators.h"
+#include "xml/attribute-record.h"
#include <glibmm/i18n.h>
@@ -59,112 +63,278 @@ namespace Dialog {
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")),
- _check_clones(
+
+ 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")),
+ frame_searchin(_("Search in")),
+ frame_scope(_("Scope")),
+
+
+ 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),
+ expander_options(_("Options")),
+ frame_options(_("General")),
+
+ 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),
+ frame_properties(_("Properties")),
+
+ check_alltypes(_("All types"), _("Search all object types"), 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),
+ frame_types(_("Object Types")),
+
+ status(""),
+ button_find(_("_Find"), _("Select all objects matching the selected fields ")),
+ button_replace(_("_Replace All"), _("Replace all the matching objects")),
+ _action_replace(false),
+ blocked(false),
+ desktop(NULL),
+ deskTrack()
+
{
+ 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, 0);
+ vbox_properties.pack_start(hbox_properties2, true, true, 2);
+ 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);
+ hboxbutton_row.pack_start(status, true, true, 6);
+ hboxbutton_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(expander_options, false, false);
+ contents->pack_end(hboxbutton_row, false, false);
+
+ checkProperties.push_back(&check_ids);
+ checkProperties.push_back(&check_style);
+ checkProperties.push_back(&check_font);
+ checkProperties.push_back(&check_attributevalue);
+ checkProperties.push_back(&check_attributename);
+
+ checkTypes.push_back(&check_paths);
+ checkTypes.push_back(&check_texts);
+ checkTypes.push_back(&check_groups);
+ checkTypes.push_back(&check_clones);
+ checkTypes.push_back(&check_images);
+ checkTypes.push_back(&check_offsets);
+ checkTypes.push_back(&check_rects);
+ checkTypes.push_back(&check_ellipses);
+ checkTypes.push_back(&check_stars);
+ checkTypes.push_back(&check_spirals);
+ checkTypes.push_back(&check_offsets);
// 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));
- _button_find.signal_clicked().connect(sigc::mem_fun(*this, &Find::onFind));
+ 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_searchin_text.signal_clicked().connect(sigc::mem_fun(*this, &Find::onSearchinText));
+ check_searchin_property.signal_clicked().connect(sigc::mem_fun(*this, &Find::onSearchinProperty));
+ check_alltypes.signal_clicked().connect(sigc::mem_fun(*this, &Find::onToggleAlltypes));
+
+ for(size_t i = 0; i < checkProperties.size(); i++) {
+ checkProperties[i]->signal_clicked().connect(sigc::mem_fun(*this, &Find::onToggleCheck));
+ }
+
+ for(size_t i = 0; i < checkTypes.size(); i++) {
+ checkTypes[i]->signal_clicked().connect(sigc::mem_fun(*this, &Find::onToggleCheck));
+ }
+
+ onSearchinText();
+ onToggleAlltypes();
- _button_find.set_can_default();
- // set_default (_button_find); // activatable by Enter
- _entry_text.getEntry()->grab_focus();
+ desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &Find::setTargetDesktop) );
+ deskTrack.connect(GTK_WIDGET(gobj()));
show_all_children();
- onClear();
+
+ Inkscape::Selection *selection = sp_desktop_selection (SP_ACTIVE_DESKTOP);
+ SPItem *item = selection->singleItem();
+ if (item) {
+ if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
+ gchar *str;
+ str = sp_te_get_string_multiline (item);
+ entry_find.getEntry()->set_text(str);
+ }
+ }
+
+ button_find.set_can_default();
+ //button_find.grab_default(); // activatable by Enter
+ entry_find.getEntry()->grab_focus();
+}
+
+Find::~Find()
+{
+ desktopChangeConn.disconnect();
+ selectChangedConn.disconnect();
+ deskTrack.disconnect();
}
-Find::~Find()
+void Find::setDesktop(SPDesktop *desktop)
{
+ Panel::setDesktop(desktop);
+ deskTrack.setBase(desktop);
+}
+
+void Find::setTargetDesktop(SPDesktop *desktop)
+{
+ if (this->desktop != desktop) {
+ if (this->desktop) {
+ selectChangedConn.disconnect();
+ }
+ this->desktop = desktop;
+ if (desktop && desktop->selection) {
+ selectChangedConn = desktop->selection->connectChanged(sigc::hide(sigc::mem_fun(*this, &Find::onSelectionChange)));
+ }
+ }
}
+void Find::onSelectionChange(void)
+{
+ if (!blocked) {
+ status.set_text("");
+ }
+}
/*########################################################################
# FIND helper functions
########################################################################*/
-
-bool
-Find::item_id_match (SPItem *item, const gchar *id, bool exact)
+Glib::ustring Find::find_replace(const gchar *str, const gchar *find, const gchar *replace, bool exact, bool casematch, bool replaceall)
{
- if (item->getRepr() == NULL) {
- return false;
+ Glib::ustring ustr = str;
+ Glib::ustring ufind = find;
+ if (!casematch) {
+ ufind = ufind.lowercase();
}
-
- if (SP_IS_STRING(item)) { // SPStrings have "on demand" ids which are useless for searching
- return false;
+ gsize n = find_strcmp_pos(ustr.c_str(), ufind.c_str(), exact, casematch);
+ while (n != std::string::npos) {
+ ustr.replace(n, ufind.length(), replace);
+ if (!replaceall) {
+ return ustr;
+ }
+ // Start the next search after the last replace character to avoid infinite loops (replace "a" with "aaa" etc)
+ n = find_strcmp_pos(ustr.c_str(), ufind.c_str(), exact, casematch, n + strlen(replace) + 1);
}
+ return ustr;
+}
- const gchar *item_id = item->getRepr()->attribute("id");
- if (item_id == NULL) {
- return false;
+gsize Find::find_strcmp_pos(const gchar *str, const gchar *find, bool exact, bool casematch, gsize start/*=0*/)
+{
+ Glib::ustring ustr = str;
+ Glib::ustring ufind = find;
+
+ if (!casematch) {
+ ustr = ustr.lowercase();
+ ufind = ufind.lowercase();
}
+ gsize pos = std::string::npos;
if (exact) {
- return ((bool) !strcmp(item_id, id));
+ if (ustr == ufind) {
+ pos = 0;
+ }
} 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));
+ pos = ustr.find(ufind, start);
}
+
+ return pos;
+}
+
+
+bool Find::find_strcmp(const gchar *str, const gchar *find, bool exact, bool casematch)
+{
+ return (std::string::npos != find_strcmp_pos(str, find, exact, casematch));
}
bool
-Find::item_text_match (SPItem *item, const gchar *text, bool exact)
+Find::item_text_match (SPItem *item, const gchar *find, bool exact, bool casematch, bool replace/*=false*/)
{
if (item->getRepr() == NULL) {
return false;
@@ -172,111 +342,317 @@ Find::item_text_match (SPItem *item, const gchar *text, bool exact)
if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
const gchar *item_text = sp_te_get_string_multiline (item);
- if (item_text == NULL)
+ if (item_text == NULL) {
return false;
- bool ret;
- if (exact) {
- ret = ((bool) !strcasecmp(item_text, text));
- } else {
- //FIXME: strcasestr
- ret = ((bool) (strstr(item_text, text) != NULL));
}
- g_free ((void*) item_text);
- return ret;
+ bool found = find_strcmp(item_text, find, exact, casematch);
+
+ if (found && replace) {
+ Glib::ustring ufind = find;
+ if (!casematch) {
+ ufind = ufind.lowercase();
+ }
+
+ Inkscape::Text::Layout const *layout = te_get_layout (item);
+ if (!layout) {
+ return found;
+ }
+
+ gchar* replace_text = g_strdup(entry_replace.get_text().c_str());
+ gsize n = find_strcmp_pos(item_text, ufind.c_str(), exact, casematch);
+ static Inkscape::Text::Layout::iterator _begin_w;
+ static Inkscape::Text::Layout::iterator _end_w;
+ while (n != std::string::npos) {
+ _begin_w = layout->charIndexToIterator(n);
+ _end_w = layout->charIndexToIterator(n + strlen(find));
+ sp_te_replace(item, _begin_w, _end_w, replace_text);
+ item_text = sp_te_get_string_multiline (item);
+ n = find_strcmp_pos(item_text, ufind.c_str(), exact, casematch, n + strlen(replace_text) + 1);
+ }
+
+ g_free(replace_text);
+ }
+
+ return found;
}
return false;
}
+
+bool
+Find::item_id_match (SPItem *item, const gchar *id, bool exact, bool casematch, bool replace/*=false*/)
+{
+ if (item->getRepr() == NULL) {
+ return false;
+ }
+
+ if (SP_IS_STRING(item)) { // SPStrings have "on demand" ids which are useless for searching
+ return false;
+ }
+
+ const gchar *item_id = item->getRepr()->attribute("id");
+ if (item_id == NULL) {
+ return false;
+ }
+
+ bool found = find_strcmp(item_id, id, exact, casematch);
+
+ if (found && replace) {
+ gchar * replace_text = g_strdup(entry_replace.get_text().c_str());
+ Glib::ustring new_item_style = find_replace(item_id, id, replace_text , exact, casematch, true);
+ if (new_item_style != item_id) {
+ item->getRepr()->setAttribute("id", new_item_style.data());
+ }
+ g_free(replace_text);
+ }
+
+ return found;
+}
+
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) {
+ gchar *item_style = g_strdup(item->getRepr()->attribute("style"));
+ if (item_style == NULL) {
return false;
}
+ bool found = find_strcmp(item_style, text, exact, casematch);
+
+ if (found && replace) {
+ gchar * replace_text = g_strdup(entry_replace.get_text().c_str());
+ Glib::ustring new_item_style = find_replace(item_style, text, replace_text , exact, casematch, true);
+ if (new_item_style != item_style) {
+ item->getRepr()->setAttribute("style", new_item_style.data());
+ }
+ g_free(replace_text);
+ }
+
+ g_free(item_style);
+ return found;
+}
+
+bool Find::item_attr_match(SPItem *item, const gchar *text, bool exact, bool casematch, bool replace/*=false*/)
+{
+ bool found = false;
+
+ if (item->getRepr() == NULL) {
+ return false;
+ }
+
+ gchar *attr_value = g_strdup(item->getRepr()->attribute(text));
if (exact) {
- return ((bool) !strcmp(item_text, text));
+ found = (attr_value != NULL);
} else {
- return ((bool) (strstr(item_text, text) != NULL));
+ found = item->getRepr()->matchAttributeName(text);
+ }
+ g_free(attr_value);
+
+ // TODO - Rename attribute name ?
+ if (found && replace) {
+ found = false;
}
+
+ return found;
}
-bool Find::item_attr_match(SPItem *item, const gchar *name, bool exact)
+bool Find::item_attrvalue_match(SPItem *item, const gchar *text, bool exact, bool casematch, bool replace/*=false*/)
{
- bool result = false;
- if (item->getRepr()) {
- if (exact) {
- const gchar *attr_value = item->getRepr()->attribute(name);
- result = (attr_value != NULL);
- } else {
- result = item->getRepr()->matchAttributeName(name);
+ bool ret = false;
+
+ if (item->getRepr() == NULL) {
+ return false;
+ }
+
+ Inkscape::Util::List<Inkscape::XML::AttributeRecord const> iter = item->getRepr()->attributeList();
+ for (; iter; ++iter) {
+ const gchar* key = g_quark_to_string(iter->key);
+ gchar *attr_value = g_strdup(item->getRepr()->attribute(key));
+ bool found = find_strcmp(attr_value, text, exact, casematch);
+ if (found) {
+ ret = true;
+ }
+
+ if (found && replace) {
+ gchar * replace_text = g_strdup(entry_replace.get_text().c_str());
+ Glib::ustring new_item_style = find_replace(attr_value, text, replace_text , exact, casematch, true);
+ if (new_item_style != attr_value) {
+ item->getRepr()->setAttribute(key, new_item_style.data());
+ }
+ }
+
+ g_free(attr_value);
+ }
+
+ return ret;
+}
+
+
+bool Find::item_font_match(SPItem *item, const gchar *text, bool exact, bool casematch, bool replace/*=false*/)
+{
+ bool ret = false;
+
+ if (item->getRepr() == NULL) {
+ return false;
+ }
+
+ const gchar *item_style = item->getRepr()->attribute("style");
+ if (item_style == NULL) {
+ return false;
+ }
+
+ std::vector<Glib::ustring> vFontTokenNames;
+ vFontTokenNames.push_back("font-family:");
+ vFontTokenNames.push_back("-inkscape-font-specification:");
+
+ std::vector<Glib::ustring> vStyleTokens = Glib::Regex::split_simple(";", item_style);
+ for(size_t i=0; i<vStyleTokens.size(); i++) {
+ Glib::ustring token = vStyleTokens[i];
+ for(size_t j=0; j<vFontTokenNames.size(); j++) {
+ if ( token.find(vFontTokenNames[j]) != std::string::npos) {
+ Glib::ustring font1 = Glib::ustring(vFontTokenNames[j]).append(text);
+ bool found = find_strcmp(token.c_str(), font1.c_str(), exact, casematch);
+ if (found) {
+ ret = true;
+ if (_action_replace) {
+ gchar *replace_text = g_strdup(entry_replace.get_text().c_str());
+ gchar *orig_str = g_strdup(token.c_str());
+ // Exact match fails since the "font-family:" is in the token, since the find was exact it still works with false below
+ Glib::ustring new_item_style = find_replace(orig_str, text, replace_text , false /*exact*/, casematch, true);
+ if (new_item_style != orig_str) {
+ vStyleTokens.at(i) = new_item_style;
+ }
+ g_free(orig_str);
+ g_free(replace_text);
+ }
+ }
+ }
+ }
+ }
+
+ if (ret && _action_replace) {
+ Glib::ustring new_item_style;
+ for(size_t i=0; i<vStyleTokens.size(); i++) {
+ new_item_style.append(vStyleTokens.at(i)).append(";");
}
+ new_item_style.erase(new_item_style.size()-1);
+ item->getRepr()->setAttribute("style", new_item_style.data());
}
- return result;
+
+ 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();
-
+ Glib::ustring tmp = entry_find.get_text();
+ if (tmp.empty()) {
+ return l;
+ }
+ gchar* text = g_strdup(tmp.c_str());
+
GSList *in = l;
GSList *out = NULL;
- if (strlen (text) != 0) {
+
+ 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)) {
- out = g_slist_prepend (out, i->data);
+ 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 {
- 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 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);
+ }
+ }
+ }
}
}
- } 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);
+
+ 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);
+ }
+ }
+ }
}
}
- } 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);
+
+ 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);
+ }
+ }
+ }
}
}
- } else {
- out = in;
+
+
+ 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);
+ }
+ }
+ }
+ }
+ }
+
}
+ g_free(text);
+
return out;
}
@@ -284,37 +660,37 @@ Find::filter_fields (GSList *l, bool exact)
bool
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;
@@ -323,8 +699,6 @@ Find::item_type_match (SPItem *item)
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))) {
@@ -336,18 +710,16 @@ Find::filter_types (GSList *l)
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;
}
GSList *
Find::all_items (SPObject *r, GSList *l, bool hidden, bool locked)
{
- SPDesktop *desktop = getDesktop();
-
if (SP_IS_DEFS(r)) {
return l; // we're not interested in items in defs
}
@@ -371,8 +743,6 @@ Find::all_items (SPObject *r, GSList *l, bool hidden, bool locked)
GSList *
Find::all_selection_items (Inkscape::Selection *s, GSList *l, SPObject *ancestor, bool hidden, bool locked)
{
- SPDesktop *desktop = getDesktop();
-
for (GSList *i = (GSList *) s->itemList(); i != NULL; i = i->next) {
if (SP_IS_ITEM (i->data) && !reinterpret_cast<SPItem *>(i->data)->cloned && !desktop->isLayer(SP_ITEM(i->data))) {
SPItem *item = reinterpret_cast<SPItem *>(i->data);
@@ -388,43 +758,67 @@ Find::all_selection_items (Inkscape::Selection *s, GSList *l, SPObject *ancestor
}
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();
+Find::onFind()
+{
+ _action_replace = false;
+ onAction();
+
+ // Return focus to the find entry
+ entry_find.getEntry()->grab_focus();
}
-
-
void
-Find::onFind()
-{
- SPDesktop *desktop = getDesktop();
+Find::onReplace()
+{
+ if (entry_find.get_text().length() < 1) {
+ status.set_text(_("Nothing to replace"));
+ return;
+ }
+ _action_replace = true;
+ onAction();
+
+ // Return focus to the find entry
+ entry_find.getEntry()->grab_focus();
+}
- bool hidden = _check_include_hidden.get_active();
- bool locked = _check_include_locked.get_active();
+void
+Find::onAction()
+{
+
+ 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();
+ blocked = true;
+
+ // Add find/replace text to combobox list
+ if (entry_find.get_text().length() > 0) {
+ entry_find.remove_text(entry_find.get_text());
+ entry_find.prepend_text(entry_find.get_text());
+ }
+
+ if (_action_replace && entry_replace.get_text().length() > 0) {
+ entry_replace.remove_text(entry_replace.get_text());
+ entry_replace.prepend_text(entry_replace.get_text());
+ }
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);
@@ -432,13 +826,7 @@ Find::onFind()
}
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);
@@ -448,88 +836,124 @@ Find::onFind()
"<b>%d</b> objects found (out of <b>%d</b>), %s match.",
count),
count, all, exact? _("exact") : _("partial"));
+ status.set_text(Glib::ustring::compose("%1 %2 %3", count, _("objects"), _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(desktop), SP_VERB_CONTEXT_TEXT, _("Text Replace"));
+ }
+
} else {
+ status.set_text(_("Not found"));
+ if (!check_scope_selection.get_active()) {
+ Inkscape::Selection *selection = sp_desktop_selection (desktop);
+ selection->clear();
+ }
desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No objects found"));
}
+ blocked = false;
+
+}
+void
+Find::onToggleCheck ()
+{
+ bool objectok = false;
+ status.set_text("");
+
+ if (check_alltypes.get_active()) {
+ objectok = true;
+ }
+ for(int i = 0; i < 11; i++) {
+ if (checkTypes[i]->get_active()) {
+ objectok = true;
+ }
+ }
+
+ if (!objectok) {
+ status.set_text(_("Select an object"));
+ }
+
+
+ bool propertyok = false;
+
+ if (!check_searchin_property.get_active()) {
+ propertyok = true;
+ } else {
+
+ for(size_t i = 0; i < checkProperties.size(); i++) {
+ if (checkProperties[i]->get_active()) {
+ propertyok = true;
+ }
+ }
+ }
+
+ if (!propertyok) {
+ status.set_text(_("Select a property"));
+ }
+
+ // Can't replace attribute names
+ bool attributenameyok = !check_attributename.get_active();
+
+ button_find.set_sensitive(objectok && propertyok);
+ button_replace.set_sensitive(objectok && propertyok && attributenameyok);
+
}
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();
+ bool all =check_alltypes.get_active();
+ for(size_t i = 0; i < checkTypes.size(); i++) {
+ checkTypes[i]->set_sensitive(!all);
+ }
+
+ onToggleCheck();
}
void
-Find::onToggleShapes ()
+Find::onSearchinText ()
{
- 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();
+ searchinToggle(false);
+ onToggleCheck();
}
+void
+Find::onSearchinProperty ()
+{
+ searchinToggle(true);
+ onToggleCheck();
+}
+
+void
+Find::searchinToggle(bool on)
+{
+ for(size_t i = 0; i < checkProperties.size(); i++) {
+ checkProperties[i]->set_sensitive(on);
+ }
+}
+
+void
+Find::onExpander ()
+{
+ if (!expander_options.get_expanded())
+ squeeze_window();
+}
/*########################################################################
# UTILITY
########################################################################*/
-
-
void
Find::squeeze_window()
{
- // TO DO: make window as small as possible
+ // TODO: resize dialog window when the expander is closed
+ // set_size_request(-1, -1);
}
-
-
} // namespace Dialog
} // namespace UI
} // namespace Inkscape