summaryrefslogtreecommitdiffstats
path: root/src/ui/dialog/styledialog.cpp
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/ui/dialog/styledialog.cpp
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/ui/dialog/styledialog.cpp')
-rw-r--r--src/ui/dialog/styledialog.cpp141
1 files changed, 67 insertions, 74 deletions
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);
}
}
}