]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
idnode: Add intsplit filtering (include double ops, too)
authorJaroslav Kysela <perex@perex.cz>
Thu, 11 Sep 2014 17:49:19 +0000 (19:49 +0200)
committerJaroslav Kysela <perex@perex.cz>
Thu, 11 Sep 2014 17:49:19 +0000 (19:49 +0200)
src/api/api_idnode.c
src/idnode.c
src/idnode.h
src/webui/static/app/idnode.js

index b7d56d51076ffbaa110f381eb4bfa274c3e283f0..997b8742e39c3cdbeeaea768012e8a4efc37f64a 100644 (file)
@@ -57,7 +57,7 @@ static void
 api_idnode_grid_conf
   ( htsmsg_t *args, api_idnode_grid_conf_t *conf )
 {
-  htsmsg_field_t *f;
+  htsmsg_field_t *f, *f2;
   htsmsg_t *filter, *e;
   const char *str;
 
@@ -84,11 +84,20 @@ api_idnode_grid_conf
         if ((v = htsmsg_get_str(e, "value")))
           idnode_filter_add_str(&conf->filter, k, v, IC_RE);
       } else if (!strcmp(t, "numeric")) {
-        uint32_t v;
-        if (!htsmsg_get_u32(e, "value", &v)) {
-          int t = str2val(htsmsg_get_str(e, "comparison") ?: "",
-                          filtcmptab);
-          idnode_filter_add_num(&conf->filter, k, v, t == -1 ? IC_EQ : t);
+        f2 = htsmsg_field_find(e, "value");
+        if (f2) {
+          int t = str2val(htsmsg_get_str(e, "comparison") ?: "", filtcmptab);
+          if (f2->hmf_type == HMF_DBL) {
+            double dbl;
+            if (!htsmsg_field_get_dbl(f2, &dbl))
+              idnode_filter_add_dbl(&conf->filter, k, dbl, t == -1 ? IC_EQ : t);
+          } else {
+            int64_t v;
+            int64_t intsplit = 0;
+            htsmsg_get_s64(e, "intsplit", &intsplit);
+            if (!htsmsg_field_get_s64(f2, &v))
+              idnode_filter_add_num(&conf->filter, k, v, t == -1 ? IC_EQ : t, intsplit);
+          }
         }
       } else if (!strcmp(t, "boolean")) {
         uint32_t v;
index 3f20e096235aa6042f231e333bf53901b95852c4..a1d6f0cff4533c50105070db4c1c132deac21345 100644 (file)
@@ -407,8 +407,54 @@ idnode_get_s64
       case PT_S64:
         *s64 = *(int64_t*)ptr;
         return 0;
+      case PT_DBL:
+        *s64 = *(double*)ptr;
+        return 0;
       case PT_TIME:
         *s64 = *(time_t*)ptr;
+        return 0;
+      default:
+        break;
+    }
+  }
+  return 1;
+}
+
+/*
+ * Get field as double
+ */
+int
+idnode_get_dbl
+  ( idnode_t *self, const char *key, double *dbl )
+{
+  const property_t *p = idnode_find_prop(self, key);
+  if (p->islist) return 1;
+  if (p) {
+    const void *ptr;
+    if (p->get)
+      ptr = p->get(self);
+    else
+      ptr = ((void*)self) + p->off;
+    switch (p->type) {
+      case PT_INT:
+      case PT_BOOL:
+        *dbl = *(int*)ptr;
+        return 0;
+      case PT_U16:
+        *dbl = *(uint16_t*)ptr;
+        return 0;
+      case PT_U32:
+        *dbl = *(uint32_t*)ptr;
+        return 0;
+      case PT_S64:
+        *dbl = *(int64_t*)ptr;
+        return 0;
+      case PT_DBL:
+        *dbl = *(double *)ptr;
+        return 0;
+      case PT_TIME:
+        *dbl = *(time_t*)ptr;
+        return 0;
       default:
         break;
     }
@@ -597,7 +643,16 @@ idnode_cmp_sort
       }
       break;
     case PT_DBL:
-      // TODO
+      {
+        double dbla = 0, dblb = 0;
+        idnode_get_dbl(ina, sort->key, &dbla);
+        idnode_get_dbl(inb, sort->key, &dblb);
+        if (sort->dir == IS_ASC)
+          return dbla - dblb;
+        else
+          return dblb - dbla;
+      }
+      break;
     case PT_TIME:
       {
         time_t ta = 0, tb = 0;
@@ -617,6 +672,31 @@ idnode_cmp_sort
   return 0;
 }
 
+static void
+idnode_filter_init
+  ( idnode_t *in, idnode_filter_t *filter )
+{
+  idnode_filter_ele_t *f;
+  const property_t *p;
+
+  LIST_FOREACH(f, filter, link) {
+    if (f->type == IF_NUM) {
+      p = idnode_find_prop(in, f->key);
+      if (p) {
+        if (p->type == PT_U32 || p->type == PT_S64 ||
+            p->type == PT_TIME) {
+          int64_t v = f->u.n.n;
+          if (p->intsplit != f->u.n.intsplit) {
+            v = (v / (f->u.n.intsplit <= 0 ? 1 : 0)) * p->intsplit;
+            f->u.n.n = v;
+          }
+        }
+      }
+    }
+    f->checked = 1;
+  }
+}
+
 int
 idnode_filter
   ( idnode_t *in, idnode_filter_t *filter )
@@ -624,6 +704,8 @@ idnode_filter
   idnode_filter_ele_t *f;
   
   LIST_FOREACH(f, filter, link) {
+    if (!f->checked)
+      idnode_filter_init(in, filter);
     if (f->type == IF_STR) {
       const char *str;
       str = idnode_get_display(in, idnode_find_prop(in, f->key));
@@ -655,7 +737,29 @@ idnode_filter
       int64_t a, b;
       if (idnode_get_s64(in, f->key, &a))
         return 1;
-      b = (f->type == IF_NUM) ? f->u.n : f->u.b;
+      b = (f->type == IF_NUM) ? f->u.n.n : f->u.b;
+      switch (f->comp) {
+        case IC_IN:
+        case IC_RE:
+          break; // Note: invalid
+        case IC_EQ:
+          if (a != b)
+            return 1;
+          break;
+        case IC_LT:
+          if (a > b)
+            return 1;
+          break;
+        case IC_GT:
+          if (a < b)
+            return 1;
+          break;
+      }
+    } else if (f->type == IF_DBL) {
+      double a, b;
+      if (idnode_get_dbl(in, f->key, &a))
+        return 1;
+      b = f->u.dbl;
       switch (f->comp) {
         case IC_IN:
         case IC_RE:
@@ -699,13 +803,26 @@ idnode_filter_add_str
 
 void
 idnode_filter_add_num
-  ( idnode_filter_t *filt, const char *key, int64_t val, int comp )
+  ( idnode_filter_t *filt, const char *key, int64_t val, int comp, int64_t intsplit )
 {
   idnode_filter_ele_t *ele = calloc(1, sizeof(idnode_filter_ele_t));
   ele->key  = strdup(key);
   ele->type = IF_NUM;
   ele->comp = comp;
-  ele->u.n  = val;
+  ele->u.n.n = val;
+  ele->u.n.intsplit = intsplit;
+  LIST_INSERT_HEAD(filt, ele, link);
+}
+
+void
+idnode_filter_add_dbl
+  ( idnode_filter_t *filt, const char *key, double dbl, int comp )
+{
+  idnode_filter_ele_t *ele = calloc(1, sizeof(idnode_filter_ele_t));
+  ele->key   = strdup(key);
+  ele->type  = IF_DBL;
+  ele->comp  = comp;
+  ele->u.dbl = dbl;
   LIST_INSERT_HEAD(filt, ele, link);
 }
 
index 82c70245bfcc5e5d017bf631437de7a3eeddc0ba..f3d03387a2d2039cf000188eba5164b76e4aaf03 100644 (file)
@@ -100,16 +100,22 @@ typedef struct idnode_filter_ele
 {
   LIST_ENTRY(idnode_filter_ele) link; ///< List link
 
+  int checked;
   char *key;                          ///< Filter key
   enum {
     IF_STR,
     IF_NUM,
+    IF_DBL,
     IF_BOOL
   } type;                             ///< Filter type
   union {
     int      b;
     char    *s;
-    int64_t  n;
+    struct {
+      int64_t n;
+      int64_t intsplit;
+    } n;
+    double   dbl;
     regex_t  re;
   } u;                                ///< Filter data
   enum {
@@ -175,13 +181,16 @@ idnode_perm(idnode_t *self, struct access *a, htsmsg_t *msg_to_write)
 const char *idnode_get_str (idnode_t *self, const char *key );
 int         idnode_get_u32 (idnode_t *self, const char *key, uint32_t *u32);
 int         idnode_get_s64 (idnode_t *self, const char *key,  int64_t *s64);
+int         idnode_get_dbl (idnode_t *self, const char *key,   double *dbl);
 int         idnode_get_bool(idnode_t *self, const char *key, int *b);
 int         idnode_get_time(idnode_t *self, const char *key, time_t *tm);
 
 void idnode_filter_add_str
   (idnode_filter_t *f, const char *k, const char *v, int t);
 void idnode_filter_add_num
-  (idnode_filter_t *f, const char *k, int64_t s64, int t);
+  (idnode_filter_t *f, const char *k, int64_t s64, int t, int64_t intsplit);
+void idnode_filter_add_dbl
+  (idnode_filter_t *f, const char *k, double dbl, int t);
 void idnode_filter_add_bool
   (idnode_filter_t *f, const char *k, int b, int t);
 void idnode_filter_clear
index 18eabf5f8a361a2bb9e2592794affcf9053c2028..9608274fe883c87a22b94d116cc5c2b4aa185d64 100644 (file)
@@ -107,6 +107,44 @@ tvheadend.idnode_enum_store = function(f)
     return store;
 };
 
+Ext.ux.grid.filter.IntsplitFilter = Ext.extend(Ext.ux.grid.filter.NumericFilter, {
+
+    fieldCls : Ext.form.TextField,
+
+    constructor: function(conf) {
+        this.intsplit = conf.intsplit;
+        if (!conf.fields)
+            conf.fields = {
+                gt: { maskRe: /[0-9\.]/ },
+                lt: { maskRe: /[0-9\.]/ },
+                eq: { maskRe: /[0-9\.]/ }
+            };
+        Ext.ux.grid.filter.IntsplitFilter.superclass.constructor.call(this, conf);
+    },
+
+    getSerialArgs: function () {
+        var key,
+        args = [],
+        values = this.menu.getValue();
+        for (key in values) {
+            var s = values[key].toString().split('.');
+            var v = 0;
+            if (s.length > 0)
+                v = parseInt(s[0]) * this.intsplit;
+            if (s.length > 1)
+                v += parseInt(s[1]);
+            args.push({
+                type: 'numeric',
+                comparison: key,
+                value: v,
+                intsplit: this.intsplit
+            });
+        }
+        return args;
+    }
+
+});
+
 tvheadend.IdNodeField = function(conf)
 {
     /*
@@ -151,7 +189,10 @@ tvheadend.IdNodeField = function(conf)
         var cfg = conf && this.id in conf ? conf[this.id] : {};
         var w = 300;
         var ftype = 'string';
-        if (this.type === 'int' || this.type === 'u32' ||
+        if (this.intsplit) {
+            ftype = 'intsplit';
+            w = 80;
+        } else if (this.type === 'int' || this.type === 'u32' ||
             this.type === 'u16' || this.type === 's64' ||
             this.type === 'dbl') {
             ftype = 'numeric';
@@ -180,7 +221,8 @@ tvheadend.IdNodeField = function(conf)
             hidden: this.hidden,
             filter: {
                 type: ftype,
-                dataIndex: this.id
+                dataIndex: this.id,
+                intsplit: this.intsplit
             }
         };
 
@@ -307,7 +349,11 @@ tvheadend.IdNodeField = function(conf)
                 case 's32':
                 case 'dbl':
                 case 'time':
-                    cons = Ext.form.NumberField;
+                    if (this.intsplit) {
+                        c['maskRe'] = /[0-9\.]/;
+                        cons = Ext.form.TextField;
+                    } else
+                        cons = Ext.form.NumberField;
                     break;
 
                 /* 'str' and 'perm' */