# HG changeset patch
# User Jim Unroe <rock.unroe@gmail.com>
# Date 1359853011 18000
# Node ID b0767d6ce7d092423a1cfa498aaf45f8e7f012ff
# Parent  41b8c8a428c3136a49ba9742b79752a6f764602d
[uv5r] add workmode vfo presets
#467

diff -r 41b8c8a428c3 -r b0767d6ce7d0 chirp/settings.py
--- a/chirp/settings.py	Mon Jan 28 20:30:01 2013 -0500
+++ b/chirp/settings.py	Sat Feb 02 19:56:51 2013 -0500
@@ -28,16 +28,20 @@
     def __init__(self):
         self._current = None
         self._has_changed = False
+        self._callback = lambda x: x
 
     def changed(self):
         """Returns True if the setting has been changed since init"""
         return self._has_changed
 
+    def set_callback(self, callback):
+        self._callback = callback
+
     def set_value(self, value):
         """Sets the current value, triggers changed"""
         if self._current != None and value != self._current:
             self._has_changed = True
-        self._current = value
+        self._current = self._callback(value)
 
     def get_value(self):
         """Gets the current value"""
@@ -81,6 +85,45 @@
         """Returns the step increment"""
         return self._step
 
+class RadioSettingValueFloat(RadioSettingValue):
+    """A floating-point setting"""
+    def __init__(self, minval, maxval, current, resolution=0.001, precision=5):
+        RadioSettingValue.__init__(self)
+        self._min = minval
+        self._max = maxval
+        self._res = resolution
+        self._pre = precision
+        self.set_value(current)
+
+    def format(self, value=None):
+        """Formats the value into a string"""
+        if value is None:
+            value = self._current
+        fmt_string = "%%.%if" % self._pre
+        print fmt_string
+        return fmt_string % value
+
+    def set_value(self, value):
+        try:
+            value = float(value)
+        except:
+            raise InvalidValueError("A floating point value is required")
+        if value > self._max or value < self._min:
+            raise InvalidValueError("Value %s not in range %s-%s" % (
+                    self.format(value),
+                    self.format(self._min), self.format(self._max)))
+        
+        # FIXME: honor resolution
+
+        RadioSettingValue.set_value(self, value)
+
+    def get_min(self):
+        """Returns the minimum allowed value"""
+        return self._min
+
+    def get_max(self):
+        """Returns the maximum allowed value"""
+
 class RadioSettingValueBoolean(RadioSettingValue):
     """A boolean setting"""
     def __init__(self, current):
diff -r 41b8c8a428c3 -r b0767d6ce7d0 chirp/uv5r.py
--- a/chirp/uv5r.py	Mon Jan 28 20:30:01 2013 -0500
+++ b/chirp/uv5r.py	Sat Feb 02 19:56:51 2013 -0500
@@ -20,8 +20,8 @@
 from chirp import bitwise
 from chirp.settings import RadioSetting, RadioSettingGroup, \
     RadioSettingValueInteger, RadioSettingValueList, \
-    RadioSettingValueList, RadioSettingValueBoolean, \
-    RadioSettingValueString
+    RadioSettingValueBoolean, RadioSettingValueString, \
+    InvalidValueError
 
 MEM_FORMAT = """
 #seekto 0x0008;
@@ -211,6 +211,7 @@
 STEDELAY_LIST = ["%s ms" % x for x in range(100, 1100, 100)]
 STEDELAY_LIST.insert(0, "OFF")
 SCODE_LIST = ["%s" % x for x in range(1, 16)]
+BAND_LIST = ["VHF", "UHF"]
 
 SETTING_LISTS = {
     "step" : STEP_LIST,
@@ -230,6 +231,7 @@
     "rpste" : RPSTE_LIST,
     "stedelay" : STEDELAY_LIST,
     "scode" : SCODE_LIST,
+    "band" : BAND_LIST,
 }
 
 def _do_status(radio, block):
@@ -444,6 +446,7 @@
 
     def process_mmap(self):
         self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
+        print self.get_settings()
 
     def sync_in(self):
         try:
@@ -644,7 +647,7 @@
             return int(version_tag[idx:idx+3])
         raise Exception("Unrecognized firmware version string")
 
-    def _get_settings(self):
+    def get_settings(self):
         _settings = self._memobj.settings[0]
         basic = RadioSettingGroup("basic", "Basic Settings")
         advanced = RadioSettingGroup("advanced", "Advanced Settings")
@@ -884,15 +887,45 @@
                           RadioSettingValueInteger(0, 127, _mrcnb))
         workmode.append(rs)
 
-        options = ["VHF", "UHF"]
         rs = RadioSetting("vfoa.band", "VFO A Band",
-                          RadioSettingValueList(options,
-                                                options[self._memobj.vfoa.band]))
+                          RadioSettingValueList(BAND_LIST,
+                                                BAND_LIST[self._memobj.vfoa.band]))
+        workmode.append(rs)
+
+        def convert_bytes_to_freq(bytes):
+           real_freq = 0
+           for byte in bytes:
+               real_freq = (real_freq * 10) + byte
+           return real_freq
+
+        def convert_freq_to_bytes(real_freq):
+            bytes = [ 0 for x in range(0,8) ]   # init list with 8 times 0
+            real_freq = int(freq * 100000)      # it has to be integer
+            for i in range(7, -1, -1):          # go from 7 to 0
+                bytes[i] = real_freq%10         # extract last digit
+                real_freq /= 10                 # throw away last digit
+            return bytes
+
+        def my_validate(value):
+            if value < 40000000 and value > 17400000:
+                raise InvalidValueError("Can't be between 174000000-40000000")
+            return value
+
+        val1a = RadioSettingValueInteger(13600000, 52000000,
+                               convert_bytes_to_freq(self._memobj.vfoa.freq))
+        val1a.set_callback(my_validate)
+        rs = RadioSetting("vfoa.freq", "VFO A Frequency", val1a)
         workmode.append(rs)
 
         rs = RadioSetting("vfob.band", "VFO B Band",
-                          RadioSettingValueList(options,
-                                                options[self._memobj.vfob.band]))
+                          RadioSettingValueList(BAND_LIST,
+                                                BAND_LIST[self._memobj.vfob.band]))
+        workmode.append(rs)
+
+        val1b = RadioSettingValueInteger(13600000, 52000000,
+                               convert_bytes_to_freq(self._memobj.vfob.freq))
+        val1b.set_callback(my_validate)
+        rs = RadioSetting("vfob.freq", "VFO B Frequency", val1b)
         workmode.append(rs)
 
         options = ["High", "Low"]
@@ -949,33 +982,38 @@
 
         return group
 
-    def get_settings(self):
-        try:
-            return self._get_settings()
-        except:
-            import traceback
-            print "Failed to parse settings:"
-            traceback.print_exc()
-            return None
-
     def set_settings(self, settings):
+        def convert_freq_to_bytes(freq):
+            bytes = [ 0 for x in range(0,8) ]   # init list with 8 times 0
+            for i in range(7, -1, -1):          # go from 7 to 0
+                bytes[i] = freq%10              # extract last digit
+                freq /= 10                      # throw away last digit
+            return bytes
+            
         _settings = self._memobj.settings[0]
         for element in settings:
             if not isinstance(element, RadioSetting):
                 self.set_settings(element)
                 continue
-            try:
-                if "." in element.get_name():
-                    bits = element.get_name().split(".")
-                    obj = self._memobj
-                    for bit in bits[:-1]:
-                        obj = getattr(obj, bit)
-                    setting = bits[-1]
-                else:
-                    obj = _settings
-                    setting = element.get_name()
-                print "Setting %s = %s" % (setting, element.value)
-                setattr(obj, setting, element.value)
-            except Exception, e:
-                print element.get_name()
-                raise
+            elif element.get_name() == "vfoa.freq":
+                self._memobj.vfoa.freq = convert_freq_to_bytes(element.value.get_value())
+            elif element.get_name() == "vfob.freq":
+                self._memobj.vfob.freq = convert_freq_to_bytes(element.value.get_value())
+            else:
+                try:
+                    if "." in element.get_name():
+                        bits = element.get_name().split(".")
+                        obj = self._memobj
+                        for bit in bits[:-1]:
+                            obj = getattr(obj, bit)
+                        setting = bits[-1]
+                    else:
+                        obj = _settings
+                        setting = element.get_name()
+                    print "Setting %s = %s" % (setting, element.value)
+                    if setting == "footest":
+                        return # This is a fake setting!
+                    setattr(obj, setting, element.value)
+                except Exception, e:
+                    print element.get_name()
+                    raise
diff -r 41b8c8a428c3 -r b0767d6ce7d0 chirpui/settingsedit.py
--- a/chirpui/settingsedit.py	Mon Jan 28 20:30:01 2013 -0500
+++ b/chirpui/settingsedit.py	Sat Feb 02 19:56:51 2013 -0500
@@ -63,7 +63,12 @@
         if self._top_setting_group is None:
             return
 
-        job = common.RadioJob(None, "set_settings", self._top_setting_group)
+        def setting_cb(result):
+            if isinstance(result, Exception):
+                common.show_error(_("Error in setting value: %s") % result)
+
+        job = common.RadioJob(setting_cb, "set_settings",
+                              self._top_setting_group)
         job.set_desc("Setting radio settings")
         self._rthread.submit(job)
 
@@ -73,6 +78,8 @@
             adj.configure(value.get_value(),
                           value.get_min(), value.get_max(),
                           value.get_step(), 1, 0)
+        elif isinstance(value, settings.RadioSettingValueFloat):
+            widget.set_text(value.format())
         elif isinstance(value, settings.RadioSettingValueBoolean):
             widget.set_active(value.get_value())
         elif isinstance(value, settings.RadioSettingValueList):
@@ -89,9 +96,11 @@
             print "Unsupported widget type %s for %s" % (value.__class__,
                                                          element.get_name())
             
-    def _save_setting(self, widget, value):
+    def _do_save_setting(self, widget, value):
         if isinstance(value, settings.RadioSettingValueInteger):
             value.set_value(widget.get_adjustment().get_value())
+        elif isinstance(value, settings.RadioSettingValueFloat):
+            value.set_value(widget.get_text())
         elif isinstance(value, settings.RadioSettingValueBoolean):
             value.set_value(widget.get_active())
         elif isinstance(value, settings.RadioSettingValueList):
@@ -105,6 +114,12 @@
 
         self._save_settings()
 
+    def _save_setting(self, widget, value):
+        try:
+            self._do_save_setting(widget, value)
+        except settings.InvalidValueError, e:
+            common.show_error(_("Invalid setting value: %s") % e)
+
     def _build_ui_group(self, group):
         def pack(widget, pos):
             self._table.attach(widget, pos, pos+1, self._index, self._index+1,
@@ -139,6 +154,9 @@
                     widget = gtk.SpinButton()
                     print "Digits: %i" % widget.get_digits()
                     signal = "value-changed"
+                elif isinstance(value, settings.RadioSettingValueFloat):
+                    widget = gtk.Entry()
+                    signal = "focus-out-event"
                 elif isinstance(value, settings.RadioSettingValueBoolean):
                     widget = gtk.CheckButton(_("Enabled"))
                     signal = "toggled"
@@ -160,7 +178,11 @@
                 arraybox.pack_start(lalign, 1, 1, 1)
                 widget.show()
                 self._load_setting(value, widget)
-                widget.connect(signal, self._save_setting, value)
+                if signal == "focus-out-event":
+                    widget.connect(signal, lambda w, e, v:
+                                       self._save_setting(w, v), value)
+                else:
+                    widget.connect(signal, self._save_setting, value)
 
             self._index += 1
 
