class QTableItem(object): def _buildMenu(self, parent): """ Context menu of table item, shows with right click """ self.menu = QContextMenu(parent) self.menu._actions(( ('Удалить', self._remove), )) self._avaibility() return self.menu def _avaibility(self): if self._row._kind not in ('ddict', 'list'): self.menu.avaibility[self._remove].setEnabled(False) def _remove(self): self.wrapper.wrapper.doc.remove( self.root._getaddr(self._row._addr, self._field._fieldName), commit=False ) self.root._changed(self.wrapper.wrapper.doc) self.root._dy_changed(self.wrapper.wrapper.doc.t) self.wrapper.wrapper.tree._update() self.wrapper.wrapper._editDocument( self.wrapper.wrapper.tree.currentItem() )
class QTableItem(QtGui.QTableWidgetItem, uni): def __init__(self, root, parent, text): self.root = root self.wrapper = parent QtGui.QTableWidgetItem.__init__(self, text) def _build_menu(self, parent): self.menu = QContextMenu(parent) self.menu._actions(( # ('Добавить элемент', self._add), ('Удалить', self._remove), )) return self.menu def __lt__(self, other): """ Метод для корректной сортировке полей с числовыми значениями """ try: return float(self.data(0).toPyObject()) < float(other.data(0).toPyObject()) except: return QtGui.QTableWidgetItem.__lt__(self, other) def _add(self): """ Добавляем документ в таблицу """ dialog = EnsureDialog( self.root, self, u''' Добавить новый документ? ''', u'Новый документ' ) if dialog.exec_() == QtGui.QDialog.Accepted: new = self.wrapper.wrapper.table.new(commit=False) self.root._changed(new) self.wrapper.wrapper.filter._clear() self.wrapper._fill(self.wrapper.wrapper.table.all(), new.id) def _remove(self): """ Удаляем документ из таблицы """ dialog = EnsureDialog( self.root, self, u''' Это действие безвозвратно удалит документ %s. Документ также будет удален с жесткого диска. Вы уверены? ''' % self._doc.id, u'Удалить документ' ) if dialog.exec_() == QtGui.QDialog.Accepted: self.root._unchanged(self._doc) self._doc.delete() self.wrapper._fill(self.wrapper.wrapper.table.all()) if self._doc in self.root.tab._tabs: self.root.tab.removeTab( self.root.tab.indexOf( self.root.tab._tabs[self._doc] ) )
class QItem(QtGui.QTreeWidgetItem): """ Элемент дерева шаблона - поле """ def __init__(self, root, parent, name): self.wrapper = parent self.root = root QtGui.QTreeWidgetItem.__init__(self, name) def _build_menu(self, parent): """ Context menu of table item, shows with right click """ self.menu = QContextMenu(parent) self.menu._actions(( ('Добавить элемент', self._addChild), ('Переименовать', self._rename), ('Удалить', self._remove) )) self._avaibility() return self.menu def _avaibility(self): if not self.parent(): self.menu.avaibility[self._remove].setEnabled(False) self.menu.avaibility[self._rename].setEnabled(False) else: if not (self.parent()._kind in ('ddict', 'list') or \ self._structure.blank): self.menu.avaibility[self._remove].setEnabled(False) if self.parent()._kind != 'ddict': self.menu.avaibility[self._rename].setEnabled(False) if not (self._kind in ('ddict', 'list') or self._hiddenProp()): self.menu.avaibility[self._addChild].setEnabled(False) def _hiddenProp(self): return set(self._structure.keys) - set(self._sf)\ - set(self.wrapper.wrapper.doc.get(self._addr)) def _remove(self): dialog = EnsureDialog( self.root, self, u"Это действие удалит поле %s.\nВы уверены?" % self._addr, u'Удалить поле' ) if dialog.exec_() == QtGui.QDialog.Accepted: self.wrapper.setCurrentItem(self.parent()) self.wrapper.wrapper.doc.remove(self._addr, commit=False) self.wrapper._update() self.wrapper.wrapper._editDocument(self.wrapper.currentItem()) self.root._changed(self.wrapper.wrapper.doc) self.root._dy_changed(self.wrapper.wrapper.table) def _addChild(self): dialog = FieldAddDialog(self.root, self) if dialog.exec_() == QtGui.QDialog.Accepted: if self._kind == 'dict': self.wrapper.wrapper.doc.set( self.root._getaddr(self._addr, dialog._field), commit=False ) else: try: self.wrapper.wrapper.doc.add( self._addr, key=dialog._field, commit=False ) except: self.root._log() self.root._dy_changed(self.wrapper.wrapper.table) self.root._changed(self.wrapper.wrapper.doc) self.wrapper.wrapper._update() def _rename(self): dialogue = InputDialugue( self.root, self, u'Новое имя', self.text(0) ) if dialogue.exec_() == QtGui.QDialog.Accepted: if not dialogue._val: return self.wrapper.wrapper.doc.__move__( self._addr, self.root._getaddr( self.parent()._addr, dialogue._val ), False) self.wrapper._update() self.root._changed(self.wrapper.wrapper.doc) def _setIcon(self): if self._kind == 'dict': ico = 'dict.png' else: ico = 'list.png' self.setIcon(0, QtGui.QIcon(os.path.join('ui', ico))) def __lt__(self, other): """ Метод для корректной сортировке полей с числовыми значениями """ try: return float('%s' % self.text(0)) < float('%s' % other.text(0)) except: return QtGui.QTreeWidgetItem.__lt__(self, other)
class QRemoteImage(QtGui.QLabel, QtGui.QTableWidgetItem): """ Виджет позволяющий вставить изображение с удаленного сервера в таблицу использует кеш """ def __init__(self, root, parent, addr): self.root = root self.wrapper = parent QtGui.QLabel.__init__(self) self.addr = addr # self.connect(self.thread, QtCore.SIGNAL('finished()'), self._get_finished) # self.connect(self.thread, QtCore.SIGNAL('taskDone()'), self._get_finished, QtCore.Qt.QueuedConnection) self.wrapper.queue.put((addr, self)) def _buildMenu(self, parent): self.menu = QContextMenu(parent) self.menu._actions((("Изменить адрес", self._specify), ("Загрузить с компьютера", self._upload))) return self.menu def contextMenuEvent(self, event): menu = self._buildMenu(self) action = menu.exec_(self.mapToGlobal(event.pos())) menu._do(action) # поток def _get(self, addr): """ запускаем поток получающий изображение """ self.wrapper.queue.put((addr, self)) self.wrapper.thread.start() def _get_finished(self, ispix, val, remote): """ Вставляет изображение Вызывается при завершении текущей задачи в очереди. """ if ispix: self.setPixmap(QtGui.QPixmap(val)) else: self.setText(val) if remote: self.wrapper.resizeColumnsToContents() self.wrapper.resizeRowsToContents() # редактирование def _specify(self): """ позволяет изменить текущий url указав адрес на удаленном сервере """ dialogue = InputDialugue(self.root, self.wrapper, u"Укажите Url", initial=self.addr) if dialogue.exec_() == QtGui.QDialog.Accepted: self._val = dialogue._val self.wrapper._memSave(self) # self._get(self._val) def _upload(self): """ позволяет изменить текущий url загрузив изображение с локальной машины """ dialogue = UploadDialugue(self.root, self.wrapper) if dialogue.exec_() == QtGui.QDialog.Accepted: status = dialogue._resp.get("status") self.root.window.statusbar.showMessage(status or "Coudn't connect to server") if status == "Success": self._val = dialogue._resp["result"]["relative"] self.wrapper._memSave(self) # self._get(self._val) def toPyObject(self): return self
class QItem(QtGui.QTreeWidgetItem): """ Элемент дерева шаблона - поле """ def __init__(self, root, parent, name): self.wrapper = parent self.root = root QtGui.QTreeWidgetItem.__init__(self, name) def _build_menu(self, name): """ Context menu of table item, shows with right click """ self.menu = QContextMenu(name) self.menu._actions(( ('Добавить элемент', self._addChild), ('Удалить', self._remove), )) self._avaibility() return self.menu def _avaibility(self): if self.text(0) == '$items' or not self.parent(): self.menu.avaibility[self._remove].setEnabled(False) if not self.static: self.menu.avaibility[self._addChild].setEnabled(False) def _addChild(self): # item = self.wrapper.currentItem() dialog = FieldAddDialog(self.root, self) if dialog.exec_() == QtGui.QDialog.Accepted: # self.__updateProjectList() # print field._kwargs self.wrapper.wrapper.table.add( self._addr, dialog._name, dialog._kind, commit=False, **dialog._kwargs ) self.wrapper._update() self.root._changed(self.wrapper.wrapper.table) self.root._dy_changed(self.wrapper.wrapper.table) for i in self.wrapper.wrapper.table.objects.values(): self.root._changed(i) def _remove(self): item = self.wrapper.currentItem() dialog = EnsureDialog( self.root, text=u""" Это действие удалит поле в шаблоне, и всех документах таблицы. Вы уверены? """ ) if dialog.exec_() == QtGui.QDialog.Accepted: self.wrapper.setCurrentItem(item.parent()) self.wrapper.wrapper._editDocument(item.parent()) self.wrapper.wrapper.table.remove( item._addr, commit=False ) self.wrapper._update() self.root._changed(self.wrapper.wrapper.table) for i in self.wrapper.wrapper.table.objects.values(): self.root._changed(i) def _setIcon(self): self.static = True if self._kind == 'dict' and not self._data['$format'].get('dynamic') \ else False if self.static: ico = 'list.png' else: ico = 'dict.png' self.setIcon(0, QtGui.QIcon(os.path.join('ui', ico)))
class QProjectTableItem(QtGui.QTreeWidgetItem,): """ Второй уровень левого меню """ def __init__(self, root, parent, name): QtGui.QTreeWidgetItem.__init__(self, name) self.root = root self.wrapper = parent self.setIcon(0, QtGui.QIcon(os.path.join('ui', 'project.png'))) def _build_menu(self, parent): """ Context menu of table item, shows with right click """ self.menu = QContextMenu(parent) self.menu._actions(( ('Добавить документ', self._addDocument), ('Импорт из csv', self._importTable), ('Экспорт в csv', self._exportTable), ('Удалить', self._delete), ('Свойства', self._property), ('Шаблон', self._openTemplate), )) return self.menu def _property(self): """ Диалог свойств таблицы """ project_name = self.parent()._project.name table_name = self.text(0) # table = projectManager.getProjectByName(u'%s' % project_name).data.table.get(u'%s' % table_name) property = QTableProperty(project_name, table_name, self._table, self.root) property.exec_() def _delete(self): """ Удаляем таблицу """ name = '%s' % self.text(0) dialogue = EnsureDialog( self, text=u""" Это действие удалит таблицу %s, и все ее документы Вы уверены? """ % name ) if dialogue.exec_() == QtGui.QDialog.Accepted: self.parent()._project.data.table[name].delete() self.parent().removeChild(self) del self def _openTemplate(self, item=None): """ открываем шаблон таблицы, если такая вкладка уже есть, то делаем ее активной """ project_name = self.parent().text(0) table_name = self.text(0) self.root.tab._addTab( '%s_t' % self._table, QTemplate(project_name, table_name, self._table, self.root), '%s template' % table_name ) # Документы def _addDocument(self): """ Создавем новый документ в таблице """ new = self._table.new(commit=False) self.root._changed(new) self.root._openDocument( new.id, self._table, self._project.name ) self.root._dy_changed(self._table) # CSV def _exportTable(self, item=None): """ ЭКспортируем данные из тпблицы в csv файл """ dialogue = ExportDialog(self.root, self) if dialogue.exec_() == QtGui.QDialog.Accepted: try: self.root._message(u'Wait') path = '%s.csv' % os.path.join( u'%s' % dialogue.edtPath.text(), '%s' % dialogue.edtName.text() ) self._table.dumps( path, dialogue._fields ) self.root._message(u'%s успешно создан' % path) except: self.root._log() def _importTable(self, item=None): """ Импорт данных из csv файла в таблицу """ dialogue = ImportDialog(self.root, self) if dialogue.exec_() == QtGui.QDialog.Accepted: # print dialogue._pth, dialogue.sync.checkState() try: self.root._message(u'Wait') self._table.loads(dialogue._pth, dialogue.sync.checkState()) self.root._message(u'%s успешно загружен' % dialogue._pth) except: self.root._log()
class QProjectItem(QtGui.QTreeWidgetItem): """ Верхний уровень меню, проекты """ def __init__(self, root, parent, name): QtGui.QTreeWidgetItem.__init__(self, name) self._disabled = False self.root = root self.wrapper = parent def _build_menu(self, parent): """ Context menu of table item, shows with right click """ self.menu = QContextMenu(parent) self.menu._actions(( ('Добавить таблицу', self._addTable), ('Переименовать', self._rename), ('Удалить', self._remove), ('Свойства', self._props), ('Модули', self._plugin), ('Экспорт в AMF', self._amf), )) self.menuPlugins = QContextMenu('Plugins', parent) self.menuHg = QContextMenu('Mercurial', parent) self.menuHg._actions(( ("Обновить", self._hg_update), ("Зафиксировать", self._hg_commit) )) try: pth = os.path.join(self._project.data.path, 'scripts') self.menuPlugins._actions([ (i.replace('.swf', ''), self._openHtml) for i in os.listdir(pth) if re.match('.*\.swf$', i) ]) self.branches = QContextMenu(u'Переключить ветку', parent) self.branches._actions( [(i, self._hg_branch) for i in self._project.data.branches()] ) self.menuHg.addMenu(self.branches) except: pass self.menu.addMenu(self.menuPlugins) self.menu.addMenu(self.menuHg) self._avaibility() return self.menu def _disable(self): """ Имитируем отключение проекта, если не удалось проинициализровать его базу """ self.setTextColor(0, QtGui.QColor('grey')) self._disabled = True self.root._message(self._project.error) def _avaibility(self): """ Для неактивных проектов отключаем некоторые пункты контекстного меню """ if self._disabled: for i in (self._amf, self._plugin, self._props, self._addTable): self.menu.avaibility[i].setDisabled(True) self.menuPlugins.setDisabled(True) self.menuHg.setDisabled(True) def _props(self): """ Свойства проекта """ dialogue = ProjectProperty(self.root, self._project) dialogue.exec_() def _remove(self): """ Удаляем проект из среды """ dialog = EnsureDialog( self.root, self, u''' Удалить проект из среды? Данные на жестком диске не будут удалены ''', u'Удалить проект' ) if dialog.exec_() == QtGui.QDialog.Accepted: item = self.root.tree.currentItem() projectManager.delProject(item._project.name) self.root._update() def _rename(self): """ Простой диалог для переименования проекта влияет только на отображение в дереве """ dialogue = InputDialugue( self.root, self, u'Новое имя', self._project.name ) if dialogue.exec_() == QtGui.QDialog.Accepted: if not dialogue._val: return self.root.window.settings.setValue( "proj/%s/name" % dialogue._val, self.root.window.settings.value( "proj/%s/name" % self._project.name, self._project.name ).toPyObject() ) self.root.window.settings.remove( "proj/%s/name" % self._project.name ) projectManager.renameProject(self._project.name, dialogue._val) self.root._update() # Таблицы def _addTable(self): """ Добавляем новую таблицу """ dialogue = TableNewDialugue(self.root, self) if dialogue.exec_() == QtGui.QDialog.Accepted: self._project.data.create( dialogue._name, **dialogue._kwargs ) new = QProjectTableItem(self.root, self, [str(dialogue._name)]) new._project = self._project new._table = self._project.data.table[dialogue._name] self.addChild(new) # AMF def _amf(self): """ Экспорт содержимого базы в AMF файл поддерживается загрузка на удаленный сервер """ dialogue = AMFDialog(self.root, self._project) dialogue.exec_() # Плагины def _openHtml(self): """ Открываем флеш плагин на отдельной вкладке, Поддержка общения flash <-> js <-> JsonDB через класс WebView """ swf = '%s' % self.root.tree._caction.text() pth = os.path.abspath(os.path.join( self._project.data.path, 'scripts', '%s.swf' % swf )) self.root.tab._addTab( pth, WebView(self.root, self, pth), '%s ()' % swf ) def _plugin(self): """ Немодальное окно диалога подключаемого python-модуля (находятся в папке path/to/db/scripts) """ dialogue = PluginDialog(self.root, self._project) dialogue.show() # Mercurial def _hg_update(self): """ Удобный диалог для hg pull & hg update -C """ if HgDialogue(self.root, self, 'update').exec_() == QtGui.QDialog.Accepted: self.root._message(u'Wait. Идет обновление дерева проектов') self._project._load() self.root._update() self.root._message(u'Ready') def _hg_commit(self): """ Удобный диалог для hg commit & hg push """ HgDialogue(self.root, self, 'commit').exec_() def _hg_branch(self): branch = '%s' % self.root.tree._caction.text() self.root._message("Wait") self._project.data.branch(branch) self.root._message("Project %s updated to branch %s" % (self._project.name, branch)) self._project._load() self.root._update()