# HG changeset patch # User Dan Smith dsmith@danplanet.com # Date 1364855446 25200 # Node ID a11f2427091df6e0a0a2a6fe5fb1c1956333eb58 # Parent 66f225bbeb996964b922ef37800224fc76611870 [RFC] Abstract Bank and BankModel to MemoryMapping and MappingModel
This is mostly just a search-and-replace for the above names, but makes way for supporting things like scan lists that behave exactly the same way.
Updated with unit tests, fixes needed to import_logic, and a change to add a name property to the model so we can adjust the UI's naming of models like Scan Lists and Banks separately.
diff -r 66f225bbeb99 -r a11f2427091d chirp/chirp_common.py --- a/chirp/chirp_common.py Mon Apr 01 13:45:17 2013 -0700 +++ b/chirp/chirp_common.py Mon Apr 01 15:30:46 2013 -0700 @@ -543,8 +543,8 @@ except Exception: self.dv_code = 0
-class Bank: - """Base class for a radio's Bank""" +class MemoryMapping(object): + """Base class for a memory mapping""" def __init__(self, model, index, name): self._model = model self._index = index @@ -554,75 +554,87 @@ return self.get_name()
def __repr__(self): - return "Bank-%s" % self._index + return "%s-%s" % (self.__class__.__name__, self._index)
def get_name(self): - """Returns the static or user-adjustable bank name""" + """Returns the mapping name""" return self._name
def get_index(self): - """Returns the immutable bank index (string or int)""" + """Returns the immutable index (string or int)""" return self._index
def __eq__(self, other): return self.get_index() == other.get_index()
+class MappingModel(object): + """Base class for a memory mapping model""" + + def __init__(self, radio, name): + self._radio = radio + self._name = name + + def get_name(self): + return self._name + + def get_num_mappings(self): + """Returns the number of mappings in the model (should be + callable without consulting the radio""" + raise NotImplementedError() + + def get_mappings(self): + """Return a list of mappings""" + raise NotImplementedError() + + def add_memory_to_mapping(self, memory, mapping): + """Add @memory to @mapping.""" + raise NotImplementedError() + + def remove_memory_from_mapping(self, memory, mapping): + """Remove @memory from @mapping. + Shall raise exception if @memory is not in @bank""" + raise NotImplementedError() + + def get_mapping_memories(self, mapping): + """Return a list of memories in @mapping""" + raise NotImplementedError() + + def get_memory_mappings(self, memory): + """Return a list of mappings that @memory is in""" + raise NotImplementedError() + +class Bank(MemoryMapping): + """Base class for a radio's Bank""" + class NamedBank(Bank): """A bank that can have a name""" def set_name(self, name): """Changes the user-adjustable bank name""" self._name = name
-class BankModel: +class BankModel(MappingModel): """A bank model where one memory is in zero or one banks at any point""" def __init__(self, radio): - self._radio = radio + super(BankModel, self).__init__(radio, 'Banks')
- def get_num_banks(self): - """Returns the number of banks (should be callable without - consulting the radio""" - raise Exception("Not implemented") +class MappingModelIndexInterface: + """Interface for mappings with index capabilities""" + def get_index_bounds(self): + """Returns a tuple (lo,hi) of the min and max mapping indices""" + raise NotImplementedError()
- def get_banks(self): - """Return a list of banks""" - raise Exception("Not implemented") + def get_memory_index(self, memory, mapping): + """Returns the index of @memory in @mapping""" + raise NotImplementedError()
- def add_memory_to_bank(self, memory, bank): - """Add @memory to @bank.""" - raise Exception("Not implemented") + def set_memory_index(self, memory, mapping, index): + """Sets the index of @memory in @mapping to @index""" + raise NotImplementedError()
- def remove_memory_from_bank(self, memory, bank): - """Remove @memory from @bank. - Shall raise exception if @memory is not in @bank.""" - raise Exception("Not implemented") - - def get_bank_memories(self, bank): - """Return a list of memories in @bank""" - raise Exception("Not implemented") - - def get_memory_banks(self, memory): - """Returns a list of the banks that @memory is in""" - raise Exception("Not implemented") - -class BankIndexInterface: - """Interface for banks with index capabilities""" - def get_index_bounds(self): - """Returns a tuple (lo,hi) of the minimum and maximum bank indices""" - raise Exception("Not implemented") - - def get_memory_index(self, memory, bank): - """Returns the index of @memory in @bank""" - raise Exception("Not implemented") - - def set_memory_index(self, memory, bank, index): - """Sets the index of @memory in @bank to @index""" - raise Exception("Not implemented") - - def get_next_bank_index(self, bank): - """Returns the next available bank index in @bank, or raises + def get_next_mapping_index(self, mapping): + """Returns the next available mapping index in @mapping, or raises Exception if full""" - raise Exception("Not implemented") - + raise NotImplementedError()
class MTOBankModel(BankModel): """A bank model where one memory can be in multiple banks at once """ diff -r 66f225bbeb99 -r a11f2427091d chirp/ft7800.py --- a/chirp/ft7800.py Mon Apr 01 13:45:17 2013 -0700 +++ b/chirp/ft7800.py Mon Apr 01 15:30:46 2013 -0700 @@ -336,7 +336,7 @@ class FT7800BankModel(chirp_common.BankModel): """Yaesu FT-7800/7900 bank model""" def __init__(self, radio): - chirp_common.BankModel.__init__(self, radio) + super(FT7800BankModel, self).__init__(radio) self.__b2m_cache = defaultdict(list) self.__m2b_cache = defaultdict(list)
@@ -344,24 +344,24 @@ if self.__b2m_cache: return
- for bank in self.get_banks(): + for bank in self.get_mappings(): self.__b2m_cache[bank.index] = self._get_bank_memories(bank) for memnum in self.__b2m_cache[bank.index]: self.__m2b_cache[memnum].append(bank.index)
- def get_num_banks(self): + def get_num_mappings(self): return 20
- def get_banks(self): + def get_mappings(self): banks = [] - for i in range(0, self.get_num_banks()): + for i in range(0, self.get_num_mappings()): bank = chirp_common.Bank(self, "%i" % i, "BANK-%i" % (i + 1)) bank.index = i banks.append(bank)
return banks
- def add_memory_to_bank(self, memory, bank): + def add_memory_to_mapping(self, memory, bank): self.__precache()
index = memory.number - 1 @@ -371,7 +371,7 @@ self.__m2b_cache[memory.number].append(bank.index) self.__b2m_cache[bank.index].append(memory.number)
- def remove_memory_from_bank(self, memory, bank): + def remove_memory_from_mapping(self, memory, bank): self.__precache()
index = memory.number - 1 @@ -395,16 +395,16 @@ memories.append(i + 1) return memories
- def get_bank_memories(self, bank): + def get_mapping_memories(self, bank): self.__precache()
return [self._radio.get_memory(n) for n in self.__b2m_cache[bank.index]]
- def get_memory_banks(self, memory): + def get_memory_mappings(self, memory): self.__precache()
- _banks = self.get_banks() + _banks = self.get_mappings() return [_banks[b] for b in self.__m2b_cache[memory.number]]
@directory.register @@ -473,7 +473,7 @@ """
class FT8800BankModel(FT7800BankModel): - def get_num_banks(self): + def get_num_mappings(self): return 10
@directory.register diff -r 66f225bbeb99 -r a11f2427091d chirp/icf.py --- a/chirp/icf.py Mon Apr 01 13:45:17 2013 -0700 +++ b/chirp/icf.py Mon Apr 01 15:30:46 2013 -0700 @@ -485,10 +485,10 @@ central implementation can, with a few icom-specific radio interfaces serve most/all of them"""
- def get_num_banks(self): + def get_num_mappings(self): return self._radio._num_banks
- def get_banks(self): + def get_mappings(self): banks = []
for i in range(0, self._radio._num_banks): @@ -498,31 +498,32 @@ banks.append(bank) return banks
- def add_memory_to_bank(self, memory, bank): + def add_memory_to_mapping(self, memory, bank): self._radio._set_bank(memory.number, bank.index)
- def remove_memory_from_bank(self, memory, bank): + def remove_memory_from_mapping(self, memory, bank): if self._radio._get_bank(memory.number) != bank.index: raise Exception("Memory %i not in bank %s. Cannot remove." % \ (memory.number, bank))
self._radio._set_bank(memory.number, None)
- def get_bank_memories(self, bank): + def get_mapping_memories(self, bank): memories = [] for i in range(*self._radio.get_features().memory_bounds): if self._radio._get_bank(i) == bank.index: memories.append(self._radio.get_memory(i)) return memories
- def get_memory_banks(self, memory): + def get_memory_mappings(self, memory): index = self._radio._get_bank(memory.number) if index is None: return [] else: - return [self.get_banks()[index]] + return [self.get_mappings()[index]]
-class IcomIndexedBankModel(IcomBankModel, chirp_common.BankIndexInterface): +class IcomIndexedBankModel(IcomBankModel, + chirp_common.MappingModelIndexInterface): """Generic bank model for Icom radios with indexed banks""" def get_index_bounds(self): return self._radio._bank_index_bounds @@ -531,7 +532,7 @@ return self._radio._get_bank_index(memory.number)
def set_memory_index(self, memory, bank, index): - if bank not in self.get_memory_banks(memory): + if bank not in self.get_memory_mappings(memory): raise Exception("Memory %i is not in bank %s" % (memory.number, bank))
@@ -539,7 +540,7 @@ raise Exception("Invalid index") self._radio._set_bank_index(memory.number, index)
- def get_next_bank_index(self, bank): + def get_next_mapping_index(self, bank): indexes = [] for i in range(*self._radio.get_features().memory_bounds): if self._radio._get_bank(i) == bank.index: diff -r 66f225bbeb99 -r a11f2427091d chirp/import_logic.py --- a/chirp/import_logic.py Mon Apr 01 13:45:17 2013 -0700 +++ b/chirp/import_logic.py Mon Apr 01 15:30:46 2013 -0700 @@ -219,27 +219,27 @@ if not dst_bm: return
- dst_banks = dst_bm.get_banks() + dst_banks = dst_bm.get_mappings()
src_bm = src_radio.get_bank_model() if not src_bm: return
- src_banks = src_bm.get_banks() - src_mem_banks = src_bm.get_memory_banks(src_mem) + src_banks = src_bm.get_mappings() + src_mem_banks = src_bm.get_memory_mappings(src_mem) src_indexes = [src_banks.index(b) for b in src_mem_banks]
- for bank in dst_bm.get_memory_banks(dst_mem): - dst_bm.remove_memory_from_bank(dst_mem, bank) + for bank in dst_bm.get_memory_mappings(dst_mem): + dst_bm.remove_memory_from_mapping(dst_mem, bank)
for index in src_indexes: try: bank = dst_banks[index] print "Adding memory to bank %s" % bank - dst_bm.add_memory_to_bank(dst_mem, bank) - if isinstance(dst_bm, chirp_common.BankIndexInterface): + dst_bm.add_memory_to_mapping(dst_mem, bank) + if isinstance(dst_bm, chirp_common.MappingModelIndexInterface): dst_bm.set_memory_index(dst_mem, bank, - dst_bm.get_next_bank_index(bank)) + dst_bm.get_next_mapping_index(bank))
except IndexError: pass diff -r 66f225bbeb99 -r a11f2427091d chirp/vx3.py --- a/chirp/vx3.py Mon Apr 01 13:45:17 2013 -0700 +++ b/chirp/vx3.py Mon Apr 01 15:30:46 2013 -0700 @@ -110,10 +110,10 @@
class VX3BankModel(chirp_common.BankModel): """A VX-3 bank model""" - def get_num_banks(self): + def get_num_mappings(self): return 24
- def get_banks(self): + def get_mappings(self): _banks = self._radio._memobj.bank_names
banks = [] diff -r 66f225bbeb99 -r a11f2427091d chirp/vx5.py --- a/chirp/vx5.py Mon Apr 01 13:45:17 2013 -0700 +++ b/chirp/vx5.py Mon Apr 01 15:30:46 2013 -0700 @@ -82,18 +82,18 @@ chirp_common.PowerLevel("L1", watts=0.05)]
class VX5BankModel(chirp_common.BankModel): - def get_num_banks(self): + def get_num_mappings(self): return 5
- def get_banks(self): + def get_mappings(self): banks = [] - for i in range(0, self.get_num_banks()): + for i in range(0, self.get_num_mappings()): bank = chirp_common.Bank(self, "%i" % (i+1), "MG%i" % (i+1)) bank.index = i banks.append(bank) return banks
- def add_memory_to_bank(self, memory, bank): + def add_memory_to_mapping(self, memory, bank): _members = self._radio._memobj.bank_groups[bank.index].members _bank_used = self._radio._memobj.bank_used[bank.index] for i in range(0, len(_members)): @@ -107,7 +107,7 @@ return True raise Exception(_("{bank} is full").format(bank=bank))
- def remove_memory_from_bank(self, memory, bank): + def remove_memory_from_mapping(self, memory, bank): _members = self._radio._memobj.bank_groups[bank.index].members _bank_used = self._radio._memobj.bank_used[bank.index]
@@ -128,7 +128,7 @@ if not remaining_members: _bank_used.current_member = 0xFF
- def get_bank_memories(self, bank): + def get_mapping_memories(self, bank): memories = []
_members = self._radio._memobj.bank_groups[bank.index].members @@ -143,10 +143,11 @@ memories.append(self._radio.get_memory(member.channel+1)) return memories
- def get_memory_banks(self, memory): + def get_memory_mappings(self, memory): banks = [] - for bank in self.get_banks(): - if memory.number in [x.number for x in self.get_bank_memories(bank)]: + for bank in self.get_mappings(): + if memory.number in [x.number for x in + self.get_mapping_memories(bank)]: banks.append(bank) return banks
diff -r 66f225bbeb99 -r a11f2427091d chirp/vx7.py --- a/chirp/vx7.py Mon Apr 01 13:45:17 2013 -0700 +++ b/chirp/vx7.py Mon Apr 01 15:30:46 2013 -0700 @@ -103,18 +103,18 @@
class VX7BankModel(chirp_common.BankModel): """A VX-7 Bank model""" - def get_num_banks(self): + def get_num_mappings(self): return 9
- def get_banks(self): + def get_mappings(self): banks = [] - for i in range(0, self.get_num_banks()): + for i in range(0, self.get_num_mappings()): bank = chirp_common.Bank(self, "%i" % (i+1), "MG%i" % (i+1)) bank.index = i banks.append(bank) return banks
- def add_memory_to_bank(self, memory, bank): + def add_memory_to_mapping(self, memory, bank): _members = self._radio._memobj.bank_members[bank.index] _bank_used = self._radio._memobj.bank_used[bank.index] for i in range(0, 48): @@ -123,7 +123,7 @@ _bank_used.in_use = 0x0000 break
- def remove_memory_from_bank(self, memory, bank): + def remove_memory_from_mapping(self, memory, bank): _members = self._radio._memobj.bank_members[bank.index].members _bank_used = self._radio._memobj.bank_used[bank.index]
@@ -143,7 +143,7 @@ if not remaining_members: _bank_used.in_use = 0xFFFF
- def get_bank_memories(self, bank): + def get_mapping_memories(self, bank): memories = []
_members = self._radio._memobj.bank_members[bank.index].members @@ -158,11 +158,11 @@ memories.append(self._radio.get_memory(number+1)) return memories
- def get_memory_banks(self, memory): + def get_memory_mappings(self, memory): banks = [] - for bank in self.get_banks(): + for bank in self.get_mappings(): if memory.number in [x.number for x in - self.get_bank_memories(bank)]: + self.get_mapping_memories(bank)]: banks.append(bank) return banks
diff -r 66f225bbeb99 -r a11f2427091d chirp/vx8.py --- a/chirp/vx8.py Mon Apr 01 13:45:17 2013 -0700 +++ b/chirp/vx8.py Mon Apr 01 15:30:46 2013 -0700 @@ -151,10 +151,10 @@
class VX8BankModel(chirp_common.BankModel): """A VX-8 bank model""" - def get_num_banks(self): + def get_num_mappings(self): return 24
- def get_banks(self): + def get_mappings(self): banks = [] _banks = self._radio._memobj.bank_info
@@ -174,7 +174,7 @@ flags = self._radio._memobj.flag
# Find a suitable bank and MR for VFO A and B. - for bank in self.get_banks(): + for bank in self.get_mappings(): bank_used = self._radio._memobj.bank_used[bank.index] if bank_used != 0xFFFF: members = self._radio._memobj.bank_members[bank.index] @@ -213,7 +213,7 @@ vfo_bak.mr_index = vfo.mr_index vfo_bak.bank_enable = vfo.bank_enable
- def add_memory_to_bank(self, memory, bank): + def add_memory_to_mapping(self, memory, bank): _members = self._radio._memobj.bank_members[bank.index] _bank_used = self._radio._memobj.bank_used[bank.index] for i in range(0, 100): @@ -224,7 +224,7 @@
self.update_vfo()
- def remove_memory_from_bank(self, memory, bank): + def remove_memory_from_mapping(self, memory, bank): _members = self._radio._memobj.bank_members[bank.index] _bank_used = self._radio._memobj.bank_used[bank.index]
@@ -246,7 +246,7 @@
self.update_vfo()
- def get_bank_memories(self, bank): + def get_mapping_memories(self, bank): memories = [] _members = self._radio._memobj.bank_members[bank.index] _bank_used = self._radio._memobj.bank_used[bank.index] @@ -260,11 +260,11 @@
return memories
- def get_memory_banks(self, memory): + def get_memory_mappings(self, memory): banks = [] - for bank in self.get_banks(): + for bank in self.get_mappings(): if memory.number in \ - [x.number for x in self.get_bank_memories(bank)]: + [x.number for x in self.get_mapping_memories(bank)]: banks.append(bank)
return banks diff -r 66f225bbeb99 -r a11f2427091d chirpui/bankedit.py --- a/chirpui/bankedit.py Mon Apr 01 13:45:17 2013 -0700 +++ b/chirpui/bankedit.py Mon Apr 01 15:30:46 2013 -0700 @@ -22,68 +22,70 @@ from chirp import chirp_common from chirpui import common, miscwidgets
-class BankNamesJob(common.RadioJob): - def __init__(self, bm, editor, cb): +class MappingNamesJob(common.RadioJob): + def __init__(self, model, editor, cb): common.RadioJob.__init__(self, cb, None) - self.__bm = bm + self.__model = model self.__editor = editor
def execute(self, radio): - self.__editor.banks = [] + self.__editor.mappings = []
- banks = self.__bm.get_banks() - for bank in banks: - self.__editor.banks.append((bank, bank.get_name())) + mappings = self.__model.get_mappings() + for mapping in mappings: + self.__editor.mappings.append((mapping, mapping.get_name()))
gobject.idle_add(self.cb, *self.cb_args)
-class BankNameEditor(common.Editor): +class MappingNameEditor(common.Editor): + TYPE = _("Mapping") + def refresh(self): - def got_banks(): + def got_mappings(): self._keys = [] - for bank, name in self.banks: - self._keys.append(bank.get_index()) - self.listw.set_item(bank.get_index(), - bank.get_index(), + for mapping, name in self.mappings: + self._keys.append(mapping.get_index()) + self.listw.set_item(mapping.get_index(), + mapping.get_index(), name)
- self.listw.connect("item-set", self.bank_changed) + self.listw.connect("item-set", self.mapping_changed)
- job = BankNamesJob(self._bm, self, got_banks) - job.set_desc(_("Retrieving bank information")) + job = MappingNamesJob(self._model, self, got_mappings) + job.set_desc(_("Retrieving %s information") % self.TYPE) self.rthread.submit(job)
- def get_bank_list(self): - banks = [] + def get_mapping_list(self): + mappings = [] keys = self.listw.get_keys() for key in keys: - banks.append(self.listw.get_item(key)[2]) + mappings.append(self.listw.get_item(key)[2])
- return banks - - def bank_changed(self, listw, key): + return mappings + + def mapping_changed(self, listw, key): def cb(*args): self.emit("changed")
name = self.listw.get_item(key)[2] - bank, oldname = self.banks[self._keys.index(key)] + mapping, oldname = self.mappings[self._keys.index(key)]
def trigger_changed(*args): self.emit("changed")
job = common.RadioJob(trigger_changed, "set_name", name) - job.set_target(bank) - job.set_desc(_("Setting name on bank")) + job.set_target(mapping) + job.set_desc(_("Setting name on %s") % self.TYPE.lower()) self.rthread.submit(job)
return True
- def __init__(self, rthread): - super(BankNameEditor, self).__init__(rthread) - self._bm = rthread.radio.get_bank_model() + def __init__(self, rthread, model): + super(MappingNameEditor, self).__init__(rthread) + self._model = model
types = [(gobject.TYPE_STRING, "key"), - (gobject.TYPE_STRING, _("Bank")), + (gobject.TYPE_STRING, self.TYPE), (gobject.TYPE_STRING, _("Name"))]
self.listw = miscwidgets.KeyedListWidget(types) @@ -92,7 +94,7 @@ self.listw.set_sort_column(1, -1) self.listw.show()
- self.banks = [] + self.mappings = []
sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) @@ -108,51 +110,61 @@ self.refresh() self._loaded = True
-class MemoryBanksJob(common.RadioJob): - def __init__(self, bm, cb, number): +class BankNameEditor(MappingNameEditor): + TYPE = _("Bank") + + def __init__(self, rthread): + model = rthread.radio.get_bank_model() + super(BankNameEditor, self).__init__(rthread, model) + +class MemoryMappingsJob(common.RadioJob): + def __init__(self, model, cb, number): common.RadioJob.__init__(self, cb, None) - self.__bm = bm + self.__model = model self.__number = number
def execute(self, radio): mem = radio.get_memory(self.__number) if mem.empty: - banks = [] + mappings = [] indexes = [] else: - banks = self.__bm.get_memory_banks(mem) + mappings = self.__model.get_memory_mappings(mem) indexes = [] - if isinstance(self.__bm, chirp_common.BankIndexInterface): - for bank in banks: - indexes.append(self.__bm.get_memory_index(mem, bank)) - self.cb(mem, banks, indexes, *self.cb_args) + if isinstance(self.__model, + chirp_common.MappingModelIndexInterface): + for mapping in mappings: + indexes.append(self.__model.get_memory_index(mem, mapping)) + self.cb(mem, mappings, indexes, *self.cb_args)
-class BankMembershipEditor(common.Editor): +class MappingMembershipEditor(common.Editor): + TYPE = _("Mapping") + def _number_to_path(self, number): return (number - self._rf.memory_bounds[0],)
- def _get_next_bank_index(self, bank): - # NB: Only works for one-to-one bank models right now! + def _get_next_mapping_index(self, mapping): + # NB: Only works for one-to-one models right now! iter = self._store.get_iter_first() indexes = [] - ncols = len(self._cols) + len(self.banks) + ncols = len(self._cols) + len(self.mappings) while iter: vals = self._store.get(iter, *tuple([n for n in range(0, ncols)])) loc = vals[self.C_LOC] index = vals[self.C_INDEX] - banks = vals[self.C_BANKS:] - if True in banks and banks.index(True) == bank: + mappings = vals[self.C_MAPPINGS:] + if True in mappings and mappings.index(True) == mapping: indexes.append(index) iter = self._store.iter_next(iter)
- index_bounds = self._bm.get_index_bounds() + index_bounds = self._model.get_index_bounds() num_indexes = index_bounds[1] - index_bounds[0] indexes.sort() for i in range(0, num_indexes): if i not in indexes: return i + index_bounds[0] # In case not zero-origin index
- return 0 # If the bank is full, just wrap around! + return 0 # If the mapping is full, just wrap around!
def _toggled_cb(self, rend, path, colnum): try: @@ -164,56 +176,60 @@ if not self._store.get(iter, self.C_FILLED)[0]: return
- # The bank index is the column number, minus the 3 label columns - bank, name = self.banks[colnum - len(self._cols)] + # The mapping index is the column number, minus the 3 label columns + mapping, name = self.mappings[colnum - len(self._cols)] loc, = self._store.get(self._store.get_iter(path), self.C_LOC)
+ is_indexed = isinstance(self._model, + chirp_common.MappingModelIndexInterface) + if rend.get_active(): # Changing from True to False - fn = "remove_memory_from_bank" + fn = "remove_memory_from_mapping" index = None else: # Changing from False to True - fn = "add_memory_to_bank" - if self._rf.has_bank_index: - index = self._get_next_bank_index(colnum - len(self._cols)) + fn = "add_memory_to_mapping" + if is_indexed: + index = self._get_next_mapping_index(colnum - len(self._cols)) else: index = None
def do_refresh_memory(*args): - # Step 2: Update our notion of the memory's bank information + # Step 2: Update our notion of the memory's mapping information self.refresh_memory(loc)
- def do_bank_index(result, memory): + def do_mapping_index(result, memory): if isinstance(result, Exception): - common.show_error("Failed to add {mem} to bank: {err}" + common.show_error("Failed to add {mem} to mapping: {err}" .format(mem=memory.number, err=str(result)), parent=self.editorset.parent_window) return self.emit("changed") - # Step 3: Set the memory's bank index (maybe) - if not self._rf.has_bank_index or index is None: + # Step 3: Set the memory's mapping index (maybe) + if not is_indexed or index is None: return do_refresh_memory()
job = common.RadioJob(do_refresh_memory, - "set_memory_index", memory, bank, index) - job.set_target(self._bm) - job.set_desc(_("Updating bank index " - "for memory {num}").format(num=memory.number)) + "set_memory_index", memory, mapping, index) + job.set_target(self._model) + job.set_desc(_("Updating {type} index " + "for memory {num}").format(type=self.TYPE, + num=memory.number)) self.rthread.submit(job)
- def do_bank_adjustment(memory): - # Step 1: Do the bank add/remove - job = common.RadioJob(do_bank_index, fn, memory, bank) - job.set_target(self._bm) + def do_mapping_adjustment(memory): + # Step 1: Do the mapping add/remove + job = common.RadioJob(do_mapping_index, fn, memory, mapping) + job.set_target(self._model) job.set_cb_args(memory) - job.set_desc(_("Updating bank information " + job.set_desc(_("Updating mapping information " "for memory {num}").format(num=memory.number)) self.rthread.submit(job)
# Step 0: Fetch the memory - job = common.RadioJob(do_bank_adjustment, "get_memory", loc) + job = common.RadioJob(do_mapping_adjustment, "get_memory", loc) job.set_desc(_("Getting memory {num}").format(num=loc)) self.rthread.submit(job)
@@ -223,36 +239,37 @@ def refresh_memory(*args): self.refresh_memory(loc)
- def set_index(banks, memory): + def set_index(mappings, memory): self.emit("changed") # Step 2: Set the index job = common.RadioJob(refresh_memory, "set_memory_index", - memory, banks[0], int(new)) - job.set_target(self._bm) + memory, mappings[0], int(new)) + job.set_target(self._model) job.set_desc(_("Setting index " "for memory {num}").format(num=memory.number)) self.rthread.submit(job)
- def get_bank(memory): - # Step 1: Get the first/only bank - job = common.RadioJob(set_index, "get_memory_banks", memory) + def get_mapping(memory): + # Step 1: Get the first/only mapping + job = common.RadioJob(set_index, "get_memory_mappings", memory) job.set_cb_args(memory) - job.set_target(self._bm) - job.set_desc(_("Getting bank for " - "memory {num}").format(num=memory.number)) + job.set_target(self._model) + job.set_desc(_("Getting {type} for " + "memory {num}").format(type=self.TYPE, + num=memory.number)) self.rthread.submit(job)
# Step 0: Get the memory - job = common.RadioJob(get_bank, "get_memory", loc) + job = common.RadioJob(get_mapping, "get_memory", loc) job.set_desc(_("Getting memory {num}").format(num=loc)) self.rthread.submit(job)
- def __init__(self, rthread, editorset): - super(BankMembershipEditor, self).__init__(rthread) + def __init__(self, rthread, editorset, model): + super(MappingMembershipEditor, self).__init__(rthread)
self.editorset = editorset self._rf = rthread.radio.get_features() - self._bm = rthread.radio.get_bank_model() + self._model = model
self._view_cols = [ (_("Loc"), TYPE_INT, gtk.CellRendererText, ), @@ -270,19 +287,22 @@ self.C_FREQ = 2 self.C_NAME = 3 self.C_INDEX = 4 - self.C_BANKS = 5 # and beyond + self.C_MAPPINGS = 5 # and beyond
cols = list(self._cols)
self._index_cache = []
- for i in range(0, self._bm.get_num_banks()): - label = "Bank %i" % (i+1) + for i in range(0, self._model.get_num_mappings()): + label = "%s %i" % (self.TYPE, (i+1)) cols.append((label, TYPE_BOOLEAN, gtk.CellRendererToggle))
self._store = gtk.ListStore(*tuple([y for x,y,z in cols])) self._view = gtk.TreeView(self._store)
+ is_indexed = isinstance(self._model, + chirp_common.MappingModelIndexInterface) + colnum = 0 for label, dtype, rtype in cols: if not rtype: @@ -305,7 +325,7 @@ elif colnum == self.C_INDEX: rend.set_property("editable", True) rend.connect("edited", self._index_edited_cb) - col.set_visible(self._rf.has_bank_index) + col.set_visible(is_indexed) colnum += 1
# A non-rendered column to absorb extra space in the row @@ -329,7 +349,7 @@ self._loaded = False
def refresh_memory(self, number): - def got_mem(memory, banks, indexes): + def got_mem(memory, mappings, indexes): iter = self._store.get_iter(self._number_to_path(memory.number)) row = [self.C_FILLED, not memory.empty, self.C_LOC, memory.number, @@ -338,29 +358,30 @@ # Hack for only one index right now self.C_INDEX, indexes and indexes[0] or 0, ] - for i in range(0, len(self.banks)): + for i in range(0, len(self.mappings)): row.append(i + len(self._cols)) - row.append(self.banks[i][0] in banks) + row.append(self.mappings[i][0] in mappings)
self._store.set(iter, *tuple(row)) if memory.number == self._rf.memory_bounds[1] - 1: - print "Got all bank info in %s" % (time.time() - self._start) + print "Got all %s info in %s" % (self.TYPE, + (time.time() - self._start))
- job = MemoryBanksJob(self._bm, got_mem, number) - job.set_desc(_("Getting bank information " - "for memory {num}").format(num=number)) + job = MemoryMappingsJob(self._model, got_mem, number) + job.set_desc(_("Getting {type} information " + "for memory {num}").format(type=self.TYPE, num=number)) self.rthread.submit(job)
def refresh_all_memories(self): for i in range(*self._rf.memory_bounds): self.refresh_memory(i)
- def refresh_banks(self, and_memories=False): - def got_banks(): + def refresh_mappings(self, and_memories=False): + def got_mappings(): for i in range(len(self._cols) - len(self._view_cols) - 1, - len(self.banks)): + len(self.mappings)): col = self._view.get_column(i + len(self._view_cols)) - bank, name = self.banks[i] + mapping, name = self.mappings[i] if name: col.set_title(name) else: @@ -368,8 +389,8 @@ if and_memories: self.refresh_all_memories()
- job = BankNamesJob(self._bm, self, got_banks) - job.set_desc(_("Getting bank information")) + job = MappingNamesJob(self._model, self, got_mappings) + job.set_desc(_("Getting %s information") % self.TYPE) self.rthread.submit(job)
def focus(self): @@ -378,7 +399,7 @@ return
self._start = time.time() - self.refresh_banks(True) + self.refresh_mappings(True)
self._loaded = True
@@ -387,5 +408,15 @@ if self.is_focused(): self.refresh_all_memories()
+ def mappings_changed(self): + self.refresh_mappings() + +class BankMembershipEditor(MappingMembershipEditor): + TYPE = _("Bank") + + def __init__(self, rthread, editorset): + model = rthread.radio.get_bank_model() + super(BankMembershipEditor, self).__init__(rthread, editorset, model) + def banks_changed(self): - self.refresh_banks() + self.mappings_changed() diff -r 66f225bbeb99 -r a11f2427091d tests/unit/test_import_logic.py --- a/tests/unit/test_import_logic.py Mon Apr 01 13:45:17 2013 -0700 +++ b/tests/unit/test_import_logic.py Mon Apr 01 15:30:46 2013 -0700 @@ -349,21 +349,21 @@
self.mox.StubOutWithMock(dst_radio, 'get_bank_model') self.mox.StubOutWithMock(src_radio, 'get_bank_model') - self.mox.StubOutWithMock(dst_bm, 'get_banks') - self.mox.StubOutWithMock(src_bm, 'get_banks') - self.mox.StubOutWithMock(dst_bm, 'get_memory_banks') - self.mox.StubOutWithMock(src_bm, 'get_memory_banks') - self.mox.StubOutWithMock(dst_bm, 'remove_memory_from_bank') - self.mox.StubOutWithMock(dst_bm, 'add_memory_to_bank') + self.mox.StubOutWithMock(dst_bm, 'get_mappings') + self.mox.StubOutWithMock(src_bm, 'get_mappings') + self.mox.StubOutWithMock(dst_bm, 'get_memory_mappings') + self.mox.StubOutWithMock(src_bm, 'get_memory_mappings') + self.mox.StubOutWithMock(dst_bm, 'remove_memory_from_mapping') + self.mox.StubOutWithMock(dst_bm, 'add_memory_to_mapping')
dst_radio.get_bank_model().AndReturn(dst_bm) - dst_bm.get_banks().AndReturn(dst_banks) + dst_bm.get_mappings().AndReturn(dst_banks) src_radio.get_bank_model().AndReturn(src_bm) - src_bm.get_banks().AndReturn(src_banks) - src_bm.get_memory_banks(src_mem).AndReturn([src_banks[0]]) - dst_bm.get_memory_banks(dst_mem).AndReturn([dst_banks[1]]) - dst_bm.remove_memory_from_bank(dst_mem, dst_banks[1]) - dst_bm.add_memory_to_bank(dst_mem, dst_banks[0]) + src_bm.get_mappings().AndReturn(src_banks) + src_bm.get_memory_mappings(src_mem).AndReturn([src_banks[0]]) + dst_bm.get_memory_mappings(dst_mem).AndReturn([dst_banks[1]]) + dst_bm.remove_memory_from_mapping(dst_mem, dst_banks[1]) + dst_bm.add_memory_to_mapping(dst_mem, dst_banks[0])
self.mox.ReplayAll()
diff -r 66f225bbeb99 -r a11f2427091d tests/unit/test_mappingmodel.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/unit/test_mappingmodel.py Mon Apr 01 15:30:46 2013 -0700 @@ -0,0 +1,274 @@ +# Copyright 2013 Dan Smith dsmith@danplanet.com +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. + +from tests.unit import base +from chirp import chirp_common +from chirp import icf + +class TestBaseMapping(base.BaseTest): + CLS = chirp_common.MemoryMapping + + def test_mapping(self): + model = chirp_common.MappingModel(None, 'Foo') + mapping = self.CLS(model, 1, 'Foo') + self.assertEqual(str(mapping), 'Foo') + self.assertEqual(mapping.get_name(), 'Foo') + self.assertEqual(mapping.get_index(), 1) + self.assertEqual(repr(mapping), '%s-1' % self.CLS.__name__) + self.assertEqual(mapping._model, model) + + def test_mapping_eq(self): + mapping1 = self.CLS(None, 1, 'Foo') + mapping2 = self.CLS(None, 1, 'Bar') + mapping3 = self.CLS(None, 2, 'Foo') + + self.assertEqual(mapping1, mapping2) + self.assertNotEqual(mapping1, mapping3) + +class TestBaseBank(TestBaseMapping): + CLS = chirp_common.Bank + +class _TestBaseClass(base.BaseTest): + ARGS = tuple() + + def setUp(self): + super(_TestBaseClass, self).setUp() + self.model = self.CLS(*self.ARGS) + + def _test_base(self, method, *args): + self.assertRaises(NotImplementedError, + getattr(self.model, method), *args) + +class TestBaseMappingModel(_TestBaseClass): + CLS = chirp_common.MappingModel + ARGS = tuple([None, 'Foo']) + + def test_base_class(self): + methods = [('get_num_mappings', ()), + ('get_mappings', ()), + ('add_memory_to_mapping', (None, None)), + ('remove_memory_from_mapping', (None, None)), + ('get_mapping_memories', (None,)), + ('get_memory_mappings', (None,)), + ] + for method, args in methods: + self._test_base(method, *args) + + def test_get_name(self): + self.assertEqual(self.model.get_name(), 'Foo') + +class TestBaseBankModel(TestBaseMappingModel): + ARGS = tuple([None]) + CLS = chirp_common.BankModel + + def test_get_name(self): + self.assertEqual(self.model.get_name(), 'Banks') + +class TestBaseMappingModelIndexInterface(_TestBaseClass): + CLS = chirp_common.MappingModelIndexInterface + + def test_base_class(self): + methods = [('get_index_bounds', ()), + ('get_memory_index', (None, None)), + ('set_memory_index', (None, None, None)), + ('get_next_mapping_index', (None,)), + ] + for method, args in methods: + self._test_base(method, *args) + +class TestIcomBanks(TestBaseMapping): + def test_icom_bank(self): + bank = icf.IcomBank(None, 1, 'Foo') + # IcomBank has an index attribute used by IcomBankModel + self.assertTrue(hasattr(bank, 'index')) + +class TestIcomBankModel(base.BaseTest): + CLS = icf.IcomBankModel + + def _get_rf(self): + rf = chirp_common.RadioFeatures() + rf.memory_bounds = (1, 10) + return rf + + def setUp(self): + super(TestIcomBankModel, self).setUp() + + class FakeRadio(icf.IcomCloneModeRadio): + _num_banks = 10 + _bank_index_bounds = (0, 10) + + def get_features(the_radio): + return self._get_rf() + + def _set_bank(self, number, index): + pass + + def _get_bank(self, number): + pass + + def _get_bank_index(self, number): + pass + + def _set_bank_index(self, number, index): + pass + + def get_memory(self, number): + pass + + self._radio = FakeRadio(None) + self._model = self.CLS(self._radio) + self.mox.StubOutWithMock(self._radio, '_set_bank') + self.mox.StubOutWithMock(self._radio, '_get_bank') + self.mox.StubOutWithMock(self._radio, '_set_bank_index') + self.mox.StubOutWithMock(self._radio, '_get_bank_index') + self.mox.StubOutWithMock(self._radio, 'get_memory') + + def test_get_num_mappings(self): + self.assertEqual(self._model.get_num_mappings(), 10) + + def test_get_mappings(self): + banks = self._model.get_mappings() + self.assertEqual(len(banks), 10) + i = 0 + for bank in banks: + index = chr(ord("A") + i) + self.assertEqual(bank.get_index(), index) + self.assertEqual(bank.get_name(), 'BANK-%s' % index) + self.assertEqual(bank.index, i) + i += 1 + + def test_add_memory_to_mapping(self): + mem = chirp_common.Memory() + mem.number = 5 + banks = self._model.get_mappings() + bank = banks[2] + self._radio._set_bank(5, 2) + self.mox.ReplayAll() + self._model.add_memory_to_mapping(mem, bank) + + def _setup_test_remove_memory_from_mapping(self, curbank): + mem = chirp_common.Memory() + mem.number = 5 + banks = self._model.get_mappings() + bank = banks[2] + self._radio._get_bank(5).AndReturn(curbank) + if curbank == 2: + self._radio._set_bank(5, None) + self.mox.ReplayAll() + return mem, bank + + def test_remove_memory_from_mapping(self): + mem, bank = self._setup_test_remove_memory_from_mapping(2) + self._model.remove_memory_from_mapping(mem, bank) + + def test_remove_memory_from_mapping_wrong_bank(self): + mem, bank = self._setup_test_remove_memory_from_mapping(3) + self.assertRaises(Exception, + self._model.remove_memory_from_mapping, mem, bank) + + def test_remove_memory_from_mapping_no_bank(self): + mem, bank = self._setup_test_remove_memory_from_mapping(None) + self.assertRaises(Exception, + self._model.remove_memory_from_mapping, mem, bank) + + def test_get_mapping_memories(self): + banks = self._model.get_mappings() + expected = [] + for i in range(1, 10): + should_include = bool(i % 2) + self._radio._get_bank(i).AndReturn( + should_include and banks[1].index or None) + if should_include: + self._radio.get_memory(i).AndReturn(i) + expected.append(i) + self.mox.ReplayAll() + members = self._model.get_mapping_memories(banks[1]) + self.assertEqual(members, expected) + + def test_get_memory_mappings(self): + banks = self._model.get_mappings() + mem1 = chirp_common.Memory() + mem1.number = 5 + mem2 = chirp_common.Memory() + mem2.number = 6 + self._radio._get_bank(mem1.number).AndReturn(2) + self._radio._get_bank(mem2.number).AndReturn(None) + self.mox.ReplayAll() + self.assertEqual(self._model.get_memory_mappings(mem1)[0], banks[2]) + self.assertEqual(self._model.get_memory_mappings(mem2), []) + +class TestIcomIndexedBankModel(TestIcomBankModel): + CLS = icf.IcomIndexedBankModel + + def _get_rf(self): + rf = super(TestIcomIndexedBankModel, self)._get_rf() + rf.has_bank_index = True + return rf + + def test_get_index_bounds(self): + self.assertEqual(self._model.get_index_bounds(), (0, 10)) + + def test_get_memory_index(self): + mem = chirp_common.Memory() + mem.number = 5 + self._radio._get_bank_index(mem.number).AndReturn(1) + self.mox.ReplayAll() + self.assertEqual(self._model.get_memory_index(mem, None), 1) + + def test_set_memory_index(self): + mem = chirp_common.Memory() + mem.number = 5 + banks = self._model.get_mappings() + self.mox.StubOutWithMock(self._model, 'get_memory_mappings') + self._model.get_memory_mappings(mem).AndReturn([banks[3]]) + self._radio._set_bank_index(mem.number, 1) + self.mox.ReplayAll() + self._model.set_memory_index(mem, banks[3], 1) + + def test_set_memory_index_bad_bank(self): + mem = chirp_common.Memory() + mem.number = 5 + banks = self._model.get_mappings() + self.mox.StubOutWithMock(self._model, 'get_memory_mappings') + self._model.get_memory_mappings(mem).AndReturn([banks[4]]) + self.mox.ReplayAll() + self.assertRaises(Exception, + self._model.set_memory_index, mem, banks[3], 1) + + def test_set_memory_index_bad_index(self): + mem = chirp_common.Memory() + mem.number = 5 + banks = self._model.get_mappings() + self.mox.StubOutWithMock(self._model, 'get_memory_mappings') + self._model.get_memory_mappings(mem).AndReturn([banks[3]]) + self.mox.ReplayAll() + self.assertRaises(Exception, + self._model.set_memory_index, mem, banks[3], 99) + + def test_get_next_mapping_index(self): + banks = self._model.get_mappings() + for i in range(*self._radio.get_features().memory_bounds): + self._radio._get_bank(i).AndReturn((i % 2) and banks[1].index) + if bool(i % 2): + self._radio._get_bank_index(i).AndReturn(i) + idx = 0 + for i in range(*self._radio.get_features().memory_bounds): + self._radio._get_bank(i).AndReturn((i % 2) and banks[2].index) + if i % 2: + self._radio._get_bank_index(i).AndReturn(idx) + idx += 1 + self.mox.ReplayAll() + self.assertEqual(self._model.get_next_mapping_index(banks[1]), 0) + self.assertEqual(self._model.get_next_mapping_index(banks[2]), 5)