summaryrefslogtreecommitdiffstats
path: root/noatun-plugins/oblique/query.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit84da08d7b7fcda12c85caeb5a10b4903770a6f69 (patch)
tree2a6aea76f2dfffb4cc04bb907c4725af94f70e72 /noatun-plugins/oblique/query.cpp
downloadtdeaddons-84da08d7b7fcda12c85caeb5a10b4903770a6f69.tar.gz
tdeaddons-84da08d7b7fcda12c85caeb5a10b4903770a6f69.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeaddons@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'noatun-plugins/oblique/query.cpp')
-rw-r--r--noatun-plugins/oblique/query.cpp570
1 files changed, 570 insertions, 0 deletions
diff --git a/noatun-plugins/oblique/query.cpp b/noatun-plugins/oblique/query.cpp
new file mode 100644
index 0000000..292ff16
--- /dev/null
+++ b/noatun-plugins/oblique/query.cpp
@@ -0,0 +1,570 @@
+// Copyright (c) 2003 Charles Samuels <charles@kde.org>
+// See the file COPYING for redistribution terms.
+
+#include "query.h"
+#include "file.h"
+
+#include <iostream>
+
+#include <klocale.h>
+
+#include <qdom.h>
+#include <qfile.h>
+
+QueryGroup::QueryGroup()
+{
+ mFirstChild=0;
+ mNextSibling=0;
+
+ mFuzzyness = Case | Spaces | Articles;
+ mOptions = AutoHide;
+}
+
+QueryGroup::QueryGroup(const QueryGroup &copy)
+{
+ mFirstChild=0;
+ mNextSibling=0;
+
+ operator=(copy);
+
+}
+
+QueryGroup &QueryGroup::operator =(const QueryGroup &copy)
+{
+ mFuzzyness = copy.mFuzzyness;
+ mOptions = copy.mOptions;
+ mPropertyName = copy.mPropertyName;
+ mPresentation = copy.mPresentation;
+ mValue = copy.mValue;
+ return *this;
+}
+
+QueryGroup::~QueryGroup()
+{
+ delete mFirstChild;
+ delete mNextSibling;
+}
+
+void QueryGroup::insertAfter(QueryGroup *insert)
+{
+ QueryGroup *oldAfter = mNextSibling;
+ insert->setNextSibling(oldAfter);
+ setNextSibling(insert);
+}
+
+void QueryGroup::insertUnder(QueryGroup *insert)
+{
+ QueryGroup *oldUnder = mFirstChild;
+ insert->setNextSibling(oldUnder);
+ setFirstChild(insert);
+
+}
+
+void QueryGroup::move(Query *query, QueryGroup *under, QueryGroup *after)
+{
+ query->dump();
+
+ query->take(this);
+ if (after) after->insertAfter(this);
+ else if (under) under->insertUnder(this);
+ else query->insertFirst(this);
+
+ query->dump();
+}
+
+
+QueryGroup *QueryGroup::previous(Query *query)
+{
+ QueryGroup *f = query->firstChild();
+ if (f == this) return 0;
+
+ return previous(f);
+}
+
+QueryGroup *QueryGroup::previous(QueryGroup *startWith)
+{
+ QueryGroup *current = startWith;
+ QueryGroup *after = 0;
+
+ while (current)
+ {
+ after = current->nextSibling();
+ if (after == this)
+ return current;
+
+ if (QueryGroup *child = current->firstChild())
+ {
+ if (child == this)
+ return current;
+ child = previous(child);
+ if (child) return child;
+ }
+ current = after;
+ }
+ return 0;
+}
+
+
+
+QueryGroup *QueryGroup::lastChild()
+{
+ QueryGroup *first = mFirstChild;
+ if (!first) return 0;
+ while (first->nextSibling())
+ first = first->nextSibling();
+ return first;
+}
+
+
+bool QueryGroup::fuzzyness(Fuzzyness f) const
+{
+ return mFuzzyness & f;
+}
+
+bool QueryGroup::option(Option option) const
+{
+ return mOptions & option;
+}
+
+void QueryGroup::setOption(Option option, bool on)
+{
+ if (on)
+ mOptions |= option;
+ else
+ mOptions &= ~option;
+}
+
+bool QueryGroup::matches(const File &file) const
+{
+ QString prop = file.property(propertyName());
+
+ prop = prop.simplifyWhiteSpace();
+ if (prop.isNull()) prop = "";
+
+ QRegExp re(value());
+ return re.search(prop) != -1;
+}
+
+
+
+QString QueryGroup::presentation(const File &file) const
+{
+ // "$(property)"
+ QString format=presentation();
+
+ QRegExp find("(?:(?:\\\\\\\\))*\\$\\((.*)");
+
+ int start=0;
+ while (start != -1)
+ {
+ start = find.search(format, start);
+ if (start == -1) break;
+
+ // test if there's an odd amount of backslashes
+ if (start>0 && format[start-1]=='\\')
+ {
+ // yes, so half the amount of backslashes
+
+ // count how many there are first
+ QRegExp counter("([\\\\]+)");
+ counter.search(format, start-1);
+ uint len=counter.cap(1).length()-1;
+
+ // and half them, and remove one more
+ format.replace(start-1, len/2+1, "");
+ start=start-1+len/2+find.cap(1).length()+3;
+ continue;
+ }
+
+ // now replace the backslashes with half as many
+
+ if (format[start]=='\\')
+ {
+ // count how many there are first
+ QRegExp counter("([\\\\]+)");
+ counter.search(format, start);
+ uint len=counter.cap(1).length();
+
+ // and half them
+ format.replace(start, len/2, "");
+ start=start+len/2;
+ }
+
+ // "sth"foo"sth"
+ QString cont(find.cap(1));
+ QString prefix,suffix,propname;
+ unsigned int i=0;
+ if (cont[i] == '"')
+ {
+ i++;
+ for (; i < cont.length(); i++)
+ {
+ if (cont[i] != '"')
+ prefix += cont[i];
+ else
+ break;
+ }
+ i++;
+ }
+
+
+ for (; i < cont.length(); ++i)
+ {
+ if (cont[i]!='"' && cont[i]!=')')
+ propname += cont[i];
+ else
+ break;
+ }
+
+ if (cont[i] == '"')
+ {
+ i++;
+ for (; i < cont.length(); i++)
+ {
+ if (cont[i] != '"')
+ suffix += cont[i];
+ else
+ break;
+ }
+ i++;
+ }
+ i++;
+
+
+ QString propval = file.property(propname);
+
+// the following code won't be enabled until the presentation is reloaded
+// at the best times
+/* if (propname == "length")
+ {
+ int len = propval.toInt();
+ if ( len < 0 ) // no file loaded
+ propval = "--:--";
+
+ int secs = length()/1000; // convert milliseconds -> seconds
+ int seconds = secs % 60;
+ propval.sprintf("%.2d:%.2d", ((secs-seconds)/60), seconds);
+ }
+*/
+
+ if (propval.length())
+ {
+ propval = prefix+propval+suffix;
+ format.replace(start, i+2, propval);
+ start += propval.length();
+ }
+ else
+ {
+ format.replace(start, i+2, "");
+ }
+ }
+ return format;
+}
+
+
+Query::Query()
+{
+ mGroupFirst=0;
+}
+
+Query::~Query()
+{
+ delete mGroupFirst;
+}
+
+Query::Query(const Query &copy)
+{
+ mGroupFirst = 0;
+ operator=(copy);
+}
+
+Query &Query::operator =(const Query &copy)
+{
+ if (&copy == this) return *this;
+ delete mGroupFirst;
+ mGroupFirst=0;
+ if (const QueryGroup *parent = copy.firstChild())
+ {
+ mGroupFirst = new QueryGroup(*parent);
+ deepCopy(parent->firstChild(), mGroupFirst);
+ }
+ return *this;
+}
+
+QueryGroup *Query::firstChild()
+{
+ return mGroupFirst;
+}
+
+const QueryGroup *Query::firstChild() const
+{
+ return mGroupFirst;
+}
+
+void Query::setFirstChild(QueryGroup *g)
+{
+ mGroupFirst = g;
+}
+
+void Query::insertFirst(QueryGroup *g)
+{
+ g->setNextSibling(mGroupFirst);
+ mGroupFirst = g;
+}
+
+void Query::clear()
+{
+ delete mGroupFirst;
+ mGroupFirst=0;
+}
+
+QString Query::load(const QString &filename)
+{
+ QFile file(filename);
+ unless (file.open(IO_ReadOnly)) return QString::null;
+
+ QDomDocument doc;
+ doc.setContent(&file);
+ return load(doc.documentElement());
+}
+
+QString Query::load(QDomElement element)
+{
+ clear();
+
+ if (element.tagName().lower() == "obliqueschema")
+ {
+ QDomNode node = element.firstChild();
+
+ while (!node.isNull())
+ {
+ QDomElement e = node.toElement();
+ if (e.tagName().lower() == "group")
+ loadGroup(e);
+ node = node.nextSibling();
+ }
+ }
+ else
+ {
+ return QString::null;
+ }
+
+ // for internationalization:
+ // Add these if you create new schemas and release them with Oblique
+ (void)I18N_NOOP("Standard");
+
+ QString title = element.attribute("title");
+ if (element.hasAttribute("standard"))
+ title = i18n(title.utf8());
+ return title;
+}
+
+void Query::save(const QString &name, QDomElement &element)
+{
+ element.setTagName("ObliqueSchema");
+ element.setAttribute("version", "1.0");
+ element.setAttribute("title", name);
+ for (QueryGroup *g = firstChild(); g; g = g->nextSibling())
+ saveGroup(element, g);
+}
+
+void Query::save(const QString &name, const QString &filename)
+{
+ QFile file(filename);
+ unless (file.open(IO_Truncate|IO_ReadWrite ))
+ return;
+ QDomDocument doc("ObliqueSchema");
+ doc.setContent(QString("<!DOCTYPE ObliqueSchema><ObliqueSchema/>"));
+ QDomElement e = doc.documentElement();
+ save(name, e);
+
+ QTextStream ts(&file);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ // scourge elimination
+ QString data = doc.toString();
+ QString old = data;
+ while (data.replace(QRegExp("([\n\r]+)(\t*) "), "\\1\\2\t") != old)
+ {
+ old = data;
+ }
+ ts << data;
+}
+
+
+void Query::take(QueryGroup *item)
+{
+ QueryGroup *previous = item->previous(this);
+
+ if (!previous)
+ {
+ mGroupFirst = item->nextSibling();
+ item->setNextSibling(0);
+ return;
+ }
+
+ if (previous->nextSibling() == item)
+ {
+ previous->setNextSibling(item->nextSibling());
+ item->setNextSibling(0);
+ }
+ else if (previous->firstChild() == item)
+ {
+ previous->setFirstChild(item->nextSibling());
+ item->setNextSibling(0);
+ }
+}
+
+static void dump(QueryGroup *item, int depth)
+{
+ if (!item) return;
+
+ do
+ {
+ for (int d = 0; d < depth; d++)
+ std::cerr << " ";
+ std::cerr << "prop: " << item->propertyName().utf8() << " pres: "
+ << item->presentation().utf8() << std::endl;
+ dump(item->firstChild(), depth+1);
+
+ } while ((item = item->nextSibling()));
+
+}
+
+void Query::dump()
+{
+ ::dump(firstChild(), 0);
+}
+
+
+
+
+void Query::loadGroup(QDomElement element, QueryGroup *parent)
+{
+ QDomNode node = element.firstChild();
+
+ QueryGroup *group = new QueryGroup;
+ if (parent)
+ {
+ if (QueryGroup *last = parent->lastChild())
+ last->setNextSibling(group);
+ else
+ parent->setFirstChild(group);
+ }
+ else
+ {
+ mGroupFirst = group;
+ }
+
+ while (!node.isNull())
+ {
+ QDomElement e = node.toElement();
+ if (e.tagName().lower() == "group")
+ {
+ loadGroup(e, group);
+ }
+ else if (e.tagName().lower() == "property")
+ {
+ group->setPropertyName(e.text());
+ }
+ else if (e.tagName().lower() == "value")
+ {
+ group->setValue(QRegExp(e.text()));
+ }
+ else if (e.tagName().lower() == "presentation")
+ {
+ group->setPresentation(e.text());
+ }
+ else if (e.tagName().lower() == "options")
+ {
+ QDomNode node = e.firstChild();
+ while (!node.isNull())
+ {
+ QDomElement e = node.toElement();
+
+ if (e.tagName().lower() == "disabled")
+ group->setOption(QueryGroup::Disabled, true);
+ else if (e.tagName().lower() == "unique") // backwards compat (for now)
+ group->setOption(QueryGroup::Playable, true);
+ else if (e.tagName().lower() == "playable")
+ group->setOption(QueryGroup::Playable, true);
+ else if (e.tagName().lower() == "childrenvisible")
+ group->setOption(QueryGroup::ChildrenVisible, true);
+ else if (e.tagName().lower() == "autoopen")
+ group->setOption(QueryGroup::AutoOpen, true);
+
+ node = node.nextSibling();
+ }
+
+ }
+ node = node.nextSibling();
+ }
+}
+
+void Query::saveGroup(QDomElement &parent, QueryGroup *group)
+{
+ QDomDocument doc = parent.ownerDocument();
+ QDomElement element = doc.createElement("group");
+ parent.appendChild(element);
+
+ QDomElement childe;
+ QDomText childtext;
+ {
+ childe = doc.createElement("property");
+ element.appendChild(childe);
+ childtext = doc.createTextNode(group->propertyName());
+ childe.appendChild(childtext);
+ }
+ {
+ childe = doc.createElement("value");
+ element.appendChild(childe);
+ childtext = doc.createTextNode(group->value().pattern());
+ childe.appendChild(childtext);
+ }
+ {
+ childe = doc.createElement("presentation");
+ element.appendChild(childe);
+ childtext = doc.createTextNode(group->presentation());
+ childe.appendChild(childtext);
+ }
+ {
+ childe = doc.createElement("options");
+ element.appendChild(childe);
+ if (group->option(QueryGroup::Disabled))
+ childe.appendChild(doc.createElement("disabled"));
+ if (group->option(QueryGroup::Playable))
+ childe.appendChild(doc.createElement("playable"));
+ if (group->option(QueryGroup::ChildrenVisible))
+ childe.appendChild(doc.createElement("childrenvisible"));
+ if (group->option(QueryGroup::AutoOpen))
+ childe.appendChild(doc.createElement("autoopen"));
+ }
+
+ for (QueryGroup *c = group->firstChild(); c; c = c->nextSibling())
+ {
+ saveGroup(element, c);
+ }
+}
+
+void Query::deepCopy(const QueryGroup *from, QueryGroup *toParent)
+{
+ if (!from) return;
+ QueryGroup *last=0;
+
+ while (from)
+ {
+ QueryGroup *copy = new QueryGroup(*from);
+ if (last)
+ {
+ last->setNextSibling(copy);
+ last = copy;
+ }
+ else
+ {
+ toParent->setFirstChild(copy);
+ last = copy;
+ }
+ deepCopy(from->firstChild(), last);
+ from = from->nextSibling();
+ }
+}
+