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;
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;
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;
}
}
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;
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 )
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));
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:
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);
}
{
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 {
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
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)
{
/*
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';
hidden: this.hidden,
filter: {
type: ftype,
- dataIndex: this.id
+ dataIndex: this.id,
+ intsplit: this.intsplit
}
};
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' */