Repository: pwr-Solaar/Solaar

Issue:
Fine tune `Later` action for different use cases
**Information**
<!-- The version of Solaar in this repository has more features than released vesions.  Update to this version before asking for a new feature. -->
- Solaar version (`solaar --version` and `git describe --tags`): 1.1.11, 1.1.11-104-g4a89a79a
- Distribution: Ubuntu 23.10
- Kernel version (ex. `uname -srmo`): Linux 6.7.9-zabbly+ x86_64 GNU/Linux

<details>

```
OUTPUT HERE
```
</details>


**Is your feature request related to a problem? Please describe.**
I have some key / click combinations I am trying to run, which are I believe achievable with minor tweaks to the current way the `Later` action is designed. It is currently in seconds but it would be better to be usable in milliseconds.

**Describe the solution you'd like**
Using a float based value instead of an integer for `Later`, so that some more adjustments are possible  for different use cases. For example, I am trying to assign print screen and selection to a button. This is possible, however due to a pop-up, there is a small delay of about 0.1/0.2 seconds necessary between my two key presses, whereas 1 second is a bit too long.

Thank you!



Discussion:

Resolving patch:
diff --git a/lib/logitech_receiver/common.py b/lib/logitech_receiver/common.py
--- a/lib/logitech_receiver/common.py
+++ b/lib/logitech_receiver/common.py
@@ -379,8 +379,6 @@ class NamedInts:
 
     def __init__(self, dict=None, **kwargs):
         def _readable_name(n):
-            if not is_string(n):
-                raise TypeError("expected string, got " + str(type(n)))
             return n.replace("__", "/").replace("_", " ")
 
         # print (repr(kwargs))
diff --git a/lib/logitech_receiver/diversion.py b/lib/logitech_receiver/diversion.py
--- a/lib/logitech_receiver/diversion.py
+++ b/lib/logitech_receiver/diversion.py
@@ -1355,9 +1355,9 @@ def __init__(self, args, warn=True):
         if not (isinstance(args, list) and len(args) >= 1):
             if warn:
                 logger.warning("rule Later argument not list with minimum length 1: %s", args)
-        elif not (isinstance(args[0], int)) or not 0 < args[0] < 101:
+        elif not (isinstance(args[0], (int, float))) or not 0.01 <= args[0] <= 100:
             if warn:
-                logger.warning("rule Later argument delay not integer between 1 and 100: %s", args)
+                logger.warning("rule Later delay not between 0.01 and 100: %s", args)
         else:
             self.delay = args[0]
             self.rule = Rule(args[1:], warn=warn)
@@ -1368,7 +1368,10 @@ def __str__(self):
 
     def evaluate(self, feature, notification, device, last_result):
         if self.delay and self.rule:
-            GLib.timeout_add_seconds(self.delay, Rule.once, self.rule, feature, notification, device, last_result)
+            if self.delay >= 1:
+                GLib.timeout_add_seconds(int(self.delay), Rule.once, self.rule, feature, notification, device, last_result)
+            else:
+                GLib.timeout_add(int(self.delay * 1000), Rule.once, self.rule, feature, notification, device, last_result)
         return None
 
     def data(self):
diff --git a/lib/solaar/ui/diversion_rules.py b/lib/solaar/ui/diversion_rules.py
--- a/lib/solaar/ui/diversion_rules.py
+++ b/lib/solaar/ui/diversion_rules.py
@@ -1131,20 +1131,21 @@ def left_label(cls, component):
 
 class LaterUI(RuleComponentUI):
     CLASS = _DIV.Later
-    MIN_VALUE = 1
+    MIN_VALUE = 0.01
     MAX_VALUE = 100
 
     def create_widgets(self):
         self.widgets = {}
         self.label = Gtk.Label(valign=Gtk.Align.CENTER, hexpand=True)
-        self.label.set_text(_("Number of seconds to delay."))
+        self.label.set_text(_("Number of seconds to delay.  Delay between 0 and 1 is done with higher precision."))
         self.widgets[self.label] = (0, 0, 1, 1)
         self.field = Gtk.SpinButton.new_with_range(self.MIN_VALUE, self.MAX_VALUE, 1)
+        self.field.set_digits(3)
         self.field.set_halign(Gtk.Align.CENTER)
         self.field.set_valign(Gtk.Align.CENTER)
         self.field.set_hexpand(True)
         #        self.field.set_vexpand(True)
-        self.field.connect("changed", self._on_update)
+        self.field.connect("value-changed", self._on_update)
         self.widgets[self.field] = (0, 1, 1, 1)
 
     def show(self, component, editable):
@@ -1153,7 +1154,7 @@ def show(self, component, editable):
             self.field.set_value(component.delay)
 
     def collect_value(self):
-        return [int(self.field.get_value())] + self.component.components
+        return [float(int((self.field.get_value() + 0.0001) * 1000)) / 1000] + self.component.components
 
     @classmethod
     def left_label(cls, component):


Test patch: