]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
webui/prop: add support for integer range type (extjs spinner)
authorJaroslav Kysela <perex@perex.cz>
Wed, 6 Apr 2016 10:36:35 +0000 (12:36 +0200)
committerJaroslav Kysela <perex@perex.cz>
Wed, 6 Apr 2016 10:36:35 +0000 (12:36 +0200)
16 files changed:
Makefile.webui
src/access.c
src/channels.c
src/config.c
src/epggrab/channel.c
src/idnode.c
src/input/mpegts/iptv/iptv.c
src/input/mpegts/iptv/iptv_mux.c
src/prop.c
src/prop.h
src/webui/static/app/idnode.js
src/webui/static/extjs/examples/ux/Spinner.js [new symlink]
src/webui/static/extjs/examples/ux/SpinnerField.js [new symlink]
src/webui/static/extjs/examples/ux/css/Spinner.css [new symlink]
src/webui/static/extjs/examples/ux/images/spinner-split.gif [new symlink]
src/webui/static/extjs/examples/ux/images/spinner.gif [new symlink]

index 83102509ec1a08681029bde8900fd4f9290821d8..c7321881502682bda126047f1e44250fee7b87e4 100644 (file)
@@ -69,6 +69,7 @@ CSS_INIT   += $(EXTJSPATH)/resources/css/ext-all-notheme.css
 CSS_DONE   += $(ROOTPATH)/livegrid/resources/css/ext-ux-livegrid.css
 CSS_DONE   += $(EXTJSPATH)/examples/ux/gridfilters/css/GridFilters.css
 CSS_DONE   += $(EXTJSPATH)/examples/ux/gridfilters/css/RangeMenu.css
+CSS_DONE   += $(EXTJSPATH)/examples/ux/css/Spinner.css
 CSS_DONE   += static/xcheckbox/xcheckbox.css
 CSS_DONE   += static/app/ext.css
 
@@ -98,6 +99,8 @@ JAVASCRIPT += $(EXTJSPATH)/examples/ux/gridfilters/filter/NumericFilter.js
 JAVASCRIPT += $(EXTJSPATH)/examples/ux/gridfilters/filter/StringFilter.js
 JAVASCRIPT += $(EXTJSPATH)/examples/ux/gridfilters/menu/ListMenu.js
 JAVASCRIPT += $(EXTJSPATH)/examples/ux/gridfilters/menu/RangeMenu.js
+JAVASCRIPT += $(EXTJSPATH)/examples/ux/Spinner.js
+JAVASCRIPT += $(EXTJSPATH)/examples/ux/SpinnerField.js
 JAVASCRIPT += $(ROOTPATH)/app/i18n-post.js
 
 #
index 70387a0dc84ac0d925bd492d6d2dd3df70f83378..cc45a854b765f151664dbc180ce3b2fe6e19a5c4 100644 (file)
@@ -1655,7 +1655,7 @@ const idclass_t access_entry_class = {
     },
     {
       .type     = PT_S64,
-      .intsplit = CHANNEL_SPLIT,
+      .intextra = CHANNEL_SPLIT,
       .id       = "channel_min",
       .name     = N_("Minimal channel number"),
       .desc     = N_("Lowest channel number the user can access."),
@@ -1663,7 +1663,7 @@ const idclass_t access_entry_class = {
     },
     {
       .type     = PT_S64,
-      .intsplit = CHANNEL_SPLIT,
+      .intextra = CHANNEL_SPLIT,
       .id       = "channel_max",
       .name     = N_("Maximal channel number"),
       .desc     = N_("Highest channel number the user can access."),
index e31a7a63be71dbac68009d7d2ea6058cff01c98e..f9bd211ef6bfe4731aa33ce92d3a14c5aaf73bd4 100644 (file)
@@ -397,7 +397,7 @@ const idclass_t channel_class = {
     },
     {
       .type     = PT_S64,
-      .intsplit = CHANNEL_SPLIT,
+      .intextra = CHANNEL_SPLIT,
       .id       = "number",
       .name     = N_("Number"),
       .desc     = N_("Number. The position the channel will appear on "
index 518639c984fc76652bf7ca0269695b3372b3d87e..4f75f97fda90b639ba810325c0256b79ab7652ed 100644 (file)
@@ -2058,6 +2058,7 @@ const idclass_t config_class = {
     },
     {
       .type   = PT_U32,
+      .intextra = INTEXTRA_RANGE(1, 0x7ff, 1),
       .id     = "cookie_expires",
       .name   = N_("Cookie expiration (days)"),
       .desc   = N_("The number of days cookies set by Tvheadend should "
index 018c1105b35f6ad7fab565c31e12e05e5ee59ed6..745bfcf3b169c9912fcfc74f0f65fa6d9d91161d 100644 (file)
@@ -737,7 +737,7 @@ const idclass_t epggrab_channel_class = {
     },
     {
       .type     = PT_S64,
-      .intsplit = CHANNEL_SPLIT,
+      .intextra = CHANNEL_SPLIT,
       .id       = "number",
       .name     = N_("Number"),
       .desc     = N_("Channel number as defined in EPG data."),
index 84da3aed95e417c9e38223b85196b12a8d17bfbe..d6902dd01839c3b554584555a4fdf0cec8a7a85f 100644 (file)
@@ -817,8 +817,8 @@ idnode_filter_init
         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 / MIN(1, f->u.n.intsplit)) * p->intsplit;
+          if (INTEXTRA_IS_SPLIT(p->intextra) && p->intextra != f->u.n.intsplit) {
+            v = (v / MIN(1, f->u.n.intsplit)) * p->intextra;
             f->u.n.n = v;
           }
         }
index 4663769924173d2a3134b5bdce33ef2e47602db4..aa60d673169fc75b5c17f9dab2dd0f432f9adf73 100644 (file)
@@ -847,7 +847,7 @@ const idclass_t iptv_auto_network_class = {
     },
     {
       .type     = PT_S64,
-      .intsplit = CHANNEL_SPLIT,
+      .intextra = CHANNEL_SPLIT,
       .id       = "channel_number",
       .name     = N_("Channel numbers from"),
       .off      = offsetof(iptv_network_t, in_channel_number),
index 368f5cf579cdfdf70e86e278557cc0a664e4abbc..984628e46c6754eedc778f5f97e04e3e8971dbc5 100644 (file)
@@ -170,7 +170,7 @@ const idclass_t iptv_mux_class =
     },
     {
       .type     = PT_S64,
-      .intsplit = CHANNEL_SPLIT,
+      .intextra = CHANNEL_SPLIT,
       .id       = "channel_number",
       .name     = N_("Channel number"),
       .off      = offsetof(iptv_mux_t, mm_iptv_chnum),
index 7ffb5821c6c1c083d236a3e753ad6ca2b1c91061..75bb3ca380f1cb7265c16676f9c63f92eb34fc76 100644 (file)
@@ -140,13 +140,13 @@ prop_write_values
         break;
       }
       case PT_U32: {
-        if (p->intsplit) {
+        if (p->intextra && INTEXTRA_IS_SPLIT(p->intextra)) {
           char *s;
           if (!(new = htsmsg_field_get_str(f)))
             continue;
-          u32 = atol(new) * p->intsplit;
+          u32 = atol(new) * p->intextra;
           if ((s = strchr(new, '.')) != NULL)
-            u32 += (atol(s + 1) % p->intsplit);
+            u32 += (atol(s + 1) % p->intextra);
         } else {
           if (htsmsg_field_get_u32(f, &u32))
             continue;
@@ -155,10 +155,10 @@ prop_write_values
         break;
       }
       case PT_S64: {
-        if (p->intsplit) {
+        if (p->intextra && INTEXTRA_IS_SPLIT(p->intextra)) {
           if (!(new = htsmsg_field_get_str(f)))
             continue;
-          s64 = prop_intsplit_from_str(new, p->intsplit);
+          s64 = prop_intsplit_from_str(new, p->intextra);
         } else {
           if (htsmsg_field_get_s64(f, &s64))
             continue;
@@ -290,9 +290,9 @@ prop_read_value
       htsmsg_add_u32(m, name, *(uint16_t *)val);
       break;
     case PT_U32:
-      if (p->intsplit) {
-        uint32_t maj = *(int64_t *)val / p->intsplit;
-        uint32_t min = *(int64_t *)val % p->intsplit;
+      if (p->intextra && INTEXTRA_IS_SPLIT(p->intextra)) {
+        uint32_t maj = *(int64_t *)val / p->intextra;
+        uint32_t min = *(int64_t *)val % p->intextra;
         if (min) {
           snprintf(buf, sizeof(buf), "%u.%u", (unsigned int)maj, (unsigned int)min);
           htsmsg_add_str(m, name, buf);
@@ -302,9 +302,9 @@ prop_read_value
         htsmsg_add_u32(m, name, *(uint32_t *)val);
       break;
     case PT_S64:
-      if (p->intsplit) {
-        int64_t maj = *(int64_t *)val / p->intsplit;
-        int64_t min = *(int64_t *)val % p->intsplit;
+      if (p->intextra && INTEXTRA_IS_SPLIT(p->intextra)) {
+        int64_t maj = *(int64_t *)val / p->intextra;
+        int64_t min = *(int64_t *)val % p->intextra;
         if (min) {
           snprintf(buf, sizeof(buf), "%lu.%lu", (unsigned long)maj, (unsigned long)min);
           htsmsg_add_str(m, name, buf);
@@ -511,8 +511,15 @@ prop_serialize_value
     htsmsg_add_u32(m, "group", pl->group);
 
   /* Split integer value */
-  if (pl->intsplit)
-    htsmsg_add_u32(m, "intsplit", pl->intsplit);
+  if (pl->intextra) {
+    if (INTEXTRA_IS_SPLIT(pl->intextra))
+      htsmsg_add_u32(m, "intsplit", pl->intextra);
+    else {
+      htsmsg_add_s32(m, "intmax", INTEXTRA_GET_MAX(pl->intextra));
+      htsmsg_add_s32(m, "intmin", INTEXTRA_GET_MIN(pl->intextra));
+      htsmsg_add_s32(m, "intstep", INTEXTRA_GET_STEP(pl->intextra));
+    }
+  }
 
   /* Data */
   if (obj)
index 404b51de47e895fdf022558f9813eef07dbd0ba9..86b601cfe14ef7e7e3266524a769471f065b86d5 100644 (file)
@@ -64,6 +64,18 @@ typedef enum {
 #define PO_MULTILINE (1<<16) // Multiline string
 #define PO_PERSIST   (1<<17) // Persistent value (return back on save)
 
+/*
+ * min/max/step helpers
+ */
+#define INTEXTRA_RANGE(min, max, step) \
+  ((1<<31)|(((step)&0x7f)<<24)|(((max)&0xfff)<<12)|((min)&0xfff))
+
+#define INTEXTRA_IS_RANGE(e) (((e) & (1<<31)) != 0)
+#define INTEXTRA_IS_SPLIT(e) !INTEXTRA_IS_RANGE(e)
+#define INTEXTRA_GET_STEP(e) (((e)>>24)&0x7f)
+#define INTEXTRA_GET_MAX(e)  ((e)&(1<<23)?-(((e)>>12)&0x7ff):(((e)>>12)&0x7ff))
+#define INTEXTRA_GET_MIN(e)  ((e)&(1<<11)?-((e)&0x7ff):((e)&0x7ff))
+
 /*
  * Property definition
  */
@@ -76,7 +88,7 @@ typedef struct property {
   uint8_t     group;      ///< Visual group ID (like ExtJS FieldSet)
   size_t      off;        ///< Offset into object
   uint32_t    opts;       ///< Options
-  uint32_t    intsplit;   ///< integer/remainder boundary
+  uint32_t    intextra;   ///< intsplit: integer/remainder boundary or range: min/max/step
 
   /* String based processing */
   const void *(*get)  (void *ptr);
index 217243499e2ab873b1a775dbc2191755b857d28a..2a4e2726ca66aa18f793682e730acf8b37ef4372 100644 (file)
@@ -248,6 +248,9 @@ tvheadend.IdNodeField = function(conf)
     this.duration = conf.duration;
     this.date = conf.date;
     this.intsplit = conf.intsplit;
+    this.intmin = conf.intmin;
+    this.intmax = conf.intmax;
+    this.intstep = conf.intstep;
     this.hexa = conf.hexa;
     this.group = conf.group;
     this.lorder = conf.lorder;
@@ -488,8 +491,14 @@ tvheadend.IdNodeField = function(conf)
                     } else if (this.intsplit) {
                         c['maskRe'] = /[0-9\.]/;
                         cons = Ext.form.TextField;
-                    } else
+                    } else if (this.intmin || this.intmax) {
+                        cons = Ext.ux.form.SpinnerField;
+                        c['minValue'] = this.intmin;
+                        c['maxValue'] = this.intmax;
+                        c['incrementValue'] = this.intstep || 1;
+                    } else {
                         cons = Ext.form.NumberField;
+                    }
                     break;
 
                 /* 'str' and 'perm' */
@@ -812,6 +821,18 @@ tvheadend.idnode_editor_field = function(f, conf)
                     maskRe: /[0-9\.]/
                 });
                 break;
+            } else if (f.intmin || f.intmin) {
+               r = new Ext.ux.form.SpinnerField({
+                    fieldLabel: f.caption,
+                    name: f.id,
+                    disabled: d,
+                    width: 300,
+                    value: value,
+                    minValue: f.intmin,
+                    maxValue: f.intmax,
+                    incrementalValue: f.intstep || 1
+               });
+               break;
             }
             r = new Ext.form.NumberField({
                 fieldLabel: f.caption,
diff --git a/src/webui/static/extjs/examples/ux/Spinner.js b/src/webui/static/extjs/examples/ux/Spinner.js
new file mode 120000 (symlink)
index 0000000..10c08be
--- /dev/null
@@ -0,0 +1 @@
+../../../../../../vendor/ext-3.4/examples/ux/Spinner.js
\ No newline at end of file
diff --git a/src/webui/static/extjs/examples/ux/SpinnerField.js b/src/webui/static/extjs/examples/ux/SpinnerField.js
new file mode 120000 (symlink)
index 0000000..2aff716
--- /dev/null
@@ -0,0 +1 @@
+../../../../../../vendor/ext-3.4/examples/ux/SpinnerField.js
\ No newline at end of file
diff --git a/src/webui/static/extjs/examples/ux/css/Spinner.css b/src/webui/static/extjs/examples/ux/css/Spinner.css
new file mode 120000 (symlink)
index 0000000..46b82b1
--- /dev/null
@@ -0,0 +1 @@
+../../../../../../../vendor/ext-3.4/examples/ux/css/Spinner.css
\ No newline at end of file
diff --git a/src/webui/static/extjs/examples/ux/images/spinner-split.gif b/src/webui/static/extjs/examples/ux/images/spinner-split.gif
new file mode 120000 (symlink)
index 0000000..6c2e6fa
--- /dev/null
@@ -0,0 +1 @@
+../../../../../../../vendor/ext-3.4/examples/ux/images/spinner-split.gif
\ No newline at end of file
diff --git a/src/webui/static/extjs/examples/ux/images/spinner.gif b/src/webui/static/extjs/examples/ux/images/spinner.gif
new file mode 120000 (symlink)
index 0000000..e844fdd
--- /dev/null
@@ -0,0 +1 @@
+../../../../../../../vendor/ext-3.4/examples/ux/images/spinner.gif
\ No newline at end of file