zfoxatis

Pyside qtableview

Aug 12th, 2012
427
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #tableview pyside+linux(ubuntu) graphics bug (pyside+windows and pyqt4 good)
  2. # update: fixed 1.1.2 version
  3.  
  4. import sys
  5. import os
  6. import re
  7.  
  8. from PySide.QtGui import *
  9. from PySide.QtCore import *
  10. from PySide.QtSql import *
  11.  
  12. #from PyQt4.QtGui import *
  13. #from PyQt4.QtCore import *
  14. #from PyQt4.QtSql import *
  15.  
  16.  
  17.  
  18. #static dataset
  19.  
  20. from collections import namedtuple
  21.  
  22. # sqltables def
  23. tablefield=namedtuple('tablefield', 'fieldname properties foreignkey')
  24.  
  25. DBTABLES={
  26. 'szl':[
  27. tablefield('id','INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL',''),
  28. tablefield('counter','INTEGER',''),
  29. tablefield('cname','VARCHAR(180)',''),
  30. tablefield('city','VARCHAR(80)',''),
  31. tablefield('street','VARCHAR(80)',''),
  32. tablefield('footer','TEXT','')
  33. ],
  34. 'ttl':[
  35. tablefield('id','INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL',''),
  36. tablefield('code','VARCHAR(20)',''),
  37. tablefield('taxcode','VARCHAR(20)',''),
  38. tablefield('iname','VARCHAR(250)',''),
  39. tablefield('amount','REAL(14,4)',''),
  40. tablefield('netto','REAL(14,4)',''),
  41. tablefield('taxvalue','REAL(14,4)',''),
  42. tablefield('brutto','REAL(14,4)','')
  43. ]}
  44.  
  45. # subgrids def
  46. gridobj=namedtuple('gridobj', 'gridname grouplabel posx posy width height rowstretch columnstretch')
  47.  
  48. GRIDLIST={
  49. 'szl':[
  50. gridobj('gl1','szl valami',0,0,1,1,0,0),
  51. ],
  52. 'ttl':[
  53. gridobj('gl2','tableview ',0,0,1,1,0,0),
  54. gridobj('gl1','fields',1,0,1,1,0,0)
  55. ]}
  56.  
  57.  
  58. #labels text and input object other text
  59. scrobjtext=namedtuple('scrobjtext', 'labeltext statustext whatstext tooltiptext columntext')
  60.  
  61. SCRTEXTLIST={
  62. 'counter':scrobjtext('counter:','','','',''),
  63. 'cname':scrobjtext('Name:','','','',''),
  64. 'city':scrobjtext('Cityname:','','','',''),
  65. 'street':scrobjtext('Street:','','','',''),
  66. 'footer':scrobjtext('footer','','','',''),
  67.  
  68. 'code':scrobjtext('Code: ','','','',''),
  69. 'taxcode':scrobjtext('Taxcode:','','','',''),
  70. 'iname':scrobjtext('Name: ','','','',''),
  71. 'amount':scrobjtext('Amount:','','','',''),
  72. 'netto':scrobjtext('Netto:','','','',''),
  73. 'taxvalue':scrobjtext('Taxvalue','','','',''),
  74. 'brutto':scrobjtext('Brutto','','','','')
  75. }
  76.  
  77. # screen input widgets def and pos and other  
  78. scrobj=namedtuple('scrobj','gridname labelfixedwidth inputfixedwidth inputposx inputposy inputwidth inputheight inputobjname')
  79.  
  80. #(gridname:[inputobj])
  81. SCRLIST={
  82. 'szl':[
  83. scrobj('gl1',100,300,0,1,1,1,'counterMyLineEdit'),
  84. scrobj('gl1',0,0,1,1,1,1,'cnameMyLineEdit'),
  85. scrobj('gl1',0,0,2,1,1,1,'cityMyLineEdit'),
  86. scrobj('gl1',0,0,3,1,1,1,'streetMyLineEdit'),
  87. scrobj('gl1',0,0,4,1,1,1,'valutipusMyComboBox'),
  88. scrobj('gl1',0,0,5,1,1,1,'footerMyTextEdit')
  89. ],
  90. 'ttl':[
  91. scrobj('gl1',100,300,0,1,1,1,'codeMyLineEdit'),
  92. scrobj('gl1',0,0,1,1,1,1,'taxcodeMyLineEdit'),
  93. scrobj('gl1',0,0,2,1,1,1,'inameMyLineEdit'),
  94. scrobj('gl1',0,0,3,1,1,1,'amountMyDoubleSpinBox'),
  95. scrobj('gl1',0,0,4,1,1,1,'nettoMyDoubleSpinBox'),
  96. scrobj('gl1',0,0,5,1,1,1,'taxvalueMyDoubleSpinBox'),
  97. scrobj('gl1',0,0,6,1,1,1,'bruttoMyDoubleSpinBox')
  98. ]}
  99.  
  100. # tables (gridname:[tables])
  101. TABLELIST={
  102. 'ttl':[
  103. scrobj('gl2',0,0,0,0,1,2,'Say_ttlMyTableView')
  104. ]
  105. }
  106.  
  107. # screen tableviews def
  108. tablecol=namedtuple('tablecol','fieldname width')
  109.  
  110. # (TABLELIST.inputobjname:[])
  111. SCRTABLE={
  112. 'Say_ttlMyTableView':[
  113. tablecol('codeMyLineEdit',100),
  114. tablecol('inameMyLineEdit',390),
  115. tablecol('amountMyDoubleSpinBox',100),
  116. tablecol('nettoMyDoubleSpinBox',100),
  117. tablecol('bruttoMyDoubleSpinBox',100)
  118. ]
  119. }
  120.  
  121. # buttons def (gridname:[buttons])
  122. BUTTONLIST={
  123. 'ttl':[
  124. ['firstButton','First',':/first.png','self.firstRecord'],
  125. ['prevButton','Previous',':/prev.png','self.prevRecord'],
  126. ['nextButton','Next',':/next.png','self.nextRecord'],
  127. ['lastButton','Last',':/first.png','self.lastRecord'],
  128. ['newButton','New',':/add.png','self.newRecord'],
  129. ['deleteButton','Delete',':/delete.png','self.deleteRecord'],
  130. ['saveButton','Save',':/save.png','self.saveRecord'],
  131. ['cancelButton','Cancel',':/save.png','self.cancelRecord']
  132. ]}
  133.      
  134. class MyDoubleSpinBox(QDoubleSpinBox):
  135.     def __init__(self):
  136.         super(MyDoubleSpinBox,self).__init__()
  137.         self.setDecimals(2)
  138.         self.setMinimum(0.00)
  139.         self.setMaximum(99999999999.99)
  140.         self.setAlignment(Qt.AlignRight)
  141.        
  142. class MyLabel(QLabel):
  143.     def __init__(self):
  144.         super(MyLabel,self).__init__()
  145.         self.setFont(labelfont)
  146.  
  147. class MyLineEdit(QLineEdit):
  148.     def __init__(self):
  149.         super(MyLineEdit,self).__init__()
  150.  
  151. class MyTextEdit(QTextEdit):
  152.     def __init__(self):
  153.         super(MyTextEdit,self).__init__()    
  154.  
  155. class MyGridLayout(QGridLayout):
  156.     def __init__(self):
  157.         super(MyGridLayout,self).__init__()
  158.         self.setVerticalSpacing(3)
  159.         self.setHorizontalSpacing(3)
  160.  
  161. class ItemFormatDelegate1(QSqlRelationalDelegate):
  162.     def __init__(self, parent=None):
  163.         super(ItemFormatDelegate1, self).__init__(parent)
  164.     def paint(self, painter, option, index):
  165.         myoption = QStyleOptionViewItem(option)
  166.         value=index.data(Qt.DisplayRole)
  167.         if type(value)==int:
  168.             myoption.displayAlignment |= Qt.AlignRight|Qt.AlignVCenter
  169.         elif type(value)==float:
  170.             myoption.displayAlignment |= Qt.AlignRight|Qt.AlignVCenter
  171.         elif type(value)==str:
  172.             myoption.displayAlignment |= Qt.AlignLeft|Qt.AlignVCenter
  173.         else:
  174.             myoption.displayAlignment |= Qt.AlignCenter|Qt.AlignVCenter
  175.         QSqlRelationalDelegate.paint(self, painter, myoption, index)
  176.  
  177. class ItemFormatDelegate(QSqlRelationalDelegate):
  178.     def __init__(self, parent=None):
  179.         super(ItemFormatDelegate, self).__init__(parent)
  180.    
  181.     def paint(self, painter, option, index):
  182.         value=index.data(Qt.DisplayRole)
  183.         if type(value)==int:
  184.             valuealign=Qt.AlignRight|Qt.AlignVCenter
  185.             valueout = '{0:}'.format(value)
  186.  
  187.         elif type(value)==float:
  188.             valuealign=Qt.AlignRight|Qt.AlignVCenter
  189.             valueout = '{0:.2f}'.format(value)
  190.          
  191.         elif type(value)==str:
  192.             valuealign=Qt.AlignLeft|Qt.AlignVCenter
  193.             valueout = '{}'.format(value)
  194.          
  195.         else:
  196.             valuealign=Qt.AlignCenter|Qt.AlignVCenter
  197.             valueout = '{}'.format(value)
  198.        
  199.         painter.drawText(option.rect,valuealign, valueout)
  200.  
  201.          
  202. class MyFrame(QFrame):
  203.     ''' screen factory :frame->gridlayout->groupbox->subgridlayout->qwidgets
  204.        data factory: temptable->QSqlTableModel->QDataWidgetMapper->QTableView
  205.        NAMEDTUPLES:
  206.        subgridlayouts def:     GRIDLIST    [(gridname, grouplabel, posx, posy, width, height, rowstretch, columnstretch)]
  207.        qwidget input def:       SCRLIST     [(gridname, labelfixedwidth, inputfixedwidth, inputposx, inputposy, inputwidth, inputheight, inputobjname)]
  208.        qwidget input def texts: SCRTEXTLIST [(labeltext, statustext, whatstext, tooltiptext, columntext)]
  209.        database sql def:        DBTABLES    [(fieldname, properties)]
  210.        tableview def:           SCRTABLE    [(fieldname, width)]'''
  211.    
  212.     def __init__(self,framename):
  213.         super(MyFrame, self).__init__()
  214.         self.framename=framename
  215.         self.inputlist=[]
  216.         self.tablecolumn=[]
  217.  
  218.         self.gridLayout = MyGridLayout()
  219.         self.gridLayout.setVerticalSpacing(10)
  220.         self.gridLayout.setHorizontalSpacing(10)
  221.         self.createSubgrids()
  222.         self.fields()
  223.         self.addSubgrids()
  224.         self.buttons()
  225.         self.createTmptable()
  226.         self.mapping()
  227.         self.tableViews()
  228.         self.setLayout(self.gridLayout)
  229.  
  230.     def createSubgrids(self):
  231.         try:
  232.             for grid in GRIDLIST[self.framename]:
  233.                 self.__dict__[grid.gridname]=MyGridLayout()
  234.         except:pass
  235.    
  236.     def addSubgrids(self):
  237.         '''subgrids to groupbox to gridLayout'''
  238.         try:
  239.             for grid in GRIDLIST[self.framename]:
  240.                 self.__dict__[grid.gridname].setVerticalSpacing(3)
  241.                 self.__dict__[grid.gridname].setHorizontalSpacing(3)
  242.                 self.__dict__[grid.gridname].setColumnStretch(grid.columnstretch,1)
  243.                 self.__dict__[grid.gridname].setRowStretch(grid.rowstretch,1)
  244.                 self.__dict__[grid.gridname+'groupbox']=QGroupBox()
  245.                 self.__dict__[grid.gridname+'groupbox'].setFont(groupfont)
  246.                 self.__dict__[grid.gridname+'groupbox'].setTitle(grid.grouplabel)
  247.                 self.__dict__[grid.gridname+'groupbox'].setLayout(self.__dict__[grid.gridname])
  248.                 self.gridLayout.addWidget(self.__dict__[grid.gridname+'groupbox'],grid.posx,grid.posy,grid.width,grid.height)
  249.         except:pass
  250.  
  251.     def fields(self):
  252.         '''labels and inputs (lineedit,spinbox...etc)'''
  253.         try:
  254.             for obj in SCRLIST[self.framename]:
  255.                 objdef=re.split('My',obj.inputobjname)
  256.                 objnamekey=objdef[0]
  257.                 objclass=objdef[1]
  258.                 if not objclass.endswith('Label'):
  259.                     self.__dict__[obj.inputobjname]=eval('My'+objclass+'()')
  260.                     self.__dict__[obj.inputobjname].setFont(inputfont)
  261.                     if obj.inputfixedwidth:
  262.                         self.__dict__[obj.inputobjname].setFixedWidth(obj.inputfixedwidth)
  263.                     self.__dict__[obj.gridname].addWidget(self.__dict__[obj.inputobjname],obj.inputposx,obj.inputposy,obj.inputwidth,obj.inputheight)
  264.  
  265.                     self.inputlist.append('self.'+obj.inputobjname) #(to datawidgetmapper)
  266.                     self.tablecolumn.append(objnamekey) #(to model and temptable)
  267.                        
  268.                 if SCRTEXTLIST[objnamekey].labeltext:
  269.                     labelobjname=objnamekey+'MyLabel'
  270.                     self.__dict__[labelobjname]=MyLabel()
  271.                     self.__dict__[labelobjname].setText(SCRTEXTLIST[objnamekey].labeltext)
  272.                     if obj.labelfixedwidth:
  273.                         self.__dict__[labelobjname].setFixedWidth(obj.labelfixedwidth)
  274.                     if obj.inputobjname:
  275.                         self.__dict__[labelobjname].setBuddy(self.__dict__[obj.inputobjname])
  276.                     self.__dict__[obj.gridname].addWidget(self.__dict__[labelobjname],obj.inputposx,obj.inputposy-1,1,1)
  277.         except:pass
  278.  
  279.     def buttons(self):
  280.         try:
  281.             self.buttonLayout = QHBoxLayout()
  282.             for buttonname,buttontext,buttonicon,buttonfunction in BUTTONLIST[self.framename]:
  283.                 self.__dict__[buttonname] = QPushButton()
  284.                 self.__dict__[buttonname].setText(buttontext)
  285.                 self.__dict__[buttonname].setIcon(QIcon(buttonicon))
  286.                 self.buttonLayout.addWidget(self.__dict__[buttonname])
  287.                 self.connect(self.__dict__[buttonname], SIGNAL("clicked()"),eval(buttonfunction))
  288.             self.gridLayout.addLayout(self.buttonLayout, 4, 0, 1, self.gridLayout.columnCount())
  289.         except:
  290.             self.buttonLayout=None
  291.        
  292.     def createTmptable(self):
  293.         if self.tablecolumn and not self.framename+'tmp' in db.tables():
  294.             fieldsqldef=[]
  295.             for field in self.tablecolumn:
  296.                 for dbtable in DBTABLES.keys():
  297.                     for dbfield in DBTABLES[dbtable]:
  298.                         if dbfield.fieldname==field:
  299.                             fieldsqldef.append((dbfield.fieldname,dbfield.properties))
  300.                             field=''
  301.                             exit
  302.                     if not field:
  303.                         exit
  304.             cur=QSqlQuery()
  305.             cur.exec_('CREATE TABLE {0} ( {1} ) '.format(self.framename+'tmp',
  306.                                                          ', '.join(fieldname+' '+properties for fieldname,properties in fieldsqldef)))
  307.          
  308.     def mapping(self):
  309.         try:
  310.             self.model = QSqlTableModel(self)
  311.             self.model.setTable(self.framename+'tmp')
  312.             self.model.select()
  313.             for index,columnname in enumerate(self.tablecolumn):
  314.                  self.model.setHeaderData(index,Qt.Horizontal,SCRTEXTLIST[columnname].columntext
  315.                                           if SCRTEXTLIST[columnname].columntext else SCRTEXTLIST[columnname].labeltext )
  316.             self.mapper = QDataWidgetMapper(self)
  317.             self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
  318.             self.mapper.setModel(self.model)
  319.             for index,inputobj in enumerate(self.inputlist):
  320.                 self.mapper.addMapping(eval(inputobj),index)
  321.             self.mapper.toFirst()
  322.         except:
  323.             self.model=None
  324.             self.mapper=None
  325.      
  326.     def tableViews(self):
  327.         try:
  328.             for obj in TABLELIST[self.framename]:
  329.                 counter=0
  330.                 self.tableview=obj.inputobjname
  331.                 self.__dict__[obj.inputobjname]=QTableView()
  332.                 self.__dict__[obj.inputobjname].setModel(self.model)
  333.                 self.items=ItemFormatDelegate(self)
  334.                 self.__dict__[obj.inputobjname].setItemDelegate(self.items)
  335.                 self.__dict__[obj.inputobjname].setFont(inputfont)
  336.                 self.__dict__[obj.inputobjname].setEditTriggers(QAbstractItemView.NoEditTriggers)
  337.                 self.__dict__[obj.inputobjname].setSelectionBehavior(QAbstractItemView.SelectRows)
  338.                 self.__dict__[obj.inputobjname].setSelectionMode(QTableView.SingleSelection)
  339.                 self.__dict__[obj.inputobjname].horizontalHeader().setStretchLastSection(True)
  340.                
  341.                 for index,inputfield in enumerate(self.inputlist):
  342.                     if re.split('\.',inputfield)[1] in [col.fieldname for col in SCRTABLE[obj.inputobjname]]:
  343.                         self.__dict__[obj.inputobjname].setColumnWidth(index,SCRTABLE[obj.inputobjname][counter].width)
  344.                         counter+=1
  345.                     else:
  346.                         self.__dict__[obj.inputobjname].setColumnHidden(index, True)
  347.                 self.__dict__[obj.gridname].addWidget(self.__dict__[obj.inputobjname],obj.inputposx,obj.inputposy,obj.inputwidth,obj.inputheight)
  348.                 self.__dict__[obj.gridname].setRowMinimumHeight(0,600)
  349.                 self.connect(self.__dict__[obj.inputobjname],SIGNAL('clicked(QModelIndex)'),
  350.                              lambda x:self.mapper.setCurrentModelIndex(self.__dict__[obj.inputobjname].selectedIndexes()[0]))
  351.                 self.tableSelectRow()
  352.         except:pass          
  353.    
  354.     def tableSelectRow(self):
  355.         row = self.mapper.currentIndex()
  356.         eval(self.inputlist[0]).setFocus()
  357.         if self.tableview:
  358.             #self.__dict__[self.tableview].update()
  359.             self.__dict__[self.tableview].selectRow(row)
  360.            
  361.     def firstRecord(self):
  362.         self.mapper.toFirst()
  363.         self.tableSelectRow()
  364.        
  365.     def prevRecord(self):
  366.         self.mapper.toPrevious()
  367.         self.tableSelectRow()
  368.  
  369.     def nextRecord(self):
  370.         self.mapper.toNext()
  371.         self.tableSelectRow()
  372.  
  373.     def lastRecord(self):
  374.         self.mapper.toLast()
  375.         self.tableSelectRow()
  376.  
  377.     def newRecord(self):
  378.         row = self.model.rowCount()
  379.         self.model.insertRow(row)
  380.         #self.model.submitAll()
  381.         self.deleteInputObjectValue()
  382.         self.lastRecord()
  383.  
  384.     def deleteRecord(self):
  385.         if (QMessageBox.question(self,"Delete","Delete ?",QMessageBox.Yes|QMessageBox.No)==QMessageBox.No):
  386.             return
  387.         row = self.mapper.currentIndex()
  388.         self.model.removeRow(row)
  389.         self.model.submitAll()
  390.         if row + 1 >= self.model.rowCount():
  391.             row-=1
  392.         self.mapper.setCurrentIndex(row)
  393.         self.tableSelectRow()
  394.  
  395.     def saveRecord(self):
  396.         row = self.mapper.currentIndex()
  397.         self.mapper.submit()
  398.         #self.model.submitAll()
  399.         self.mapper.setCurrentIndex(row)
  400.         self.tableSelectRow()
  401.  
  402.     def cancelRecord(self):
  403.         self.mapper.revert()
  404.         self.tableSelectRow()
  405.  
  406.     def deleteInputObjectValue(self):
  407.         for key in self.__dict__.keys():
  408.             if not key.startswith('Say_'):
  409.                 if re.search('MyDoubleSpinBox',key):
  410.                     self.__dict__[key].setValue(0)
  411.                 if re.search('MyLineEdit',key):
  412.                     self.__dict__[key].setText('')
  413.                 if re.search('MyTextEdit',key):
  414.                     self.__dict__[key].clear()
  415.                 if re.search('MyComboBox',key):
  416.                     self.__dict__[key].setCurrentIndex(0)
  417.  
  418. class PageOne(MyFrame):
  419.     def __init__(self):
  420.         super(PageOne,self).__init__('szl')      
  421.         self.gridLayout.setColumnStretch(3,1)
  422.         self.gridLayout.setRowStretch(10,1)
  423.  
  424.     def megnincs(self):pass
  425.  
  426. class PageTwo(MyFrame):  
  427.     def __init__(self):
  428.         super(PageTwo,self).__init__('ttl')
  429.         self.gridLayout.setRowStretch(11,1)
  430.  
  431. class MainWindow(QMainWindow):
  432.     def __init__(self,window):
  433.         super(MainWindow, self).__init__()
  434.         window.resize(940,680)
  435.         self.tabwidget = QTabWidget(window)
  436.         self.tabwidget.setGeometry(QRect(10, 10, 920, 660))
  437.         self.szla()
  438.         window.show()
  439.  
  440.     def szla(self):
  441.         self.tab2=QTabWidget()
  442.         self.tabwidget.addTab(self.tab2,'szlprobe')
  443.         self.szlframe=PageOne()
  444.         self.tab2.addTab(self.szlframe,'Szlpage')
  445.         self.ttlframe=PageTwo()
  446.         self.tab2.addTab(self.ttlframe,'Ttlpage')
  447.  
  448.  
  449.  
  450. def createTables():        
  451.     for tablanev in DBTABLES.keys():
  452.         createTable(tablanev)
  453.            
  454. def createTable(tablanev):
  455.     cur=QSqlQuery()  
  456.     cur.exec_('CREATE TABLE {0} ( {1} ) '.format(tablanev,createTableDef(tablanev)))
  457.        
  458. def createTableDef(tablanev):
  459.     return (', '.join(fieldname+' '+properties for fieldname,properties,foreign in DBTABLES[tablanev]))
  460.    
  461.        
  462. if __name__ == '__main__':
  463.     app = QApplication(sys.argv)  
  464.     app.setStyle('plastique') #windowsvista,cleanlooks,windows”, “motif”, “cde”, “plastique”, “windowsxp”, or “macintosh”.
  465.    
  466.     betu=QFont('Arial')
  467.     betu.setPointSize(11)
  468.     betu.setBold(True)
  469.     app.setFont(betu)
  470.    
  471.     inputfont=betu
  472.    
  473.     labelfont=QFont('Arial')
  474.     labelfont.setPointSize(11)
  475.     labelfont.setBold(False)
  476.  
  477.     groupfont=QFont('Arial')
  478.     groupfont.setPointSize(9)
  479.     groupfont.setBold(True)
  480.  
  481.  
  482.     filename = os.path.join(os.path.dirname(__file__), "probe.db")
  483.     create = not QFile.exists(filename)
  484.     db = QSqlDatabase.addDatabase("QSQLITE")
  485.     db.setDatabaseName(filename)
  486.     if not db.open():
  487.         QMessageBox.warning(None, "bugreport","Database error {}".format(db.lastError().text()))
  488.         sys.exit(1)  
  489.     if create:
  490.         createTables()
  491.     window=QMainWindow()
  492.     mainwindow = MainWindow(window)
  493.     sys.exit(app.exec_())
RAW Paste Data