class SeccionesCategoriasGUI(BaseGUI): def __init__(self,manager, managers = []): BaseGUI.__init__(self, manager, managers) self.FILENAME = 'seccion/secciones.ui' self.managerSecciones = managers[0].manager self.managerCuentas = managers[1].manager self.SeccionesGUI = managers[0] self.CategoriasGUI = managers[1] self._start_operations() def _start_operations(self): self.loadUI(self.FILENAME) self.setWindowTitle(u"Categorías") self.loadShortcuts() self.fullScreen = False centerOnScreen(self) self.SeccionesGUI.DialogAddClass.postSaveMethod = self.recargarListaSecciones #self._makeTableSecciones() self._makeTreeCuentas() #self._makeTablaCuentasEnSecciones() #self.cargarTablaSecciones() self.cargarTreeCuentas() #=============================================================================== # Metodos reimplementados : SECCIONES #=============================================================================== def _makeTableSecciones(self): if not self.ATRIBUTOSLISTA : columnasTablas = [p.capitalize() for p in self.SeccionesGUI._obtener_atributos_names()] else: self.ATRIBUTOSLISTA_CLASSNAMES = [ self.SeccionesGUI.manager.obtenerNombreAtributo( p.values()[0] ) for p in self.ATRIBUTOSLISTA] columnasTablas = [p.keys()[0] for p in self.ATRIBUTOSLISTA] self.SeccionesGUI.MyTabla = MyTableWidget(self.twDatosSeccion,columnasTablas) def _makeTablaCuentasEnSecciones(self): self.MyTablaCuentasSecciones = MyTableWidget(self.twDatosSeccionCategoria,["Cuenta"]) def cargarTablaSecciones(self,listadeobj = None): ''' carga la lista de objetos en la tabla @param listadeobj:if none carga todos, sino lo de la lista ''' if listadeobj == None: listadeobj = self.managerSecciones.getall() listadefilas = [self.SeccionesGUI._obtenerValoresAtributos(obj) for obj in listadeobj] self.SeccionesGUI.MyTabla.addItems(listadefilas) self.lbCantidadItemsSeccion.setText( str(len(listadefilas)) + ' items(s) seleccionado(s)') def recargarListaSecciones(self): valor = '' campo = '' if self.ATRI_COMBO_BUSQUEDA : campo = [p[campo] for p in self.ATRI_COMBO_BUSQUEDA if campo in p ][0] else: if campo != '' : campo = self._obtaincolumnforname(campo) resultado = self.SeccionesGUI.search(campo,valor) self.cargarTablaSecciones(resultado) def cargarTablaCuentasEnUnaSeccion(self): cuentas = self.SeccionesGUI.obtenerCuentasDeLaSeccionSeleccionada() if cuentas : self.MyTablaCuentasSecciones.addItems( [[cuenta.nombre] for cuenta in cuentas] ) @QtCore.pyqtSlot() def on_btAgregarSeccion_clicked(self): if len(self.managerCuentas.getall()) > 1 : self.SeccionesGUI.on_btAgregar_clicked( self.recargarListaSecciones ) else: QtGui.QMessageBox.warning(self, "Agregar Seccion",u"Deben existir mas de <1> cuenta(s) para poder crear una sección.") @QtCore.pyqtSlot() def on_btEditarSeccion_clicked(self): self.SeccionesGUI.on_btEditar_clicked( self.recargarListaSecciones ) @QtCore.pyqtSlot() def on_btEliminarSeccion_clicked(self): self.SeccionesGUI.on_btEliminar_clicked() self.recargarListaSecciones() self.MyTablaCuentasSecciones.fullClear() def on_twDatosSeccion_itemSelectionChanged(self): self.SeccionesGUI.on_twDatosSeccion_itemSelectionChanged( self.cargarTablaCuentasEnUnaSeccion ) #=============================================================================== # Metodos reimplementados : CUENTAS #=============================================================================== def _makeTreeCuentas(self): self.treeCuentas = TreeView( self.treeCuentas, self.connect, self.on_treeCuentas_selectedItem, QtGui.QIcon(':/newPrefix/Book.png'), QtGui.QIcon(':/newPrefix/kwikdisk.png')) def cargarTreeCuentas(self,listadeobj = None): ''' carga la lista de objetos en la tabla @param listadeobj:if none carga todos, sino lo de la lista ''' if listadeobj == None: listadeobj = self.managerCuentas.getall() listadefilas = [self.CategoriasGUI._getAttributesValues(obj) for obj in listadeobj] cuentas_ingresos, cuentas_egresos, items = [], [], [] for fila in listadefilas : if fila[2] == u'Ingreso' : cuentas_ingresos.append( fila[1] ) else: cuentas_egresos.append( fila[1] ) cuentas_ingresos.sort() cuentas_egresos.sort() map(lambda item: items.append( [u'CUENTAS DE INGRESOS',item] ), cuentas_ingresos) map(lambda item: items.append( [u'CUENTAS DE EGRESOS',item] ), cuentas_egresos) self.treeCuentas.addItems(items) self.treeCuentas.widget.expandAll() self.lbCantidadItemsCategoria.setText( str(len(items)) + ' items(s) seleccionado(s)') def recargarListaCuentas(self): valor = '' campo = '' resultado = self.CategoriasGUI.search(campo,valor) self.cargarTreeCuentas(resultado) @QtCore.pyqtSlot() def on_btAgregarCategoria_clicked(self): self.CategoriasGUI.on_btAgregar_clicked( self.cargarTreeCuentas ) @QtCore.pyqtSlot() def on_btEditarCategoria_clicked(self): try: cuenta = self.CategoriasGUI.manager.get( self.hijo )[0] self.CategoriasGUI.on_btEditar_clicked( self.cargarTreeCuentas, cuenta) except: pass @QtCore.pyqtSlot() def on_btEliminarCategoria_clicked(self): try: cuenta = self.CategoriasGUI.manager.get( self.hijo )[0] self.CategoriasGUI.on_btEliminar_clicked( self.cargarTreeCuentas , cuenta) except: pass @QtCore.pyqtSlot(int) def on_cbFiltro_currentIndexChanged(self , index): filtro = unicode(self.cbFiltro.itemText(self.cbFiltro.currentIndex()).toUtf8(),'utf-8') cuentas = None if filtro == "Todos" : cuentas = self.managerCuentas.getall() elif filtro == "Ingreso" : cuentas = self.managerCuentas.cuentasDeIngreso() elif filtro == "Egreso" : cuentas = self.managerCuentas.cuentasDeEgreso() self.cargarTreeCuentas( cuentas ) def on_treeCuentas_selectedItem(self,indice,b): if indice.parent().row() != -1: self.padre = unicode(indice.parent().data().toString().toUtf8(),'utf-8') self.hijo = unicode(indice.data().toString().toUtf8(),'utf-8')
class Ventas( BaseGUI ): def __init__(self, parent, manager, managers = []): BaseGUI.__init__(self, parent, manager, managers) self.DialogAddClass = None self.setWindowIcon(QtGui.QIcon(':/newPrefix/cart.png')) self.FILENAME = 'pos/ventas.ui' self.ALINEACIONLISTA = ['C','C','C'] self.ATRIBUTOSLISTA = [ {u' ':Venta.ide}, {u'Fecha y hora':Venta.fecha}, {u'Total':Venta.total} ] self.renglonesManager = managers[0] self._operaciones_de_inicio() self.deFecha.setDate(datetime.today()) self.makeTableDetalle() ventas = self.manager.obtenerVentas(self.deFecha.date().toPyDate()) self.cargarTabla(ventas) def _operaciones_de_inicio(self): self.loadUi() self.setWindowTitle("Detalles de ventas") self._makeTable() self._loadAppShortcuts() self.fullScreen = False self._centerOnScreen() def _obtenerValoresAtributos(self,obj): resultado = [] atributos_objeto = self.manager.getClassAttributesValues(obj) if not self.ATRIBUTOSLISTA : return atributos_objeto else: atributos_clase = self.manager.getClassAttributes() atributos_ordenados = self.ATRIBUTOSLISTA_CLASSNAMES for atributo in atributos_ordenados: resultado.append( atributos_objeto[ atributos_clase.index( atributo ) ] ) resultado[1] = resultado[1].strftime('%d/%m/%Y %H:%M') resultado[2] = "$ %8.2f" % float(resultado[2]) return resultado def makeTableDetalle(self): self.getAtributosListaDetalle() columnasTablas = [p.keys()[0] for p in self.ATRIBUTOSLISTA_DETALLE] self.tablaDetalle = MyTableWidget(self.twDetalle, columnasTablas, ['C','L','C','C']) def getAtributosListaVenta(self): self.ATRIBUTOSLISTA = [ {u' ':Venta.ide}, {u'Fecha y hora':Venta.fecha}, {u'Total':Venta.total} ] def getAtributosListaDetalle(self): self.ATRIBUTOSLISTA_DETALLE = [ {u'Cantidad':Renglon.prod_cant}, {u'Descripcion':Renglon.prod_descripcion}, {u'Precio':Renglon.prod_precio}, {u'Importe':Renglon.prod_precio} ] def _itemTableSelected(self): venta = self.actual_rows_to_objects() if venta: venta = venta[0] renglones = self.renglonesManager.obtenerRenglonesVenta(venta) items = [] self.lbTotal.setText("$ %8.2f" % venta.total) self.lbPagoCon.setText("$ %8.2f" % venta.paga_con) for renglon in renglones: importe = float(renglon.prod_cant) * float(renglon.prod_precio) items.append([ renglon.prod_cant, renglon.prod_descripcion, "$ %8.2f" % renglon.prod_precio, "$ %8.2f" % importe ]) self.tablaDetalle.addItems(items) def on_deFecha_dateChanged(self , date): ventas = self.manager.obtenerVentas(date.toPyDate()) self.cargarTabla(ventas) def on_twDatos_currentItemChanged(self , item_a, item_b): self._itemTableSelected() def on_twDatos_itemClicked(self , item): self._itemTableSelected()
class BaseGUI( QtGui.QMainWindow ): '''Base class to handle operations of CRUD screen''' def __init__(self, manager, managers = None, parent = None): QtGui.QMainWindow.__init__(self, parent) # Name file of ui for gui self.parent = parent self.FILENAME = '/plasta/gui/uis/list.ui' self.processEvents = QtGui.QApplication.processEvents self.develop = config.DEVELOP # Name file of icon window self.ICONFILE = '' # self.manager = manager # self.managers = managers # ATRIBUTOSLISTA: lista de diccionarios donde puedes indicar el orden y formato # en que se deben mostrar los atributos en la lista. Siendo la clave del diccionario, # el texto en Unicode del texto que tendra la cabecera de la columna. Y el valor contenido # en el mismo elemento, el atributo de la clase que se mostrara en esa columna # Ejemplo: # self.ATRIBUTOSLISTA = [ {u'Nombres':Cliente.Nombres}, {u'Domicilio':Cliente.Domicilio}] self.ATRIBUTOSLISTA = [] # ATRI_COMBO_BUSQUEDA: lista de diccionarios donde puedes indicar el orden de como # quieres que se muestren y vean los atributos en el combo de los filtros # El formato es el mismo que <ATRIBUTOSLISTA> self.ATRI_COMBO_BUSQUEDA = []#el orden y la cantidad de atributos en str que quieras # Use this if you need parse attributes in list # Format {listOfList}: [[index, function], ...] # Params function: fn(row, currentValue) # Use: [[0, lambda (row, value): value.uppper()], ...] self.fnsParseListAttrs = [] # self.fnAllItems = self.manager.getall # self.fnFilterItems = None # funcion para parsear los items de la tabla self.fnParseTableItem = None # Alignment of each atttribute in the list # Possible values: C = CENTER, L = LEFT, R = RIGHT # Use: self.alignmentColumns = ['C', 'L', 'R', 'L'] self.alignmentColumns = [] # List of objects current are listeds self.items = [] self.widgets = { 'btNew':True, 'btEdit':True, 'btDelete':True, 'leSearch':False, 'cbFilters':True, 'twItems':True, 'lbItemsCount':True, 'lbTitle':True } # DialogAddClass: reference to the class to instantiate to # handle dialog window add / edit self.DialogAddClass = None # Single title to show in gui self.singleTitle = self.manager.getClassName() # Plural title to show in gui self.pluralTitle = self.manager.getClassName() self.lang = config().LANG self.messages = { 'es':{ 'new':'Nuevo', 'edit':'Editar', 'delete':'Eliminar', 'deleteConfirm':u"¿Está seguro que desea eliminar?.\n\n", 'itemsCount':' item(s) listado(s)', 'search':'Buscar', 'filters':'Filtros' }, 'en':{ 'new':'New', 'edit':'Edit', 'delete':'Delete', 'deleteConfirm':u"¿Are you sure?.\n\n", 'itemsCount':' item(s) listed', 'search':'Search', 'filters':'Filters' } } def _start_operations( self ): '''Operations necessary to display the window''' self.processEvents = QtGui.QApplication.processEvents self.fullScreen = False self.lang = config().LANG self.translateWidgets() self.makeTable() self.processEvents() self.loadCombobox() self.loadTable() self.processEvents() self.loadShortcuts() centerOnScreen(self) setStyle(self) self.processEvents() if self.widgets['btEdit']: self.btEdit.setVisible(False) if self.widgets['btDelete']: self.btDelete.setVisible(False) # self.setWindowIcon( QtGui.QIcon( QtGui.QPixmap( join( abspath( dirname( __file__ ) ), self.ICONFILE ) ) ) ) if self.widgets['lbTitle']: self.lbTitle.setText(self.pluralTitle) self.setWindowTitle(self.pluralTitle) def loadUI(self, pathToFile = None): from plasta.utils.qt import loadUI loadUI(self, pathToFile) def getMsgByLang(self, msg): return self.messages[self.lang][msg] def translateWidgets(self): if self.widgets['btNew']: self.btNew.setText(self.getMsgByLang('new')) if self.widgets['btEdit']: self.btEdit.setText(self.getMsgByLang('edit')) if self.widgets['btDelete']: self.btDelete.setText(self.getMsgByLang('delete')) if self.widgets['leSearch']: self.lbSearch.setText(self.getMsgByLang('search')) if self.widgets['cbFilters']: self.lbFilters.setText(self.getMsgByLang('filters')) def toogleFullScreen( self ): ''' ''' if not self.fullScreen : self.showFullScreen() else: self.showNormal() self.fullScreen = not self.fullScreen def loadShortcuts( self ): u""" Load shortcuts used in the application. """ self._atajo_salir = QtGui.QShortcut( QtGui.QKeySequence( "Ctrl+Q" ), self, self.close ) self._atajo_fullscreen = QtGui.QShortcut( QtGui.QKeySequence( "F11" ), self, self.toogleFullScreen ) QtGui.QShortcut( QtGui.QKeySequence( QtCore.Qt.Key_Escape ), self, self.close ) if self.widgets['btNew']: QtGui.QShortcut( QtGui.QKeySequence( QtCore.Qt.CTRL | QtCore.Qt.Key_N ), self, self.on_btNew_clicked ) if self.widgets['btEdit']: QtGui.QShortcut( QtGui.QKeySequence( QtCore.Qt.CTRL | QtCore.Qt.Key_M ), self, self.on_btEdit_clicked ) if self.widgets['btDelete']: QtGui.QShortcut( QtGui.QKeySequence( "Del" ), self, self.on_btDelete_clicked ) def makeTable( self ): '''Create the structure of table (columns)''' if not self.ATRIBUTOSLISTA : tableColumns = [p.capitalize() for p in self._get_attributes_names()] else: self.ATRIBUTOSLISTA_CLASSNAMES = [ self.manager.getAttributeName( p.values()[0] ) for p in self.ATRIBUTOSLISTA] tableColumns = [p.keys()[0] for p in self.ATRIBUTOSLISTA] self.tableItems = MyTableWidget( self.twItems, tableColumns, self.alignmentColumns, fnParseItem=self.fnParseTableItem) # conecta el menu contextual a la tabla #self.connect( self.tableItems.widget, QtCore.SIGNAL( 'customContextMenuRequested(const QPoint&)' ), self.on_context_menu ) def reloadList( self ): ''' Vuelve a cargar la lista a partir de los valores actuales en la barra de busqueda y el filtro seleccionado. ''' valor = u'' campo = u'' if self.widgets['leSearch']: valor = unicode( self.leSearch.text().toUtf8(), 'utf-8' ) if self.widgets['cbFilters']: campo = unicode( self.cbFilters.itemText( self.cbFilters.currentIndex() ).toUtf8() ) if self.ATRI_COMBO_BUSQUEDA : campo = [p[campo] for p in self.ATRI_COMBO_BUSQUEDA if campo in p ][0] else: campo = self._obtainColumnForName( campo ) resultado = self.manager.searchBy( campo, valor ) if self.fnFilterItems: resultado = self.fnFilterItems(resultado) self.items = resultado self.loadTable( resultado ) if self.widgets['leSearch']: self._setSearchColor( self.leSearch, resultado ) def loadTable( self, listadeobj = None ): ''' Carga la lista de objetos en la tabla @param listadeobj:if none carga todos, sino lo de la lista ''' if listadeobj == None: listadeobj = self.fnAllItems() if self.fnFilterItems: listadeobj = self.fnFilterItems(listadeobj) self.items = listadeobj listadefilas = [self._getAttributesValues( obj ) for obj in listadeobj] self.tableItems.addItems( listadefilas ) self.setItemsCount( len( listadeobj ) ) def loadCombobox( self ): ''' Carga el combobox de campos ''' if self.widgets['cbFilters']: self.cbFilters.clear() if not self.ATRI_COMBO_BUSQUEDA : atributos = self.manager.getClassAttributes() for atributo in atributos: self.ATRI_COMBO_BUSQUEDA.append( {atributo:self._obtainColumnForName( atributo )} ) map( self.cbFilters.addItem, [p.keys()[0] for p in self.ATRI_COMBO_BUSQUEDA] ) def find( self ): ''' Reliza la busqueda y carga la tabla ''' # obtiene el valor cargado en la barra de busqueda valor = u'' if self.widgets['leSearch']: valor = unicode(self.leSearch.text().toUtf8(),'utf-8') # carga la lista segun el estado de la barra de busqueda self.reloadList() if valor != u'' else self.loadTable() def actualRowsToObjects( self ): ''' Obtiene los objetos seleccionados en la tabla @return: un objeto del tipo que maneja self.manager ''' try: widget = self.tableItems.widget items = widget.selectedItems() idxs = list(set([item.row() for item in items])) result = [self.items[idx] for idx in idxs] return result except Exception, e: print 'error:actualRowsToObjects:', e return None
class BaseGUI( QtGui.QMainWindow ): '''Base class to handle operations of CRUD screen''' def __init__(self, manager, managers = None, parent = None): QtGui.QMainWindow.__init__(self, parent) # Name file of ui for gui self.FILENAME = '/plasta/gui/uis/list.ui' self.processEvents = QtGui.QApplication.processEvents self.develop = config.DEVELOP # Name file of icon window self.ICONFILE = '' # self.manager = manager # self.managers = managers # ATRIBUTOSLISTA: lista de diccionarios donde puedes indicar el orden y formato # en que se deben mostrar los atributos en la lista. Siendo la clave del diccionario, # el texto en Unicode del texto que tendra la cabecera de la columna. Y el valor contenido # en el mismo elemento, el atributo de la clase que se mostrara en esa columna # Ejemplo: # self.ATRIBUTOSLISTA = [ {u'Nombres':Cliente.Nombres}, {u'Domicilio':Cliente.Domicilio}] self.ATRIBUTOSLISTA = [] # ATRI_COMBO_BUSQUEDA: lista de diccionarios donde puedes indicar el orden de como # quieres que se muestren y vean los atributos en el combo de los filtros # El formato es el mismo que <ATRIBUTOSLISTA> self.ATRI_COMBO_BUSQUEDA = []#el orden y la cantidad de atributos en str que quieras # Use this if you need parse attributes in list # Format {listOfList}: [[index, function], ...] # Params function: fn(row, currentValue) # Use: [[0, lambda (row, value): value.uppper()], ...] self.fnsParseListAttrs = [] # self.fnAllItems = self.manager.getall # self.fnFilterItems = None # funcion para parsear los items de la tabla self.fnParseTableItem = None # Alignment of each atttribute in the list # Possible values: C = CENTER, L = LEFT, R = RIGHT # Use: self.alignmentColumns = ['C', 'L', 'R', 'L'] self.alignmentColumns = [] # List of objects current are listeds self.items = [] self.widgets = { 'btNew':True, 'btEdit':True, 'btDelete':True, 'leSearch':True, 'cbFilters':True, 'twItems':True, 'lbItemsCount':True, 'lbTitle':True } # DialogAddClass: reference to the class to instantiate to # handle dialog window add / edit self.DialogAddClass = None # Single title to show in gui self.singleTitle = self.manager.getClassName() # Plural title to show in gui self.pluralTitle = self.manager.getClassName() self.lang = config().LANG self.messages = { 'es':{ 'new':'Nuevo', 'edit':'Editar', 'delete':'Eliminar', 'deleteConfirm':u"¿Está seguro que desea eliminar?.\n\n", 'itemsCount':' item(s) listado(s)', 'search':'Buscar', 'filters':'Filtros' }, 'en':{ 'new':'New', 'edit':'Edit', 'delete':'Delete', 'deleteConfirm':u"¿Are you sure?.\n\n", 'itemsCount':' item(s) listed', 'search':'Search', 'filters':'Filters' } } def _start_operations( self ): '''Operations necessary to display the window''' self.processEvents = QtGui.QApplication.processEvents self.fullScreen = False self.lang = config().LANG self.translateWidgets() self.makeTable() self.processEvents() self.loadCombobox() self.loadTable() self.processEvents() self.loadShortcuts() centerOnScreen(self) setStyle(self) self.processEvents() if self.widgets['btEdit']: self.btEdit.setVisible(False) if self.widgets['btDelete']: self.btDelete.setVisible(False) # self.setWindowIcon( QtGui.QIcon( QtGui.QPixmap( join( abspath( dirname( __file__ ) ), self.ICONFILE ) ) ) ) if self.widgets['lbTitle']: self.lbTitle.setText(self.pluralTitle) self.setWindowTitle(self.pluralTitle) def loadUI(self, pathToFile = None): from plasta.utils.qt import loadUI loadUI(self, pathToFile) def getMsgByLang(self, msg): return self.messages[self.lang][msg] def translateWidgets(self): if self.widgets['btNew']: self.btNew.setText(self.getMsgByLang('new')) if self.widgets['btEdit']: self.btEdit.setText(self.getMsgByLang('edit')) if self.widgets['btDelete']: self.btDelete.setText(self.getMsgByLang('delete')) if self.widgets['leSearch']: self.lbSearch.setText(self.getMsgByLang('search')) if self.widgets['cbFilters']: self.lbFilters.setText(self.getMsgByLang('filters')) def toogleFullScreen( self ): ''' ''' if not self.fullScreen : self.showFullScreen() else: self.showNormal() self.fullScreen = not self.fullScreen def loadShortcuts( self ): u""" Load shortcuts used in the application. """ self._atajo_salir = QtGui.QShortcut( QtGui.QKeySequence( "Ctrl+Q" ), self, self.close ) self._atajo_fullscreen = QtGui.QShortcut( QtGui.QKeySequence( "F11" ), self, self.toogleFullScreen ) QtGui.QShortcut( QtGui.QKeySequence( QtCore.Qt.Key_Escape ), self, self.close ) if self.widgets['btNew']: QtGui.QShortcut( QtGui.QKeySequence( QtCore.Qt.CTRL | QtCore.Qt.Key_N ), self, self.on_btNew_clicked ) if self.widgets['btEdit']: QtGui.QShortcut( QtGui.QKeySequence( QtCore.Qt.CTRL | QtCore.Qt.Key_M ), self, self.on_btEdit_clicked ) if self.widgets['btDelete']: QtGui.QShortcut( QtGui.QKeySequence( "Del" ), self, self.on_btDelete_clicked ) def makeTable( self ): '''Create the structure of table (columns)''' if not self.ATRIBUTOSLISTA : tableColumns = [p.capitalize() for p in self._get_attributes_names()] else: self.ATRIBUTOSLISTA_CLASSNAMES = [ self.manager.getAttributeName( p.values()[0] ) for p in self.ATRIBUTOSLISTA] tableColumns = [p.keys()[0] for p in self.ATRIBUTOSLISTA] self.tableItems = MyTableWidget( self.twItems, tableColumns, self.alignmentColumns, fnParseItem=self.fnParseTableItem) # conecta el menu contextual a la tabla #self.connect( self.tableItems.widget, QtCore.SIGNAL( 'customContextMenuRequested(const QPoint&)' ), self.on_context_menu ) def reloadList( self ): ''' Vuelve a cargar la lista a partir de los valores actuales en la barra de busqueda y el filtro seleccionado. ''' valor = u'' campo = u'' if self.widgets['leSearch']: valor = unicode( self.leSearch.text().toUtf8(), 'utf-8' ) if self.widgets['cbFilters']: campo = unicode( self.cbFilters.itemText( self.cbFilters.currentIndex() ).toUtf8() ) if self.ATRI_COMBO_BUSQUEDA : campo = [p[campo] for p in self.ATRI_COMBO_BUSQUEDA if campo in p ][0] else: campo = self._obtainColumnForName( campo ) resultado = self.manager.searchBy( campo, valor ) if self.fnFilterItems: resultado = self.fnFilterItems(resultado) self.items = resultado self.loadTable( resultado ) if self.widgets['leSearch']: self._setSearchColor( self.leSearch, resultado ) def loadTable( self, listadeobj = None ): ''' Carga la lista de objetos en la tabla @param listadeobj:if none carga todos, sino lo de la lista ''' if listadeobj == None: listadeobj = self.fnAllItems() if self.fnFilterItems: listadeobj = self.fnFilterItems(listadeobj) self.items = listadeobj listadefilas = [self._getAttributesValues( obj ) for obj in listadeobj] self.tableItems.addItems( listadefilas ) self.setItemsCount( len( listadeobj ) ) def loadCombobox( self ): ''' Carga el combobox de campos ''' if self.widgets['cbFilters']: self.cbFilters.clear() if not self.ATRI_COMBO_BUSQUEDA : atributos = self.manager.getClassAttributes() for atributo in atributos: self.ATRI_COMBO_BUSQUEDA.append( {atributo:self._obtainColumnForName( atributo )} ) map( self.cbFilters.addItem, [p.keys()[0] for p in self.ATRI_COMBO_BUSQUEDA] ) def find( self ): ''' Reliza la busqueda y carga la tabla ''' # obtiene el valor cargado en la barra de busqueda valor = u'' if self.widgets['leSearch']: valor = unicode(self.leSearch.text().toUtf8(),'utf-8') # carga la lista segun el estado de la barra de busqueda self.reloadList() if valor != u'' else self.loadTable() def actualRowsToObjects( self ): ''' Obtiene los objetos seleccionados en la tabla @return: un objeto del tipo que maneja self.manager ''' try: widget = self.tableItems.widget items = widget.selectedItems() idxs = list(set([item.row() for item in items])) result = [self.items[idx] for idx in idxs] return result except Exception, e: print 'error:actualRowsToObjects:', e return None
class SeccionesCategoriasGUI(BaseGUI): def __init__(self, manager, managers=[]): BaseGUI.__init__(self, manager, managers) self.FILENAME = 'model/seccion/secciones.ui' self.managerSecciones = managers[0].manager self.managerCuentas = managers[1].manager self.SeccionesGUI = managers[0] self.CategoriasGUI = managers[1] self._start_operations() def _start_operations(self): self.loadUI(self.FILENAME) self.setWindowTitle(u"Categorías") self.loadShortcuts() self.fullScreen = False centerOnScreen(self) self.SeccionesGUI.DialogAddClass.postSaveMethod = self.recargarListaSecciones #self._makeTableSecciones() self._makeTreeCuentas() #self._makeTablaCuentasEnSecciones() #self.cargarTablaSecciones() self.cargarTreeCuentas() #=============================================================================== # Metodos reimplementados : SECCIONES #=============================================================================== def _makeTableSecciones(self): if not self.ATRIBUTOSLISTA: columnasTablas = [ p.capitalize() for p in self.SeccionesGUI._obtener_atributos_names() ] else: self.ATRIBUTOSLISTA_CLASSNAMES = [ self.SeccionesGUI.manager.obtenerNombreAtributo(p.values()[0]) for p in self.ATRIBUTOSLISTA ] columnasTablas = [p.keys()[0] for p in self.ATRIBUTOSLISTA] self.SeccionesGUI.MyTabla = MyTableWidget(self.twDatosSeccion, columnasTablas) def _makeTablaCuentasEnSecciones(self): self.MyTablaCuentasSecciones = MyTableWidget( self.twDatosSeccionCategoria, ["Cuenta"]) def cargarTablaSecciones(self, listadeobj=None): ''' carga la lista de objetos en la tabla @param listadeobj:if none carga todos, sino lo de la lista ''' if listadeobj == None: listadeobj = self.managerSecciones.getall() listadefilas = [ self.SeccionesGUI._obtenerValoresAtributos(obj) for obj in listadeobj ] self.SeccionesGUI.MyTabla.addItems(listadefilas) self.lbCantidadItemsSeccion.setText( str(len(listadefilas)) + ' items(s) seleccionado(s)') def recargarListaSecciones(self): valor = '' campo = '' if self.ATRI_COMBO_BUSQUEDA: campo = [p[campo] for p in self.ATRI_COMBO_BUSQUEDA if campo in p][0] else: if campo != '': campo = self._obtaincolumnforname(campo) resultado = self.SeccionesGUI.search(campo, valor) self.cargarTablaSecciones(resultado) def cargarTablaCuentasEnUnaSeccion(self): cuentas = self.SeccionesGUI.obtenerCuentasDeLaSeccionSeleccionada() if cuentas: self.MyTablaCuentasSecciones.addItems([[cuenta.nombre] for cuenta in cuentas]) @QtCore.pyqtSlot() def on_btAgregarSeccion_clicked(self): if len(self.managerCuentas.getall()) > 1: self.SeccionesGUI.on_btAgregar_clicked(self.recargarListaSecciones) else: QtGui.QMessageBox.warning( self, "Agregar Seccion", u"Deben existir mas de <1> cuenta(s) para poder crear una sección." ) @QtCore.pyqtSlot() def on_btEditarSeccion_clicked(self): self.SeccionesGUI.on_btEditar_clicked(self.recargarListaSecciones) @QtCore.pyqtSlot() def on_btEliminarSeccion_clicked(self): self.SeccionesGUI.on_btEliminar_clicked() self.recargarListaSecciones() self.MyTablaCuentasSecciones.fullClear() def on_twDatosSeccion_itemSelectionChanged(self): self.SeccionesGUI.on_twDatosSeccion_itemSelectionChanged( self.cargarTablaCuentasEnUnaSeccion) #=============================================================================== # Metodos reimplementados : CUENTAS #=============================================================================== def _makeTreeCuentas(self): self.treeCuentas = TreeView(self.treeCuentas, self.connect, self.on_treeCuentas_selectedItem, QtGui.QIcon(':/newPrefix/Book.png'), QtGui.QIcon(':/newPrefix/kwikdisk.png')) def cargarTreeCuentas(self, listadeobj=None): ''' carga la lista de objetos en la tabla @param listadeobj:if none carga todos, sino lo de la lista ''' if listadeobj == None: listadeobj = self.managerCuentas.getall() listadefilas = [ self.CategoriasGUI._getAttributesValues(obj) for obj in listadeobj ] cuentas_ingresos, cuentas_egresos, items = [], [], [] for fila in listadefilas: if fila[2] == u'Ingreso': cuentas_ingresos.append(fila[1]) else: cuentas_egresos.append(fila[1]) cuentas_ingresos.sort() cuentas_egresos.sort() map(lambda item: items.append([u'CUENTAS DE INGRESOS', item]), cuentas_ingresos) map(lambda item: items.append([u'CUENTAS DE EGRESOS', item]), cuentas_egresos) self.treeCuentas.addItems(items) self.treeCuentas.widget.expandAll() self.lbCantidadItemsCategoria.setText( str(len(items)) + ' items(s) seleccionado(s)') def recargarListaCuentas(self): valor = '' campo = '' resultado = self.CategoriasGUI.search(campo, valor) self.cargarTreeCuentas(resultado) @QtCore.pyqtSlot() def on_btAgregarCategoria_clicked(self): self.CategoriasGUI.on_btAgregar_clicked(self.cargarTreeCuentas) @QtCore.pyqtSlot() def on_btEditarCategoria_clicked(self): try: cuenta = self.CategoriasGUI.manager.get(self.hijo)[0] self.CategoriasGUI.on_btEditar_clicked(self.cargarTreeCuentas, cuenta) except: pass @QtCore.pyqtSlot() def on_btEliminarCategoria_clicked(self): try: cuenta = self.CategoriasGUI.manager.get(self.hijo)[0] self.CategoriasGUI.on_btEliminar_clicked(self.cargarTreeCuentas, cuenta) except: pass @QtCore.pyqtSlot(int) def on_cbFiltro_currentIndexChanged(self, index): filtro = unicode( self.cbFiltro.itemText(self.cbFiltro.currentIndex()).toUtf8(), 'utf-8') cuentas = None if filtro == "Todos": cuentas = self.managerCuentas.getall() elif filtro == "Ingreso": cuentas = self.managerCuentas.cuentasDeIngreso() elif filtro == "Egreso": cuentas = self.managerCuentas.cuentasDeEgreso() self.cargarTreeCuentas(cuentas) def on_treeCuentas_selectedItem(self, indice, b): if indice.parent().row() != -1: self.padre = unicode(indice.parent().data().toString().toUtf8(), 'utf-8') self.hijo = unicode(indice.data().toString().toUtf8(), 'utf-8')
class BaseGUI( QtGui.QMainWindow ): ''' Clase base para el manejo de las operaciones de la pantalla ABM ''' def __init__(self, manager, managers = []): QtGui.QMainWindow.__init__(self) # nombre del archivo ui de la interfaz self.FILENAME = join(abspath(dirname(__file__)),'uis/admin.ui') # nombre del archivo del icono para la ventana ICONFILE = '' self.setWindowIcon( QtGui.QIcon( QtGui.QPixmap( join( abspath( dirname( __file__ ) ), ICONFILE ) ) ) )# self.manager = manager self.managers = managers # ATRIBUTOSLISTA: lista de diccionarios donde puedes indicar el orden y formato # en que se deben mostrar los atributos en la lista. Siendo la clave del diccionario, # el texto en Unicode del texto que tendra la cabecera de la columna. Y el valor contenido # en el mismo elemento, el atributo de la clase que se mostrara en esa columna # Ejemplo: # self.ATRIBUTOSLISTA = [ # {u'Nombres':Cliente.Nombres}, # {u'Domicilio':Cliente.Domicilio}] self.ATRIBUTOSLISTA = None # ATRI_COMBO_BUSQUEDA: lista de diccionarios donde puedes indicar el orden de como # quieres que se muestren y vean los atributos en el combo de los filtros # El formato es el mismo que <ATRIBUTOSLISTA> self.ATRI_COMBO_BUSQUEDA = []# # DialogAddClass: referencia a la clase que se instanciara para manejar la # ventana del dialogo abrir/editar self.DialogAddClass = None self.TITULO = "Administrador de %ss" % self.manager.getClassName() def _start_operations( self ): u''' Operaciones necesarias para levantar las ventanas ''' uic.loadUi( self.FILENAME, self ) self.setWindowTitle( self.TITULO ) self.lbTitulo.setText( self.manager.getClassName() ) self._makeTable() self.loadCombobox() self.loadTable() self._loadAppShortcuts() self.fullScreen = False self._centerOnScreen() def _toogleFullScreen( self ): ''' ''' if not self.fullScreen : self.showFullScreen() else: self.showNormal() self.fullScreen = not self.fullScreen def _loadAppShortcuts( self ): u""" Load shortcuts used in the application. """ self._atajo_salir = QtGui.QShortcut( QtGui.QKeySequence( "Ctrl+Q" ), self, self.close ) self._atajo_fullscreen = QtGui.QShortcut( QtGui.QKeySequence( "F11" ), self, self._toogleFullScreen ) QtGui.QShortcut( QtGui.QKeySequence( QtCore.Qt.Key_Escape ), self, self.close ) QtGui.QShortcut( QtGui.QKeySequence( QtCore.Qt.CTRL | QtCore.Qt.Key_N ), self, self.on_btAgregar_clicked ) QtGui.QShortcut( QtGui.QKeySequence( QtCore.Qt.CTRL | QtCore.Qt.Key_M ), self, self.on_btEditar_clicked ) QtGui.QShortcut( QtGui.QKeySequence( "Del" ), self, self.on_btEliminar_clicked ) def _get_attributes_names( self ): ''' Obtiene los atributos de la clase que maneja self.manager ''' return self.ATRIBUTOSLISTA_CLASSNAMES if self.ATRIBUTOSLISTA else self.manager.getClassAttributes() def _makeTable( self ): ''' Crea la estructura de la tabla ( columnas ) ''' if not self.ATRIBUTOSLISTA : columnasTablas = [p.capitalize() for p in self._get_attributes_names()] else: self.ATRIBUTOSLISTA_CLASSNAMES = [ self.manager.getAttributeName( p.values()[0] ) for p in self.ATRIBUTOSLISTA] columnasTablas = [p.keys()[0] for p in self.ATRIBUTOSLISTA] self.MyTabla = MyTableWidget( self.twDatos, columnasTablas ) # conecta el menu contextual a la tabla self.connect( self.MyTabla.widget, QtCore.SIGNAL( 'customContextMenuRequested(const QPoint&)' ), self.on_context_menu ) def _getAttributesValues( self, obj ): ''' Devuelve en una lista los atributos de un objetos, ordenados segun lo indicado en self.ATRIBUTOSLISTA ''' resultado = [] atributos_objeto = self.manager.getClassAttributesValues( obj ) if not self.ATRIBUTOSLISTA : return atributos_objeto else: atributos_clase = self.manager.getClassAttributes() atributos_ordenados = self.ATRIBUTOSLISTA_CLASSNAMES for atributo in atributos_ordenados: resultado.append( atributos_objeto[ atributos_clase.index( atributo ) ] ) return resultado def _obtainColumnForName(self, columnname): ''' A partir de un string obtiene la columna de storm @param columnname:nombre del atributo en str @return: ''' #MAGIC################### busqueda = self.manager.CLASS.__dict__[columnname] if str( type( busqueda ) ) != "<class 'storm.references.Reference'>" : try: campo = self.manager.CLASS.__dict__['_storm_columns'][busqueda] except: print "no tengo idea del error gui-_obtainColumnForName" campo = busqueda else: campo = busqueda #END MAGIC############### return campo def _find( self ): ''' Reliza la busqueda y carga la tabla ''' # obtiene el valor cargado en la barra de busqueda valor = unicode(self.leBusqueda.text().toUtf8(),'utf-8') # carga la lista segun el estado de la barra de busqueda self.reloadList() if valor != u'' else self.loadTable() def _setSearchColor(self, widget, resultados_busqueda): color_rojo = 'background-color: rgb(255, 178, 178);' try: if self.myStyleSheetBlanco == '' : if not widget.styleSheet().isEmpty() : style = widget.styleSheet() self.myStyleSheetBlanco = widget.styleSheet() pos1 = style.indexOf( 'QLineEdit' ) pos2 = style.indexOf( '}', pos1 ) style = style.replace( pos2, 1, color_rojo + '}' ) self.myStyleSheetRojo = style else: self.myStyleSheetRojo = color_rojo if not widget.text().isEmpty() : if len( resultados_busqueda ) == 0 : widget.setStyleSheet( self.myStyleSheetRojo ) else: widget.setStyleSheet( self.myStyleSheetBlanco ) else: widget.setStyleSheet( self.myStyleSheetBlanco ) except: self.myStyleSheetBlanco = '' self.myStyleSheetRojo = '' self._setSearchColor( widget, resultados_busqueda ) def reloadList( self ): ''' Vuelve a cargar la lista a partir de los valores actuales en la barra de busqueda y el filtro seleccionado. ''' valor = unicode( self.leBusqueda.text().toUtf8(), 'utf-8' ) campo = unicode( self.cbCampos.itemText( self.cbCampos.currentIndex() ).toUtf8() ) if self.ATRI_COMBO_BUSQUEDA : campo = [p[campo] for p in self.ATRI_COMBO_BUSQUEDA if campo in p ][0] else: campo = self._obtainColumnForName( campo ) resultado = self.search( campo, valor ) self.loadTable( resultado ) self._setSearchColor( self.leBusqueda, resultado ) def loadCombobox( self ): ''' Carga el combobox de campos ''' self.cbCampos.clear() if not self.ATRI_COMBO_BUSQUEDA : atributos = self.manager.getClassAttributes() for atributo in atributos: self.ATRI_COMBO_BUSQUEDA.append( {atributo:self._obtainColumnForName( atributo )} ) map( self.cbCampos.addItem, [p.keys()[0] for p in self.ATRI_COMBO_BUSQUEDA] ) def loadTable( self, listadeobj = None ): ''' Carga la lista de objetos en la tabla @param listadeobj:if none carga todos, sino lo de la lista ''' if listadeobj == None: listadeobj = self.manager.getall() listadefilas = [self._getAttributesValues( obj ) for obj in listadeobj] self.MyTabla.addItems( listadefilas ) self.setItemsCount( len( listadeobj ) ) def search( self, camponame, valor ): ''' @param camponame:el nombre del campo en string @param valor:el valor de el campo(soporta los tipos de datos de searchBy) @return: lista de obj ''' return self.manager.searchBy( camponame, valor ) def on_context_menu( self, point ): mypoint = QtCore.QPoint( point.x() + 10, point.y() + 30 ) self.popMenu = QtGui.QMenu( self ) self.popMenu.addAction("Nuevo",self.on_btAgregar_clicked ,QtGui.QKeySequence("Ctrl+N")) self.popMenu.addAction("Modificar",self.on_btEditar_clicked ,QtGui.QKeySequence("Ctrl+M")) self.popMenu.addAction("Eliminar",self.on_btEliminar_clicked ,QtGui.QKeySequence("Del")) self.popMenu.exec_(self.MyTabla.widget.mapToGlobal(mypoint) ) def actual_rows_to_objects( self ): ''' Obtiene los objetos seleccionados en la tabla @return: un objeto del tipo que maneja self.manager ''' listadelistastring = self.MyTabla.getListSelectedRows() atributos_names = self._get_attributes_names() classid = self.manager.CLASSid listadeobjetos = [] if listadelistastring != []: # obtiene el tipo de dato de la clave del objeto for value in self.manager.getClassAttributesInfo().values() : if value['primary'] == True : primary_type = value['type'] for lista in listadelistastring: posicion_ide = atributos_names.index( classid ) if primary_type is 'int' : valor_ide = int( lista[posicion_ide] ) else: valor_ide = lista[posicion_ide] listadeobjetos.append( self.manager.searchBy( self._obtainColumnForName( self.manager.CLASSid ), valor_ide )[0] ) return listadeobjetos return None ############################## # METODOS PARA REIMPLEMENTAR # ############################## def add( self ): #REIMPLEMENT return self.DialogAddClass( self.manager, itemaeditar = False, managers = self.managers ) def edit( self, obj ): #REIMPLEMENT return self.DialogAddClass( self.manager, itemaeditar = obj, managers = self.managers ) def delete( self, obj ): #REIMPLEMENT self.manager.delete( obj ) ########################## # METODOS DE LOS EVENTOS # ########################## def setItemsCount( self, valor ): ''' Establece en el label la cantidad de elementos listados. ''' self.lbCantidadItems.setText( str( valor ) + ' items(s) seleccionado(s)' ) def on_leBusqueda_textChanged( self, cadena ): self._find() @QtCore.pyqtSlot( int ) def on_cbCampos_currentIndexChanged ( self, entero ): if not self.leBusqueda.text().isEmpty() : self._find() @QtCore.pyqtSlot() def on_btAgregar_clicked( self ): wAgregar = self.add() wAgregar.postSaveMethod = self.reloadList wAgregar.exec_() @QtCore.pyqtSlot() def on_btEditar_clicked( self ): listadeobjetosseleccionados = self.actual_rows_to_objects() if listadeobjetosseleccionados: for obj in listadeobjetosseleccionados: wEditar = self.edit( obj ) wEditar.postSaveMethod = self.reloadList wEditar.exec_() @QtCore.pyqtSlot() def on_btEliminar_clicked( self ): listadeobjetosseleccionados = self.actual_rows_to_objects() if listadeobjetosseleccionados: for obj in listadeobjetosseleccionados: result = QtGui.QMessageBox.warning( self, u"Eliminar " + self.manager.getClassName(), u"¿Esta seguro que desea delete?.\n\n", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No ) if result == QtGui.QMessageBox.Yes: self.delete( obj ) self._find() def on_twDatos_doubleClicked( self , index ): pass ######### # OTROS # ######### def _centerOnScreen ( self ): '''Centers the window on the screen.''' resolution = QtGui.QDesktopWidget().screenGeometry() self.move( ( resolution.width() / 2 ) - ( self.frameSize().width() / 2 ), ( resolution.height() / 2 ) - ( self.frameSize().height() / 2 ) )