summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah, Kamalpreet Grewal <>2016-07-25 13:40:59 +0000
committerkamalpreetgrewal <grewalkamal005@gmail.com>2016-07-25 13:40:59 +0000
commit6641c2e8c586612aad47e1296584ca6447e11b15 (patch)
treec4a59dec5624aebab6aee2f0b6f3902a9168a7da /src
parentMerge changes from trunk (diff)
downloadinkscape-6641c2e8c586612aad47e1296584ca6447e11b15.tar.gz
inkscape-6641c2e8c586612aad47e1296584ca6447e11b15.zip
Add robust implementation of _getSelectorVec()
(bzr r14949.1.60)
Diffstat (limited to 'src')
-rw-r--r--src/document.cpp54
-rw-r--r--src/document.h3
-rw-r--r--src/ui/dialog/styledialog.cpp141
3 files changed, 124 insertions, 74 deletions
diff --git a/src/document.cpp b/src/document.cpp
index 9f408788b..834d54132 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -1053,6 +1053,60 @@ sigc::connection SPDocument::connectIdChanged(gchar const *id,
return priv->id_changed_signals[g_quark_from_string(id)].connect(slot);
}
+void _getObjectsByClassRecursive(Glib::ustring const &klass, SPObject *parent, std::vector<SPObject *> &objects)
+{
+ if (parent) {
+ Glib::ustring class_attribute;
+ char const *temp = parent->getAttribute("class");
+ if (temp) {
+ class_attribute = temp;
+ }
+
+ if (class_attribute.find( klass ) != std::string::npos) {
+ objects.push_back( parent );
+ }
+
+ // Check children
+ for (SPObject *child = parent->children; child; child = child->next) {
+ _getObjectsByClassRecursive( klass, child, objects );
+ }
+ }
+}
+
+std::vector<SPObject *> SPDocument::getObjectsByClass(Glib::ustring const &klass) const
+{
+ std::vector<SPObject *> objects;
+ g_return_val_if_fail(!klass.empty(), objects);
+
+ _getObjectsByClassRecursive(klass, root, objects);
+ return objects;
+}
+
+void _getObjectsByElementRecursive(Glib::ustring const &element, SPObject *parent,
+ std::vector<SPObject *> &objects)
+{
+ if (parent) {
+ Glib::ustring prefixed = "svg:" + element;
+ if (parent->getRepr()->name() == prefixed) {
+ objects.push_back(parent);
+ }
+
+ // Check children
+ for (SPObject *child = parent->children; child; child = child->next) {
+ _getObjectsByElementRecursive(element, child, objects);
+ }
+ }
+}
+
+std::vector<SPObject *> SPDocument::getObjectsByElement(Glib::ustring const &element) const
+{
+ std::vector<SPObject *> objects;
+ g_return_val_if_fail(!element.empty(), objects);
+
+ _getObjectsByElementRecursive(element, root, objects);
+ return objects;
+}
+
void SPDocument::bindObjectToRepr(Inkscape::XML::Node *repr, SPObject *object)
{
if (object) {
diff --git a/src/document.h b/src/document.h
index 813d4ae49..49bde1897 100644
--- a/src/document.h
+++ b/src/document.h
@@ -179,6 +179,9 @@ public:
SPObject *getObjectById(char const *id) const;
sigc::connection connectIdChanged(const char *id, IDChangedSignal::slot_type slot);
+ std::vector<SPObject *> getObjectsByClass(Glib::ustring const &klass) const;
+ std::vector<SPObject *> getObjectsByElement(Glib::ustring const &element) const;
+
void bindObjectToRepr(Inkscape::XML::Node *repr, SPObject *object);
SPObject *getObjectByRepr(Inkscape::XML::Node *repr) const;
diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp
index 1004fa151..259f326e4 100644
--- a/src/ui/dialog/styledialog.cpp
+++ b/src/ui/dialog/styledialog.cpp
@@ -425,95 +425,88 @@ std::string StyleDialog::_setClassAttribute(std::vector<SPObject*> sel)
*/
std::vector<StyleDialog::InkSelector> StyleDialog::_getSelectorVec()
{
- std::string key, value, selId;
for (unsigned i = 0; i < _document->getReprRoot()->childCount(); ++i) {
if (std::string(_document->getReprRoot()->nthChild(i)->name()) == "svg:style") {
_styleExists = true;
_newDrawing = false;
_styleChild = _document->getReprRoot()->nthChild(i);
- std::stringstream str;
- str << _document->getReprRoot()->nthChild(i)->firstChild()->content();
- std::string sel;
- /**
- * If a selector without any style attribute content is added, the
- * value is set to empty so that its corresponding XML repr is added.
- */
- while(std::getline(str, sel, '\n')) {
+ // Get content from first style element.
+ std::string content = _styleChild->firstChild()->content();
+
+ // Remove end-of-lines (check it works on Windoze).
+ content.erase(std::remove(content.begin(), content.end(), '\n'), content.end());
+
+ // First split into selector/value chunks.
+ // An attempt to use Glib::Regex failed. A C++11 version worked but
+ // reportedly has problems on Windows. Using split_simple() is simpler
+ // and probably faster.
+ //
+ // Glib::RefPtr<Glib::Regex> regex1 =
+ // Glib::Regex::create("([^\\{]+)\\{([^\\{]+)\\}");
+ //
+ // Glib::MatchInfo minfo;
+ // regex1->match(content, minfo);
+
+ // Split on curly brackets. Even tokens are selectors, odd are values.
+ std::vector<std::string> tokens = Glib::Regex::split_simple("[}{]", content);
+
+ for (unsigned i = 0; i < tokens.size()-1; i += 2) {
+ std::string selectors = tokens[i];
+ REMOVE_SPACES(selectors); // Remove leading/trailing spaces
+
+ /** Make a list of all objects that selector matches. This is
+ * currently limited to simple id, class, and element selectors.
+ * Expanding this would take integrating a true CSS parser.
+ */
std::vector<SPObject *>objVec;
- REMOVE_SPACES(sel);
- if (!sel.empty()) {
- key = strtok((char*)sel.c_str(), "{");
- _selectorName = key;
- char *temp = strtok(NULL, "}");
- if (strtok(temp, "}") != NULL) {
- value = strtok(temp, "}");
- }
- std::stringstream ss(key);
- std::string token;
- std::size_t found = key.find(",");
- if (found!=std::string::npos) {
- while(std::getline(ss, token, ',')) {
- REMOVE_SPACES(token);
+ // Split selector string into individual selectors (which are comma separated).
+ std::vector<std::string> tokens2 = Glib::Regex::split_simple
+ ("\\s*,\\s*", selectors );
- if (token[0] == '.') {
- token.erase(0, token.find_first_not_of('.'));
- for (unsigned i = 0; i < _document->getReprRoot()
- ->childCount(); ++i) {
- if (_document->getReprRoot()->
- nthChild(i)->attribute("class") &&
- _document->getReprRoot()->nthChild(i)
- ->attribute("class") == token) {
- selId = _document->getReprRoot()->nthChild(i)
- ->attribute("id");
- objVec.push_back( _document->getObjectById(selId));
- }
- }
- }
- else if (token[0] == '#') {
- token.erase(0, token.find_first_not_of('#'));
- selId = token;
- objVec.push_back(_document->getObjectById(selId));
- }
- else {
- std::cout << "simple text" << std::endl;
- }
+ for(unsigned i = 0; i < tokens2.size(); ++i) {
+ std::string token2 = tokens2[i];
+
+ // Find objects that match class selector
+ if (token2[0] == '.') {
+ token2.erase(0,1);
+ std::vector<SPObject *> objects = _document
+ ->getObjectsByClass(token2);
+ objVec.insert(objVec.end(), objects.begin(), objects.end());
+ }
+
+ // Find objects that match id selector
+ else if (token2[0] == '#') {
+ token2.erase(0,1);
+ SPObject * object = _document->getObjectById(token2);
+ if (object) {
+ objVec.push_back(object);
}
}
+
+ // Find objects that match element selector
else {
- REMOVE_SPACES(key);
- std::string tkn = key;
- if (tkn[0] == '.') {
- tkn.erase(0, tkn.find_first_not_of('.'));
- for (unsigned i = 0; i < _document->getReprRoot()
- ->childCount(); ++i) {
- if (_document->getReprRoot()->
- nthChild(i)->attribute("class") &&
- _document->getReprRoot()->nthChild(i)
- ->attribute("class") == tkn) {
- selId = _document->getReprRoot()->nthChild(i)
- ->attribute("id");
- objVec.push_back(_document->getObjectById(selId));
- }
- }
- }
- else if (tkn[0] == '#') {
- tkn.erase(0, key.find_first_not_of('#'));
- selId = tkn;
- objVec.push_back(_document->getObjectById(selId));
- }
- else {
- std::cout << "simple text" << std::endl;
- }
+ std::vector<SPObject *> objects = _document->
+ getObjectsByElement(token2);
+ objVec.insert(objVec.end(), objects.begin(), objects.end());
}
- _selectorValue = _selectorName + "{" + value + "}\n";
+ }
- inkSelector._selector = key;
- inkSelector._matchingObjs = objVec;
- inkSelector._xmlContent = _selectorValue;
- _selectorVec.push_back(inkSelector);
+ std::string values;
+ // Check to make sure we do have a value to match selector.
+ if ((i+1) < tokens.size()) {
+ values = tokens[i+1];
+ } else {
+ std::cerr << "StyleDialog::_getSelectorVec: Missing values "
+ "for last selector!" << std::endl;
}
+
+ _selectorValue = selectors + "{" + values + "}\n";
+ inkSelector._selector = selectors;
+ inkSelector._matchingObjs = objVec;
+ inkSelector._xmlContent = _selectorValue;
+ _selectorVec.push_back(inkSelector);
}
}
}