class QTemplate(QtGui.QSplitter, uni): def __init__(self, project_name, table_name, table, root): self.project_name = project_name self.table_name = table_name self.table = table self.root = root QtGui.QSplitter.__init__(self) self.grid = QtGui.QGridLayout() self.tree = QDocTree(root, self) self.doctable = QDocTable(root, self) self._editDocument() self.grid.addWidget(self.tree, 0, 0) self.grid.addWidget(self.doctable, 0, 1) self.setLayout(self.grid) self.tree.itemClicked.connect(self._editDocument) # self.doctable.itemDoubleClicked.connect(self._activate) self.doctable.itemChanged.connect(self._mem_save) # self.saveAction = QtGui.QAction("&Save", self); # self.saveAction.connect(self.save) self.splitterMoved.connect(self._saveState) self.restoreState(self.root.window.settings.value("pattern/state").toByteArray()) def _saveState(self): self.root.window.settings.setValue("pattern/state", self.saveState()) def _update(self, *args): pass def _editDocument(self, item=None): item = item or self.tree.currentItem() self.doctable._fill(item) def _getaddr(self, prefix, postfix): if prefix: return ".".join((str(prefix), str(postfix))) else: return postfix def _mem_save(self, item): if hasattr(item, "_activated"): self.root._changed(self.table) self.root._dy_changed(self.table) if not isinstance(item, QComboTable): item._val = "%s" % item.text() try: kw = {item._field: self._get_val(item)} if item._field == "kind": if item._val == "dynamic dict": kw = {"kind": "dict", "dynamic": 1} if kw["kind"] in self.table.core.defaults: kw["default"] = self.table.core.defaults[kw["kind"]] # print item._row._addr, kw self.table.change(item._row._addr, False, **kw) if item._field == "kind": item._row._kind = item._val self.root.window.statusbar.showMessage("ready") except: self.root._log() self._editDocument(item._row) self.tree._update() def _get_val(self, item): if not projectManager.pattern[self._kind(item._row._addr)][item._field] and item._val == "": return None if item._field in ("min", "max"): return float(item._val) if item._row._kind == "float" else int(item._val) elif item._field == "default": return self._convert(item, item._val) elif item._field == "values": return [self._convert(item, i.strip()) for i in item._val.split(",")] else: return item._val def _convert(self, item, value): return projectManager.converter[item._row._kind](value) def save(self): if self.table in self.root.changed: self.root._unchanged(self.table) self.table.save() def _kind(self, addr): """ Возвращает внутренний тип поля, на основании внутреннего поля таблицы(в движке) Разница в том что в движке динамические словари именуются ddict В JsonDB Explorer они именуются dynamic dict """ ikind = self.table.__kind__(addr) if ikind == "ddict": ikind = "dynamic dict" return ikind
class QDoc(QtGui.QSplitter, uni): def __init__(self, project_name, table_name, table, id, root): self.project_name = project_name self.table_name = table_name self.table = table self.doc = self.table.get(id) self.root = root QtGui.QSplitter.__init__(self) self.tree = QDocTree(root, self) self.doctable = QDocTable(root, self) self.addWidget(self.tree) self.rpanel = RightPan(self.root, self) self.addWidget(self.rpanel) self.tree.itemClicked.connect(self._editDocument) self.doctable.itemChanged.connect(self._memSave) self.splitterMoved.connect(self._saveState) self.restoreState(self.root.stg.value("doc/state").toByteArray()) self.rpanel.restoreState(self.root.stg.value("doc/rpanel/state").toByteArray()) def _update(self, *args): """ Обновляем содержимое вкладки, если была изменена структура таблицы, или сам документ """ if self.root._dy_unchanged(self.table) or not hasattr(self, 'firstshow'): self.tree._update() if not self.tree.currentItem(): self.tree.setCurrentItem(self.tree.topLevelItem(0)) self._editDocument() self.firstshow = True def _saveState(self): """ Сохраняем геометрию вкладки """ self.root.stg.setValue("doc/state", self.saveState()) self.root.stg.setValue("doc/rpanel/state", self.rpanel.saveState()) def _editDocument(self, item=None): """ Заполняем таблицу по текущему элементу дерева """ item = item or self.tree.currentItem() self.doctable._fill(item) self.rpanel.raw.setPlainText(u'%s' % json.dumps(item._data, ensure_ascii=False, indent=4)) def _memSave(self, item): """ При изменении в модели сохраняем модель в память Актуально только после инициализации """ if not hasattr(item, '_activated'): return self.root._changed(self.doc) self.root._dy_changed(self.table) if hasattr(item, '_fieldName'): newname = '%s' % item.text() self.doc.__move__( self.root._getaddr(item._row._addr, item._fieldName), self.root._getaddr(item._row._addr, newname), commit= False ) item._fieldName = newname else: if not isinstance(item, QComboTable) and not \ isinstance(item, QRemoteImage): item._val = '%s' % item.text() try: target = self.root._getaddr(item._row._addr, item._field._fieldName) if item._val == '' and self.table.structure(target)['$format'].get('blank'): self.doc.remove(target) else: self.doc.set( target, self._get_val(item), False ) except (UnicodeEncodeError, ValueError): self.root._message( u'Ошибка типа значения, пожалуйста укажите значение соответствующего типа' ) except: self.root._log() self.tree._update() self._editDocument(self.tree.currentItem()) def _get_val(self, item): """ Возвращает конвертированное в соответствии с шаблоном значение поля(новое) """ kind = self.table.__kind__( self.root._getaddr(item._row._addr, item._field._fieldName) ) return projectManager.converter[kind](item._val) def save(self): """ Сохраняем всеменения из памяти базы на жесткий диск """ if self.doc in self.root.changed: # index = self.root.tab.tabBar().currentIndex() # self.root.tab.tabBar().setTabText(index, # re.sub('\*$', '', unicode(self.root.tab.tabBar().tabText(index))) # ) self.root.changed.remove(self.doc) self.doc.save()