mirror of
https://github.com/kk7ds/chirp.git
synced 2024-09-21 10:37:15 +00:00
[py3] Changes to ui so that we can actually start under py3/gi
This adds a chirp.ui.compat module where we can pile things needed to handle python3 differently. Right now there are a bunch of things that just fail for reasons I don't fully grasp yet. Those go under a py3safe() decorator, which logs and then ignores them. Also, there is an issue with the sensitive=True bit on the columns for empty memories. Need to figure that out. #495
This commit is contained in:
parent
434b9668ea
commit
26b583576c
31
chirp/ui/compat.py
Normal file
31
chirp/ui/compat.py
Normal file
@ -0,0 +1,31 @@
|
||||
import contextlib
|
||||
import logging
|
||||
|
||||
import gtk
|
||||
|
||||
LOG = logging.getLogger('uicompat')
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def py3safe():
|
||||
try:
|
||||
yield
|
||||
except Exception as e:
|
||||
LOG.exception('FIXMEPY3: %s' % e)
|
||||
|
||||
|
||||
def SpinButton(adj):
|
||||
try:
|
||||
return gtk.SpinButton(adj)
|
||||
except TypeError:
|
||||
sb = gtk.SpinButton()
|
||||
sb.configure(adj, 1.0, 0)
|
||||
return sb
|
||||
|
||||
def Frame(label):
|
||||
try:
|
||||
return gtk.Frame(label)
|
||||
except TypeError:
|
||||
f = gtk.Frame()
|
||||
f.set_label(label)
|
||||
return f
|
@ -18,6 +18,7 @@ import gobject
|
||||
import logging
|
||||
|
||||
from chirp.ui import common, miscwidgets
|
||||
from chirp.ui import compat
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -50,9 +51,10 @@ class CallsignEditor(gtk.HBox):
|
||||
self.listw.set_editable(1, True)
|
||||
self.listw.connect("item-set", self._cs_changed)
|
||||
|
||||
rend = self.listw.get_renderer(1)
|
||||
rend.set_property("family", "Monospace")
|
||||
rend.set_property("width-chars", width)
|
||||
with compat.py3safe():
|
||||
rend = self.listw.get_renderer(1)
|
||||
rend.set_property("family", "Monospace")
|
||||
rend.set_property("width-chars", width)
|
||||
|
||||
sw = gtk.ScrolledWindow()
|
||||
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
@ -126,7 +128,7 @@ class DStarEditor(common.Editor):
|
||||
|
||||
fixed = self.rthread.radio.get_features().has_implicit_calls
|
||||
|
||||
frame = gtk.Frame(_("Your callsign"))
|
||||
frame = compat.Frame(_("Your callsign"))
|
||||
self.editor_ucall = CallsignEditor(first_fixed=fixed)
|
||||
self.editor_ucall.set_size_request(-1, 200)
|
||||
self.editor_ucall.show()
|
||||
@ -134,7 +136,7 @@ class DStarEditor(common.Editor):
|
||||
frame.show()
|
||||
box.pack_start(frame, 1, 1, 0)
|
||||
|
||||
frame = gtk.Frame(_("Repeater callsign"))
|
||||
frame = compat.Frame(_("Repeater callsign"))
|
||||
self.editor_rcall = CallsignEditor(first_fixed=fixed)
|
||||
self.editor_rcall.set_size_request(-1, 200)
|
||||
self.editor_rcall.show()
|
||||
@ -142,7 +144,7 @@ class DStarEditor(common.Editor):
|
||||
frame.show()
|
||||
box.pack_start(frame, 1, 1, 0)
|
||||
|
||||
frame = gtk.Frame(_("My callsign"))
|
||||
frame = compat.Frame(_("My callsign"))
|
||||
self.editor_mcall = CallsignEditor()
|
||||
self.editor_mcall.set_size_request(-1, 200)
|
||||
self.editor_mcall.show()
|
||||
|
@ -28,8 +28,9 @@ import gobject
|
||||
import sys
|
||||
|
||||
from chirp.ui import inputdialog, common
|
||||
from chirp.ui import compat
|
||||
from chirp import platform, directory, util
|
||||
from chirp.drivers import generic_xml, generic_csv, repeaterbook
|
||||
from chirp.drivers import generic_csv, repeaterbook
|
||||
from chirp.drivers import ic9x, kenwood_live, idrp, vx7, vx5, vx6
|
||||
from chirp.drivers import icf, ic9x_icf
|
||||
from chirp import CHIRP_VERSION, chirp_common, detect, errors
|
||||
@ -45,7 +46,7 @@ if __name__ == "__main__":
|
||||
|
||||
try:
|
||||
import serial
|
||||
except ImportError, e:
|
||||
except ImportError as e:
|
||||
common.log_exception()
|
||||
common.show_error("\nThe Pyserial module is not installed!")
|
||||
|
||||
@ -374,7 +375,7 @@ of file.
|
||||
if not radio:
|
||||
return
|
||||
LOG.debug("Manually selected %s" % radio)
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
common.log_exception()
|
||||
common.show_error(os.path.basename(fname) + ": " + str(e))
|
||||
return
|
||||
@ -384,7 +385,7 @@ of file.
|
||||
eset = editorset.EditorSet(radio, self,
|
||||
filename=fname,
|
||||
tempname=tempname)
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
common.log_exception()
|
||||
common.show_error(
|
||||
_("There was an error opening {fname}: {error}").format(
|
||||
@ -491,7 +492,7 @@ of file.
|
||||
|
||||
try:
|
||||
eset.save(fname)
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
d = inputdialog.ExceptionDialog(e)
|
||||
d.run()
|
||||
d.destroy()
|
||||
@ -574,7 +575,7 @@ of file.
|
||||
try:
|
||||
shutil.copy(fn, stock_dir)
|
||||
LOG.debug("Copying %s -> %s" % (fn, stock_dir))
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
LOG.error("Unable to copy %s to %s: %s" % (fn, stock_dir, e))
|
||||
return False
|
||||
return True
|
||||
@ -584,7 +585,7 @@ of file.
|
||||
if not os.path.isdir(stock_dir):
|
||||
try:
|
||||
os.mkdir(stock_dir)
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
LOG.error("Unable to create directory: %s" % stock_dir)
|
||||
return
|
||||
if not self.copy_shipped_stock_configs(stock_dir):
|
||||
@ -730,7 +731,7 @@ of file.
|
||||
rtscts=rclass.HARDWARE_FLOW,
|
||||
timeout=0.25)
|
||||
ser.flushInput()
|
||||
except serial.SerialException, e:
|
||||
except serial.SerialException as e:
|
||||
d = inputdialog.ExceptionDialog(e)
|
||||
d.run()
|
||||
d.destroy()
|
||||
@ -776,7 +777,7 @@ of file.
|
||||
rtscts=radio.HARDWARE_FLOW,
|
||||
timeout=0.25)
|
||||
ser.flushInput()
|
||||
except serial.SerialException, e:
|
||||
except serial.SerialException as e:
|
||||
d = inputdialog.ExceptionDialog(e)
|
||||
d.run()
|
||||
d.destroy()
|
||||
@ -910,7 +911,7 @@ of file.
|
||||
radio = dmrmarc.DMRMARCRadio(None)
|
||||
radio.set_params(city, state, country)
|
||||
self.do_open_live(radio, read_only=True)
|
||||
except errors.RadioError, e:
|
||||
except errors.RadioError as e:
|
||||
common.show_error(e)
|
||||
|
||||
self.window.set_cursor(None)
|
||||
@ -1021,7 +1022,6 @@ of file.
|
||||
query = query % (code,
|
||||
band and band or "%%",
|
||||
county and county or "%%")
|
||||
print query
|
||||
|
||||
# Do this in case the import process is going to take a while
|
||||
# to make sure we process events leading up to this
|
||||
@ -1045,11 +1045,11 @@ of file.
|
||||
("query=%s\n" % query) +
|
||||
("\n") +
|
||||
("\n".join(radio.errors)))
|
||||
except errors.InvalidDataError, e:
|
||||
except errors.InvalidDataError as e:
|
||||
common.show_error(str(e))
|
||||
self.window.set_cursor(None)
|
||||
return
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
common.log_exception()
|
||||
|
||||
reporting.report_model_usage(radio, "import", True)
|
||||
@ -1127,7 +1127,6 @@ of file.
|
||||
|
||||
query = "https://www.repeaterbook.com/repeaters/downloads/CHIRP/" \
|
||||
"app_direct.php?loc=%s&band=%s&dist=%s" % (loc, band, dist)
|
||||
print query
|
||||
|
||||
# Do this in case the import process is going to take a while
|
||||
# to make sure we process events leading up to this
|
||||
@ -1151,11 +1150,11 @@ of file.
|
||||
("query=%s\n" % query) +
|
||||
("\n") +
|
||||
("\n".join(radio.errors)))
|
||||
except errors.InvalidDataError, e:
|
||||
except errors.InvalidDataError as e:
|
||||
common.show_error(str(e))
|
||||
self.window.set_cursor(None)
|
||||
return
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
common.log_exception()
|
||||
|
||||
reporting.report_model_usage(radio, "import", True)
|
||||
@ -1239,7 +1238,7 @@ of file.
|
||||
|
||||
try:
|
||||
radio = PRRadio(filename)
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
common.show_error(str(e))
|
||||
return
|
||||
|
||||
@ -1378,7 +1377,7 @@ of file.
|
||||
radio = radioreference.RadioReferenceRadio(None)
|
||||
radio.set_params(zipcode, username, passwd)
|
||||
self.do_open_live(radio, read_only=True)
|
||||
except errors.RadioError, e:
|
||||
except errors.RadioError as e:
|
||||
common.show_error(e)
|
||||
|
||||
self.window.set_cursor(None)
|
||||
@ -1620,7 +1619,7 @@ of file.
|
||||
# See this for why:
|
||||
# http://stackoverflow.com/questions/2904274/globals-and-locals-in-python-exec
|
||||
exec(pyc, globals(), globals())
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
common.log_exception()
|
||||
common.show_error("Unable to load module: %s" % e)
|
||||
|
||||
@ -1934,15 +1933,17 @@ of file.
|
||||
box = gtk.HBox(False, 2)
|
||||
|
||||
self.sb_general = gtk.Statusbar()
|
||||
self.sb_general.set_has_resize_grip(False)
|
||||
self.sb_general.show()
|
||||
box.pack_start(self.sb_general, 1, 1, 1)
|
||||
|
||||
self.sb_radio = gtk.Statusbar()
|
||||
self.sb_radio.set_has_resize_grip(True)
|
||||
self.sb_radio.show()
|
||||
box.pack_start(self.sb_radio, 1, 1, 1)
|
||||
|
||||
with compat.py3safe():
|
||||
self.sb_general.set_has_resize_grip(False)
|
||||
self.sb_radio.set_has_resize_grip(True)
|
||||
|
||||
box.show()
|
||||
return box
|
||||
|
||||
@ -2065,7 +2066,9 @@ of file.
|
||||
allocation = window.get_allocation()
|
||||
CONF.set_int("window_w", allocation.width, "state")
|
||||
CONF.set_int("window_h", allocation.height, "state")
|
||||
self.connect("expose_event", expose)
|
||||
|
||||
with compat.py3safe():
|
||||
self.connect("expose_event", expose)
|
||||
|
||||
def state_change(window, event):
|
||||
CONF.set_bool(
|
||||
|
@ -29,7 +29,10 @@ import pickle
|
||||
import os
|
||||
import logging
|
||||
|
||||
import six
|
||||
|
||||
from chirp.ui import common, shiftdialog, miscwidgets, config, memdetail
|
||||
from chirp.ui import compat
|
||||
from chirp.ui import bandplans
|
||||
from chirp import chirp_common, errors, directory, import_logic
|
||||
|
||||
@ -423,7 +426,7 @@ class MemoryEditor(common.Editor):
|
||||
if extd:
|
||||
val = extd
|
||||
|
||||
return val
|
||||
return str(val)
|
||||
|
||||
def render(self, _, rend, model, iter, colnum):
|
||||
val, hide = model.get(iter, colnum, self.col("_hide_cols"))
|
||||
@ -1001,18 +1004,29 @@ class MemoryEditor(common.Editor):
|
||||
else:
|
||||
choices = gtk.ListStore(TYPE_STRING, TYPE_STRING)
|
||||
for choice in self.choices[_cap]:
|
||||
choices.append([choice, self._render(i, choice)])
|
||||
choices.append([str(choice), self._render(i, choice)])
|
||||
rend.set_property("model", choices)
|
||||
rend.set_property("text-column", 1)
|
||||
rend.set_property("editable", True)
|
||||
rend.set_property("has-entry", False)
|
||||
rend.connect("edited", self.edited, _cap)
|
||||
col = gtk.TreeViewColumn(_cap, rend, text=i, sensitive=filled)
|
||||
if six.PY3:
|
||||
# FIXMEPY3: we can't set sensitive on the column without
|
||||
# it affecting the whole column (which makes sense).
|
||||
# Setting it on the renderer doesn't seem to work like
|
||||
# we want either.
|
||||
col = gtk.TreeViewColumn(_cap, rend, text=i)
|
||||
else:
|
||||
col = gtk.TreeViewColumn(_cap, rend, text=i, sensitive=filled)
|
||||
col.set_cell_data_func(rend, self.render, i)
|
||||
else:
|
||||
rend.set_property("editable", _cap not in non_editable)
|
||||
rend.connect("edited", self.edited, _cap)
|
||||
col = gtk.TreeViewColumn(_cap, rend, text=i, sensitive=filled)
|
||||
if six.PY3:
|
||||
# FIXMEPY3: See above
|
||||
col = gtk.TreeViewColumn(_cap, rend, text=i)
|
||||
else:
|
||||
col = gtk.TreeViewColumn(_cap, rend, text=i, sensitive=filled)
|
||||
col.set_cell_data_func(rend, self.render, i)
|
||||
|
||||
col.set_reorderable(True)
|
||||
@ -1191,7 +1205,7 @@ class MemoryEditor(common.Editor):
|
||||
self._config.get_int(hikey) or 999
|
||||
|
||||
self.lo_limit_adj = gtk.Adjustment(lostart, min, max-1, 1, 10)
|
||||
lo = gtk.SpinButton(self.lo_limit_adj)
|
||||
lo = compat.SpinButton(self.lo_limit_adj)
|
||||
lo.connect("value-changed", self._store_limit, "lo")
|
||||
lo.show()
|
||||
hbox.pack_start(lo, 0, 0, 0)
|
||||
@ -1201,7 +1215,7 @@ class MemoryEditor(common.Editor):
|
||||
hbox.pack_start(lab, 0, 0, 0)
|
||||
|
||||
self.hi_limit_adj = gtk.Adjustment(histart, min+1, max, 1, 10)
|
||||
hi = gtk.SpinButton(self.hi_limit_adj)
|
||||
hi = compat.SpinButton(self.hi_limit_adj)
|
||||
hi.connect("value-changed", self._store_limit, "hi")
|
||||
hi.show()
|
||||
hbox.pack_start(hi, 0, 0, 0)
|
||||
@ -1640,13 +1654,15 @@ class DstarMemoryEditor(MemoryEditor):
|
||||
if i not in self.choices:
|
||||
continue
|
||||
column = self.view.get_column(self.col(i))
|
||||
rend = column.get_cell_renderers()[0]
|
||||
rend.set_property("has-entry", True)
|
||||
with compat.py3safe():
|
||||
rend = column.get_cell_renderers()[0]
|
||||
rend.set_property("has-entry", True)
|
||||
|
||||
for i in _dv_columns:
|
||||
col = self.view.get_column(self.col(i))
|
||||
rend = col.get_cell_renderers()[0]
|
||||
rend.set_property("family", "Monospace")
|
||||
with compat.py3safe():
|
||||
rend = col.get_cell_renderers()[0]
|
||||
rend.set_property("family", "Monospace")
|
||||
|
||||
def set_urcall_list(self, urcalls):
|
||||
store = self.choices["URCALL"]
|
||||
|
@ -21,6 +21,7 @@ import os
|
||||
import logging
|
||||
|
||||
from chirp import platform
|
||||
from chirp.ui import compat
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -186,9 +187,10 @@ class KeyedListWidget(gtk.HBox):
|
||||
|
||||
def set_editable(self, column, is_editable):
|
||||
col = self.__view.get_column(column)
|
||||
rend = col.get_cell_renderers()[0]
|
||||
rend.set_property("editable", True)
|
||||
rend.connect("edited", self._edited, column + 1)
|
||||
with compat.py3safe():
|
||||
rend = col.get_cell_renderers()[0]
|
||||
rend.set_property("editable", True)
|
||||
rend.connect("edited", self._edited, column + 1)
|
||||
|
||||
def set_sort_column(self, column, value=None):
|
||||
if not value:
|
||||
@ -197,7 +199,8 @@ class KeyedListWidget(gtk.HBox):
|
||||
col.set_sort_column_id(value)
|
||||
|
||||
def get_renderer(self, colnum):
|
||||
return self.__view.get_column(colnum).get_cell_renderers()[0]
|
||||
with compat.py3safe():
|
||||
return self.__view.get_column(colnum).get_cell_renderers()[0]
|
||||
|
||||
|
||||
class ListWidget(gtk.HBox):
|
||||
|
20
chirpw
20
chirpw
@ -15,14 +15,30 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import glob
|
||||
import os
|
||||
import six
|
||||
|
||||
if six.PY3:
|
||||
from gi import pygtkcompat
|
||||
pygtkcompat.enable()
|
||||
pygtkcompat.enable_gtk(version='3.0')
|
||||
|
||||
from chirp import logger
|
||||
from chirp import elib_intl
|
||||
from chirp import platform
|
||||
from chirp.drivers import *
|
||||
from chirp.ui import config
|
||||
|
||||
# Safe import of everything in chirp/drivers
|
||||
driver_files = glob.glob('chirp/drivers/*.py')
|
||||
for driver_file in driver_files:
|
||||
module, _ = os.path.splitext(driver_file)
|
||||
module = module.replace('/', '.')
|
||||
try:
|
||||
__import__(module)
|
||||
except Exception as e:
|
||||
print('Failed to import %s: %s' % (module, e))
|
||||
|
||||
|
||||
import sys
|
||||
import os
|
||||
@ -99,7 +115,7 @@ except:
|
||||
vmaj, vmin = pyver.split(".", 2)
|
||||
vrel = 0
|
||||
|
||||
if int(vmaj) < 2 or int(vmin) < 6:
|
||||
if int(vmaj) == 2 and int(vmin) < 6:
|
||||
# Python <2.6, emulate str.format()
|
||||
import __builtin__
|
||||
|
||||
|
@ -1 +1,2 @@
|
||||
six
|
||||
PyGObject
|
||||
|
Loading…
Reference in New Issue
Block a user