[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    extragear/multimedia/kmplayer
From:       Koos Vriezen <koos.vriezen () gmail ! com>
Date:       2009-08-31 21:32:57
Message-ID: 1251754377.259868.17338.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 1017918 by vriezen:

Add support for setting and reading state attributes

 M  +85 -48    src/expression.cpp  
 M  +17 -1     src/expression.h  
 M  +29 -12    src/kmplayer_smil.cpp  
 M  +16 -0     tests/state.smil  


--- trunk/extragear/multimedia/kmplayer/src/expression.cpp #1017917:1017918
@@ -27,18 +27,25 @@
 
 using namespace KMPlayer;
 
+QString NodeValue::value () const {
+    if (attr)
+        return attr->value ();
+    return node->nodeValue ();
+}
+
 namespace {
 
 struct EvalState {
     EvalState (EvalState *p)
-     : root (NULL), process_list (NULL), parent (p),
+     : root (NULL), attr (NULL), process_list (NULL), parent (p),
        sequence (1), ref_count (0) {}
 
     void addRef () { ++ref_count; }
     void removeRef () { if (--ref_count == 0) delete this; }
 
     Node *root;
-    NodeRefList *process_list;
+    Attribute *attr;
+    NodeValueList *process_list;
     EvalState *parent;
     int sequence;
     int ref_count;
@@ -56,9 +63,10 @@
     virtual int toInt () const;
     virtual float toFloat () const;
     virtual QString toString () const;
-    virtual NodeRefList *toNodeList () const;
+    virtual NodeValueList *toNodeList () const;
     virtual Type type () const;
     virtual void setRoot (Node *root);
+    void setRoot (Node *root, Attribute *a);
 #ifdef KMPLAYER_EXPR_DEBUG
     virtual void dump () const;
 #endif
@@ -135,21 +143,24 @@
 };
 
 struct Step : public StringBase {
-    Step (EvalState *ev) : StringBase (ev), any_path (false) {}
-    Step (EvalState *ev, const char *s, const char *e)
-     : StringBase (ev, s, e), any_path (string == "*") {}
+    Step (EvalState *ev) : StringBase (ev), any_node (false), is_attr (false) {}
+    Step (EvalState *ev, const char *s, const char *e, bool isattr=false)
+     : StringBase (ev, s, e), any_node (string == "*"), is_attr (isattr) {}
 
     bool matches (Node *n);
-    bool selected (Node *n);
+    bool matches (Attribute *a);
+    bool selected (Node *n, Attribute *a);
     bool anyPath () const { return string.isEmpty (); }
 #ifdef KMPLAYER_EXPR_DEBUG
     virtual void dump () const {
-        fprintf (stderr, "Step %s", string.toAscii ().data ());
+        fprintf (stderr, "Step %c%s",
+                is_attr ? '@' : ' ',string.toAscii ().data ());
         AST::dump();
     }
 #endif
 
-    bool any_path;
+    bool any_node;
+    bool is_attr;
 };
 
 struct Identifier : public StringBase {
@@ -159,9 +170,8 @@
 
     virtual bool toBool () const;
     virtual QString toString () const;
-    virtual NodeRefList *toNodeList () const;
+    virtual NodeValueList *toNodeList () const;
     virtual Type type () const;
-    bool childByPath (Node *node, Step *path, NodeRefList *lst) const;
     void childByStep (Step *step, bool recurse) const;
     void childByPath (Step *step, bool recurse) const;
 #ifdef KMPLAYER_EXPR_DEBUG
@@ -364,8 +374,8 @@
     }
 }
 
-NodeRefList *AST::toNodeList () const {
-    return new NodeRefList;
+NodeValueList *AST::toNodeList () const {
+    return new NodeValueList;
 }
 
 AST::Type AST::type () const {
@@ -374,9 +384,15 @@
 
 void AST::setRoot (Node *root) {
     eval_state->root = root;
+    eval_state->attr = NULL;
     eval_state->sequence++;
 }
 
+void AST::setRoot (Node *root, Attribute *a) {
+    setRoot (root);
+    eval_state->attr = a;
+}
+
 #ifdef KMPLAYER_EXPR_DEBUG
 void AST::dump () const {
     if (first_child) {
@@ -422,13 +438,13 @@
 bool NumberBase::toBool () const {
     int ii = toInt ();
     if (eval_state->parent) {
-        NodeRefList *lst = eval_state->parent->process_list;
-        Node *r = eval_state->root;
+        NodeValueList *lst = eval_state->parent->process_list;
         if (lst) {
             int count = 0;
-            for (NodeRefItem *n = lst->first (); n; n = n->nextSibling ())
+            for (NodeValueItem *n = lst->first (); n; n = n->nextSibling ())
                 if (ii == ++count)
-                    return r == n->data.ptr ();
+                    return eval_state->root == n->data.node &&
+                        eval_state->attr == n->data.attr;
         }
         return false;
     }
@@ -480,12 +496,16 @@
 }
 
 bool Step::matches (Node *n) {
-    return any_path || string == n->nodeName ();
+    return any_node || string == n->nodeName ();
 }
 
-bool Step::selected (Node *n) {
+bool Step::matches (Attribute *a) {
+    return any_node || string == a->name ();
+}
+
+bool Step::selected (Node *n, Attribute *a) {
     if (first_child) {
-        first_child->setRoot (n);
+        first_child->setRoot (n, a);
         return first_child->toBool ();
     }
     return true;
@@ -495,7 +515,7 @@
     bool b = false;
     if (eval_state->parent) {
         sequence = eval_state->sequence;
-        NodeRefList *lst = toNodeList ();
+        NodeValueList *lst = toNodeList ();
         b = lst && lst->first ();
         delete lst;
     } else {
@@ -505,25 +525,39 @@
 }
 
 void Identifier::childByStep (Step *step, bool recurse) const {
-    NodeRefList *lst = eval_state->process_list;
-    NodeRefItem *last = lst->last ();
-    NodeRefList recursive_lst;
-    for (NodeRefItem *itm = lst->first (); itm; ) {
-        NodeRefItem *next = itm == last ? NULL : itm->nextSibling ();
-        for (Node *c = itm->data->firstChild (); c; c = c->nextSibling ()) {
-            if (step->matches (c))
-                lst->append (new NodeRefItem (c));
+    NodeValueList *lst = eval_state->process_list;
+    NodeValueItem *last = lst->last ();
+    NodeValueList recursive_lst;
+    for (NodeValueItem *itm = lst->first (); itm; ) {
+        NodeValueItem *next = itm == last ? NULL : itm->nextSibling ();
+
+        Node *n = itm->data.node;
+        if (step->is_attr) {
+            Element *e = n->isElementNode() ? static_cast<Element *> (n) : NULL;
+            Attribute *a = e ? e->attributes ().first () : NULL;
+            for (; a; a = a->nextSibling ())
+                if (step->matches (a))
+                    lst->append (new NodeValueItem (NodeValue (n, a)));
             if (recurse)
-                recursive_lst.append (new NodeRefItem (c));
+                for (Node *c = n->firstChild(); c; c = c->nextSibling ())
+                    recursive_lst.append (new NodeValueItem (c));
+        } else {
+            for (Node *c = n->firstChild(); c; c = c->nextSibling ()) {
+                if (step->matches (c))
+                    lst->append (new NodeValueItem (c));
+                if (recurse)
+                    recursive_lst.append (new NodeValueItem (c));
+            }
         }
+
         lst->remove (itm);
         itm = next;
     }
     if (recurse && recursive_lst.first ()) {
         eval_state->process_list = &recursive_lst;
         childByStep (step, recurse);
-        for (NodeRefItem *r = recursive_lst.first (); r; r = r->nextSibling ())
-            lst->append (new NodeRefItem (r->data));
+        for (NodeValueItem *r = recursive_lst.first (); r; r = r->nextSibling ())
+            lst->append (new NodeValueItem (r->data));
         eval_state->process_list = lst;
     }
 }
@@ -531,12 +565,12 @@
 void Identifier::childByPath (Step *step, bool recurse) const {
     if (!step->anyPath ()) {
         childByStep (step, recurse);
-        NodeRefItem *itm = eval_state->process_list->first ();
+        NodeValueItem *itm = eval_state->process_list->first ();
         if (itm && step->first_child) {
-            NodeRefList *newlist = new NodeRefList;
+            NodeValueList *newlist = new NodeValueList;
             for (; itm; itm = itm->nextSibling ())
-                if (step->selected (itm->data))
-                    newlist->append (new NodeRefItem (itm->data));
+                if (step->selected (itm->data.node, itm->data.attr))
+                    newlist->append (new NodeValueItem (itm->data));
             delete eval_state->process_list;
             eval_state->process_list = newlist;
         }
@@ -547,10 +581,10 @@
 
 QString Identifier::toString () const {
     if (eval_state->sequence != sequence) {
-        NodeRefList *lst = toNodeList ();
+        NodeValueList *lst = toNodeList ();
         int i = lst->length ();
         if (i == 1)
-            string = lst->first ()->data->nodeValue ();
+            string = lst->first ()->data.value ();
         else
             string = QString::number (i);
         delete lst;
@@ -559,11 +593,11 @@
     return string;
 }
 
-NodeRefList *Identifier::toNodeList () const {
-    NodeRefList *old = eval_state->process_list;
-    NodeRefList *lst = new NodeRefList;
+NodeValueList *Identifier::toNodeList () const {
+    NodeValueList *old = eval_state->process_list;
+    NodeValueList *lst = new NodeValueList;
     eval_state->process_list = lst;
-    lst->append (new NodeRefItem (eval_state->root));
+    lst->append (new NodeValueItem (eval_state->root));
     childByPath ((Step *) first_child, false);
     lst = eval_state->process_list;
     eval_state->process_list = old;
@@ -645,7 +679,7 @@
     if (eval_state->sequence != sequence) {
         sequence = eval_state->sequence;
         if (eval_state->parent) {
-            NodeRefList *lst = eval_state->parent->process_list;
+            NodeValueList *lst = eval_state->parent->process_list;
             if (lst)
                 i = lst->length ();
         }
@@ -666,13 +700,13 @@
     if (eval_state->sequence != sequence) {
         sequence = eval_state->sequence;
         if (eval_state->parent) {
-            NodeRefList *lst = eval_state->parent->process_list;
+            NodeValueList *lst = eval_state->parent->process_list;
             Node *r = eval_state->root;
             if (lst) {
                 i = 0;
-                for (NodeRefItem *n = lst->first(); n; n = n->nextSibling ()) {
+                for (NodeValueItem *n = lst->first(); n; n = n->nextSibling()) {
                     i++;
-                    if (r == n->data.ptr ())
+                    if (r == n->data.node)
                         break;
                 }
             }
@@ -864,7 +898,7 @@
     case gteq:
         return first_child->toInt () >= first_child->next_sibling->toInt ();
     case eq:
-        if (t1 == t2 && t1 == AST::TString)
+        if (t1 == AST::TString || t2 == AST::TString)
             return first_child->toString () ==
                 first_child->next_sibling->toString ();
         return first_child->toInt () == first_child->next_sibling->toInt ();
@@ -998,6 +1032,9 @@
     if (*s == '/') {
         entry = new Step (ast->eval_state);
     } else {
+        bool is_attr = *s == '@';
+        if (is_attr)
+            s = ++str;
         for (; *s; ++s)
             if (!((*s >= 'a' && *s <= 'z') ||
                         (*s >= 'A' && *s <= 'Z') ||
@@ -1007,7 +1044,7 @@
                 break;
         if (str == s)
             return false;
-        entry = new Step (ast->eval_state, str, s);
+        entry = new Step (ast->eval_state, str, s, is_attr);
         if (*s == '[') {
             AST pred (new EvalState (ast->eval_state));
             if (parseStatement (s + 1, end, &pred)) {
--- trunk/extragear/multimedia/kmplayer/src/expression.h #1017917:1017918
@@ -24,13 +24,29 @@
 
 namespace KMPlayer {
 
+class NodeValue {
+public:
+    NodeValue (Node *n, Attribute *a=NULL) : node (n), attr (a) {}
+
+    QString value () const;
+
+    Node *node;
+    Attribute *attr;
+};
+
+typedef ListNode<NodeValue> NodeValueItem;
+ITEM_AS_POINTER(KMPlayer::NodeValueItem)
+typedef NodeValueItem::SharedType NodeValueItemPtr;
+typedef List <NodeValueItem> NodeValueList;
+
+
 class Expression : public VirtualVoid {
 public:
     virtual bool toBool () const = 0;
     virtual int toInt () const = 0;
     virtual float toFloat () const = 0;
     virtual QString toString () const = 0;
-    virtual NodeRefList *toNodeList () const = 0;
+    virtual NodeValueList *toNodeList () const = 0;
     virtual void setRoot (Node *root) = 0;
 };
 
--- trunk/extragear/multimedia/kmplayer/src/kmplayer_smil.cpp #1017917:1017918
@@ -1371,9 +1371,9 @@
         if (c->payload && c->connecter) {
             Expression *expr = (Expression *) c->payload;
             expr->setRoot (s);
-            NodeRefList *lst = expr->toNodeList ();
-            for (NodeRefItem *itm = lst->first(); itm; itm = itm->nextSibling())
-                if (itm->data.ptr () == ref)
+            NodeValueList *lst = expr->toNodeList ();
+            for (NodeValueItem *itm = lst->first(); itm; itm = itm->nextSibling())
+                if (itm->data.node == ref)
                     s->document()->post (c->connecter,
                                          new Posting (s, MsgStateChanged));
             delete lst;
@@ -4154,9 +4154,15 @@
         if (!ref)
             ref = evaluateExpr ("/data");
         ref->setRoot (st);
-        NodeRefList *lst = ref->toNodeList ();
-        if (lst->first ())
-            st->newValue (lst->first ()->data, where, name, value);
+        NodeValueList *lst = ref->toNodeList ();
+        NodeValueItem *itm = lst->first ();
+        if (itm) {
+            if (name.startsWith(QChar('@')) && itm->data.node->isElementNode())
+                static_cast <Element *> (itm->data.node)->setAttribute (
+                        name.mid (1), value);
+            else
+                st->newValue (itm->data.node, where, name, value);
+        }
         delete lst;
     }
 }
@@ -4184,9 +4190,15 @@
         kWarning () << "ref is empty or no state";
     } else {
         ref->setRoot (st);
-        NodeRefList *lst = ref->toNodeList ();
-        if (lst->first ())
-            st->setValue (lst->first ()->data, value);
+        NodeValueList *lst = ref->toNodeList ();
+        NodeValueItemPtr itm = lst->first ();
+        if (itm) {
+            if (itm->data.attr && itm->data.node->isElementNode ())
+                static_cast <Element *> (itm->data.node)->setAttribute (
+                        itm->data.attr->name (), itm->data.attr->value ());
+            else
+                st->setValue (itm->data.node, value);
+        }
         delete lst;
     }
 }
@@ -4199,9 +4211,14 @@
         kWarning () << "ref is empty or no state";
     } else {
         ref->setRoot (st);
-        NodeRefList *lst = ref->toNodeList ();
-        for (NodeRefItem *itm = lst->first (); itm; itm = itm->nextSibling ())
-            itm->data->parentNode ()->removeChild (itm->data);
+        NodeValueList *lst = ref->toNodeList ();
+        for (NodeValueItem *itm = lst->first(); itm; itm = itm->nextSibling()) {
+            if (itm->data.attr && itm->data.node->isElementNode ())
+                static_cast <Element *> (itm->data.node)->setAttribute (
+                        itm->data.attr->name (), QString ());
+            else
+                itm->data.node->parentNode ()->removeChild (itm->data.node);
+        }
         delete lst;
     }
 }
--- trunk/extragear/multimedia/kmplayer/tests/state.smil #1017917:1017918
@@ -40,6 +40,22 @@
       <text src="data:,books%20{number(/data/books/book)}"
             left="10" top="160" width="300" height="20"/>
     </par>
+    <newvalue name="@price" ref="/data/books/book[1]" value="10p"/>
+    <newvalue name="@foo" ref="/data/books/book[2]" value="fred"/>
+    <newvalue name="@bar" ref="/data/books/book[2]" value="barney"/>
+    <newvalue name="@price" ref="/data/books/book[3]" value="5&#36;"/>
+    <par dur="5">
+      <text src="data:,books%20with%20price%20{//book[@price]}" left="10" top="10" \
width="300" height="20"/> +      <text \
src="data:,books%20with%20price%2010p%20{//book[@price=&quot;10p&quot;]/title}" \
left="10" top="40" width="300" height="20"/> +      <text \
src="data:,price%20of%20Pygmalion%20{//book[title=&quot;Pygmalion&quot;]/@price}" \
left="10" top="70" width="300" height="20"/> +      <text \
src="data:,attributes%20on%20second%20book%20{//book[2]/@*}" left="10" top="100" \
width="300" height="20"/> +      <text \
src="data:,total%20attributes%20on%20book%20{//book/@*}" left="10" top="130" \
width="300" height="20"/> +      <text \
src="data:,second%20attribute%20on%20book%20{//book/@*[2]}" left="10" top="160" \
width="300" height="20"/> +    </par>
+    <delvalue ref="//@foo"/>
+    <par dur="5">
+      <text src="data:,second%20attribute%20on%20book%20{//book/@*[2]}" left="10" \
top="160" width="300" height="20"/> +    </par>
     <delvalue ref="//books"/>
   </body>
 </smil>


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic