class TableNumpyDataList(AbstractTableDataList): CheckDataType = None DefaultDataType = None def __init__(self, data_id=None): self._data_id = data_id self.dtype = self.DefaultDataType.dtype self.blank_data = np.zeros(1, dtype=self.dtype) self.data = np.zeros(0, dtype=self.dtype) self._headers = list( self.data.dtype.names)[:self.DefaultDataType.columns()] self._ids = [] self.list_changed = MrSignal() def clear(self): self.data.resize(0) def get_data(self): return self.data.tolist() def load_data(self, data): np.copyto(self.data, data) def add(self, data=None): self.data.resize(self.data.size + 1, refcheck=False) if data is not None: self.data[-1] = data self.list_changed.emit() return self.data[-1] def remove(self, index): if isinstance(index, (list, tuple)): i1 = index[0] i2 = index[1] else: i1 = index i2 = index indices = list(range(i1, i2 + 1)) tmp = [] for i in indices: tmp.append(tuple(self.data[i])) self.data = np.delete(self.data, indices) self.list_changed.emit() return tmp def insert(self, index, data=None): if data is not None: assert isinstance(data, tuple) try: if isinstance(data[0], tuple): return self._insert_multiple(index, data) except IndexError: data = None if index < 0: index = 0 if index >= self.data.size: return None if data is None: data = tuple(self.blank_data[0]) self.data = np.insert(self.data, index, data) self.list_changed.emit() return self.data[index] def editable_columns(self): return set(range(len(self.headers))) def _insert_multiple(self, index, data): if index < 0: index = 0 if index >= len(self.data) + 1: raise IndexError('%d' % index) self.list_changed.block() for data_ in data: self.data = np.insert(self.data, index, data_) self.list_changed.unblock() self.list_changed.emit() return data def serialize(self): data_i = self.DefaultDataType(self, 0) for i in range(self.data.shape[0]): data_i.index = i data_i.serialize() return base64.b64encode(compress(self.data.tobytes())).decode() def load(self, data): try: self.data = np.fromstring(decompress( base64.b64decode(data.encode())), dtype=self.dtype) except ValueError: print('get rid of this') return data_i = self.DefaultDataType(self, 0) for i in range(self.data.shape[0]): data_i.index = i data_i.load(self.data[i]) # np.copyto(self._data, np.fromstring(base64.b64decode(data.encode()), dtype=self.dtype)) def __getitem__(self, index): if isinstance(index, str): index = self.ids().index(index) return self.DefaultDataType(self, index) def set_data(self, index, value): row, column = index _data = self.DefaultDataType(self, row) try: old_value = _data[column] _data[column] = value new_value = _data[column] if old_value != new_value: return True, old_value, new_value else: return False, None, None except (MyExceptions.IndexError, MyExceptions.ValueError): return False, None, None @show_caller def __setitem__(self, index, data): assert isinstance(data, tuple) self.data[index] = data def id_exists(self, id_): data_i = self.DefaultDataType(self, 0) for i in range(self.data.shape[0]): data_i.index = i if data_i.id == id_: return True return False def subdata(self, index): return None def has_subdata(self): return None def find_index(self, data_id): assert isinstance(data_id, str) data_i = self.DefaultDataType(self, 0) for i in range(self.data.shape[0]): data_i.index = i if data_i.id == data_id: return i return -1 def ids(self): data_i = self.DefaultDataType(self, 0) ids_ = [] for i in range(self.data.shape[0]): data_i.index = i ids_.append(data_i.id) return ids_ def _move(self, i1, i2): _data_i1 = tuple(self.data[i1]) _data_i2 = tuple(self.data[i2]) self.data[i1], self.data[i2] = _data_i2, _data_i1 del self._ids[:] self.list_changed.emit() def shape(self): return self.data.shape[0], self.DefaultDataType.columns() @property def size(self): return self.__len__() def __len__(self): return self.data.shape[0] def get_index(self, data): pass def get_id(self): pass def up(self, index): pass def down(self, index): pass def insert_multiple(self, index, data): pass def validate(self, *args): pass @property def headers(self): return self._headers def remove_multiple(self, count): pass def add_multiple(self, count, data=None): pass
class MainData(BaseObject): headers_1 = ['Data Id', 'Data Size'] headers_2 = ['Data'] def __init__(self): super(MainData, self).__init__() self.data = OrderedDict() self.data_keys = [] self.interface1 = MainDataInterface1(self) self.interface2 = MainDataInterface2(self) self.data_changed = MrSignal() def _update_keys(self): self.data_keys.clear() self.data_keys.extend(list(self.data.keys())) self.data_changed.emit(list(self.data_keys)) def rename(self, arg1, new_name_): if isinstance(arg1, int): old_name = self.data_keys[arg1] else: old_name = arg1 old_data = OrderedDict(self.data) self.data.clear() _data = self.data for key, data in iteritems(old_data): if old_name == key: key = new_name_ _data[key] = data self.data_changed.block() self._update_keys() self.data_changed.unblock() self.data_changed.emit(('rename', old_name, new_name_)) def add(self, name=None): name = new_name(self.data, name) self.data[name] = self._new_data() self._update_keys() self.interface2.set_index(len(self.data) - 1) def insert(self, index, name=None, data=None): if name in self.data: name = new_name(self.data, name) old_data = OrderedDict(self.data) print('insert', name) self.data.clear() _data = self.data if data is None: _new_data = self._new_data() else: _new_data = data found_data = False i = 0 for key, data in iteritems(old_data): if i == index: _data[name] = _new_data found_data = True _data[key] = data i += 1 if not found_data: _data[name] = _new_data self.data_changed.block() self._update_keys() self.data_changed.unblock() self.data_changed.emit(('insert', index, name)) self.interface2.set_index(index) def delete(self, index): old_data = OrderedDict(self.data) self.data.clear() _data = self.data index_ = index i = -1 for key, data in iteritems(old_data): i += 1 if i == index: continue _data[key] = data if index >= len(self.data): index -= 1 self.data_changed.block() self._update_keys() self.data_changed.unblock() self.data_changed.emit(('delete', index_)) self.interface2.set_index(index) def up(self, index): if index == 0: return False return self._move(index, index - 1) def down(self, index): if index == len(self.data) - 1: return False return self._move(index, index + 1) def _move(self, old_index, new_index): old_data = OrderedDict(self.data) old_keys = list(old_data.keys()) self.data.clear() _data = self.data key_old = old_keys[old_index] data_old = old_data[key_old] key_new = old_keys[new_index] data_new = old_data[key_new] i = -1 for key, data in iteritems(old_data): i += 1 if i == new_index: _data[key_old] = data_old continue elif i == old_index: _data[key_new] = data_new continue _data[key] = data self._update_keys() self.interface2.set_index(new_index) return True @staticmethod def columns(): return 1 def _new_data(self): return np.zeros((1, self.columns()), dtype=np.float64) def __len__(self): return len(self.data) def serialize(self): result = [] for key, data in iteritems(self.data): result.append((key, data.tostring())) return result def load(self, data): tmp = self._new_data() dtype = tmp.dtype cols = tmp.shape[1] for data_ in data: key, _data = data_ tmp = np.fromstring(_data, dtype=dtype) self.data[key] = np.array(tmp.reshape((tmp.size // cols, cols))) self._update_keys() def clear(self): self.data.clear() self._update_keys() def ids(self): return list(self.data_keys)
class TableDictList(AbstractTableDataList): CheckDataType = DummyTableData DefaultDataType = DummyTableData def __init__(self, data_id=None): self.data = {} """:type: dict[DummyTableData]""" self._headers = list(self.DefaultDataType.headers) self._data_id = data_id self.list_changed = MrSignal() self._ids = [] def clear(self): self.data.clear() del self._ids[:] def get_id(self): return self._data_id @property def headers(self): return self._headers def get_data(self): return list(self.data.values()) def load_data(self, data): self.data.clear() for _data in data: self.data[_data.id] = data self._update_ids() def add(self, *data): tmp = self.DefaultDataType() tmp.register_model(self.model) if len(data) > 0: tmp.load(data) self.data[tmp.id] = tmp self.list_changed.emit() del self._ids[:] return tmp def remove(self, index): try: tmp = self.data[index] del self.data[index] except MyExceptions.IndexError: return None self.list_changed.emit() return tmp def add_multiple(self, count, data=None): raise NotImplementedError result = [] self.list_changed.block() if isinstance(data, (list, tuple)): assert count == len(data) for data_i in data: result.append(self.add(data_i)) else: for i in range(count): result.append(self.add()) self.list_changed.unblock() if len(result) > 0: del self._ids[:] self.list_changed.emit() return result def remove_multiple(self, count): raise NotImplementedError result = [] self.list_changed.block() data_len = self.shape()[0] last_i = data_len for i in range(count): last_i -= 1 try: result.append(self.remove(last_i)[0]) except IndexError: pass self.list_changed.unblock() if len(result) > 0: del self._ids[:] self.list_changed.emit() return result def insert(self, index, *data): if len(data) > 1: tmp = self.DefaultDataType(*data) else: tmp = self.DefaultDataType() if index < 0: index = 0 try: self.data.insert(index, tmp) del self._ids[:] self.list_changed.emit() return tmp except MyExceptions.IndexError: return None def insert_multiple(self, index, data): if index < 0: index = 0 if index >= len(self.data) + 1: raise IndexError('%d' % index) self.list_changed.block() result = [] for data_ in data: result_ = self.data.insert(index, data_) if result_ is not None: result.append(result_) self.list_changed.unblock() if len(result) > 0: del self._ids[:] self.list_changed.emit() return result def shape(self): return len(self.data), len(self.headers) def editable_columns(self): return set(range(len(self.headers))) def set_data(self, index, value): row, column = index try: old_value = self.data[row][column] self.data[row][column] = value new_value = self.data[row][column] if old_value != new_value: del self._ids[:] print('data is valid 2') return True, old_value, new_value else: print('old and new values equal') return False, None, None except (MyExceptions.IndexError, MyExceptions.ValueError): print('index or value error') print(self.data[row]) return False, None, None def validate(self, *args): raise NotImplementedError def serialize(self): data = [] for data_i in self.data: data.append(data_i.serialize()) return data def load(self, data): self.list_changed.block() for data_i in data: self.add(data_i) self.list_changed.unblock() del self._ids[:] # self._update_ids() # make sure to update other data if needed def _move(self, i1, i2): self.data[i1], self.data[i2] = self.data[i2], self.data[i1] del self._ids[:] self.list_changed.emit() def up(self, index): if index <= 0 or index >= len(self.data): return False i1 = index i2 = index - 1 self._move(i1, i2) return True def down(self, index): if index < 0 or index >= len(self.data) - 1: return False i1 = index i2 = index + 1 self._move(i1, i2) return True def __len__(self): return len(self.data) def __getitem__(self, index): if isinstance(index, str): if index == '': return None index = self.ids().index(index) return self.data[index] @show_caller def __setitem__(self, index, data): assert isinstance(data, self.CheckDataType) # TODO: what to do here? self.data[index] = data def id_exists(self, id_): for data_i in self.data: if data_i.id == id_: return True return False def subdata(self, index): row, column = index try: return self.data[row].subdata(column) except (AttributeError, IndexError): return None def has_subdata(self): try: data = self.data[0] except IndexError: return None except KeyError: raise KeyError(self._data_id) for i in range(len(data)): try: subdata = data.subdata(i) if subdata is not None: return subdata except NotImplementedError: pass return None def find_index(self, data_id): if isinstance(data_id, str): data = self.data for i in range(len(data)): if data[i].id == data_id: return i elif isinstance(data_id, self.CheckDataType): data = self.data for i in range(len(data)): if data_id is data[i]: return i return -1 def get_index(self, data): return data def ids(self): if len(self._ids) == 0: self._update_ids() return list(self._ids) def _update_ids(self): del self._ids[:] _ids = self._ids for data in self.data: _ids.append(data.id) @property def size(self): return len(self.data)
class TableDataList(AbstractTableDataList): CheckDataType = DummyTableData DefaultDataType = DummyTableData def __init__(self, data_id=None): self.data = [] """:type: list[DummyTableData]""" self._headers = list(self.DefaultDataType.headers) self._formats = list(self.DefaultDataType.formats) self._setters = list(self.DefaultDataType.setters) self._data_id = data_id self.list_changed = MrSignal() self._ids = [] def clear(self): try: self.data.clear() except AttributeError: del self.data[:] del self._ids[:] def get_id(self): return self._data_id @property def headers(self): return self._headers @property def formats(self): return self._formats @property def setters(self): return self._setters def get_data(self): return list(self.data) def load_data(self, data): del self.data[:] self.data.extend(list(data)) self._update_ids() def add(self, *data): tmp = self.DefaultDataType() # object needs to be added to data first for logging purposes self.data.append(tmp) if len(data) > 0: tmp.load(data) self.list_changed.emit() del self._ids[:] def remove(self, index): try: tmp = self.data[index] del self.data[index] except MyExceptions.IndexError: return None self.list_changed.emit() def remove_multiple(self, indices): offset = 1 for i in range(1, len(indices)): indices[i] -= offset offset += 1 for i in indices: self.remove(i) def insert(self, index, *data): tmp = self.DefaultDataType() if index < 0: index = 0 try: self.data.insert(index, tmp) if len(data) > 0: tmp.load(data) del self._ids[:] self.list_changed.emit() except MyExceptions.IndexError: pass def insert_multiple(self, indices): """ :param indices: :type indices: list[int] :return: """ if len(indices) == 0: return offset = 1 for i in range(1, len(indices)): indices[i] += offset offset += 1 for i in indices: self.insert(i) def shape(self): return len(self.data), len(self.headers) def editable_columns(self): return set(range(len(self.headers))) def set_data(self, index, value): row, column = index try: data = self.data[row] except MyExceptions.IndexError: print('index error') return getattr(data, self._setters[column])(value) def validate(self, *args): raise NotImplementedError def serialize(self): data = [] for data_i in self.data: data.append(data_i.serialize()) return data def load(self, data): self.list_changed.block() for data_i in data: self.add(data_i) self.list_changed.unblock() del self._ids[:] # self._update_ids() # make sure to update other data if needed def _move(self, i1, i2): self.data[i1], self.data[i2] = self.data[i2], self.data[i1] del self._ids[:] self.list_changed.emit() def up(self, index): if index <= 0 or index >= len(self.data): return False i1 = index i2 = index - 1 self._move(i1, i2) return True def down(self, index): if index < 0 or index >= len(self.data) - 1: return False i1 = index i2 = index + 1 self._move(i1, i2) return True def __len__(self): return len(self.data) def __getitem__(self, index): if isinstance(index, str): if index == '': return None index = self.ids().index(index) return self.data[index] @show_caller def __setitem__(self, index, data): assert isinstance(data, self.CheckDataType) # TODO: what to do here? self.data[index] = data def id_exists(self, id_): for data_i in self.data: if data_i.id == id_: return True return False def subdata(self, index): row, column = index try: return self.data[row].subdata(column) except (AttributeError, IndexError): return None def has_subdata(self): try: data = self.data[0] except IndexError: return None except KeyError: raise KeyError(self._data_id) for i in range(len(data)): try: subdata = data.subdata(i) if subdata is not None: return subdata except NotImplementedError: pass return None def find_index(self, data_id): if isinstance(data_id, str): data = self.data for i in range(len(data)): if data[i].id == data_id: return i elif isinstance(data_id, self.CheckDataType): data = self.data for i in range(len(data)): if data_id is data[i]: return i return -1 def get_index(self, data): return data def ids(self): if len(self._ids) == 0: self._update_ids() return list(self._ids) def _update_ids(self): del self._ids[:] _ids = self._ids for data in self.data: _ids.append(data.id) @property def size(self): return len(self.data) def get_formatted_data_by_index(self, index): row, col = index return self._formats[col] % self.data[row][col] def get_edit_data_by_index(self, index): row, col = index return str(self.data[row][col]) def resize(self, new_size): data_len = len(self.data) if data_len == new_size: return if new_size > data_len: diff = new_size - data_len for i in range(diff): self.add() else: diff = data_len - new_size last_i = data_len - 1 for i in range(diff): self.remove(last_i) last_i -= 1