class ServerDialog(QDialog, Ui_ServerDialogDesign): # The threadpool for the workers _threadPool = [] # And it's lock _threadLock = RLock() def __init__(self, server=None, parent=None): """The `ServerDialog` constructor. Parameters: - `serverList`: a `ServerList` instance containing the list of available servers. - `server`: the name of a server. If provided, this server will be selected in the serverList view. """ super(ServerDialog, self).__init__(parent) self.setupUi(self) self.networkIcon.setPixmap(pixmapFromTheme( 'preferences-system-network', ':/icons/48/preferences-system-network') ) self.authIcon.setPixmap(pixmapFromTheme( 'preferences-other', ':/icons/48/preferences-other') ) self.securityIcon.setPixmap(pixmapFromTheme( 'preferences-system', ':/icons/48/preferences-system') ) self.__serverList = ServerList() #Load the serverlist from disk. self.__serverListCopy = None # When we click "Save", the current list is saved here # The list actually returned to the caller. Could be the copy or current active list self.__returnList = None # Create the model used by the views and connect signals for registering # changes (to define the "Cancel"-buttons behaviour). self.slm = ServerListModel(self.__serverList, self) self.slm.dataChanged.connect(self.wasChanged) self.slm.rowsInserted.connect(self.wasChanged) self.slm.rowsRemoved.connect(self.wasChanged) # Used for determining if we should confirm cancel self.isChanged = False # The serverListView works on the servermodel self.serverListView.setModel(self.slm) # Enable/disable editing depending on if we have a server to edit if self.slm.hasServers(): self.tabWidget.setEnabled(True) self.testConnectionButton.setEnabled(True) else: self.tabWidget.setEnabled(False) self.testConnectionButton.setEnabled(False) self.splitter.setStretchFactor(1, 0) # Update list of baseDNs on serverchange self.serverListView.selectionModel().selectionChanged.connect(self.setBaseDN) #Same as below # Map columns of the model to fields in the gui self.mapper = QDataWidgetMapper() self.mapper.setModel(self.slm) # The delegate handles the comboboxes and to-from the list of custom baseDNs # (delegate is used manually for the baseDNs) self.serverDelegate = ServerDelegate() self.mapper.setItemDelegate(self.serverDelegate) self.mapper.addMapping(self.hostEdit, 1) self.mapper.addMapping(self.portSpinBox, 2) self.mapper.addMapping(self.bindAnonBox, 3) self.mapper.addMapping(self.baseDNBox, 4) self.mapper.addMapping(self.bindAsEdit, 6) self.mapper.addMapping(self.passwordEdit, 7) self.mapper.addMapping(self.encryptionBox, 8) self.mapper.addMapping(self.mechanismBox, 9) self.mapper.addMapping(self.aliasBox, 10) self.mapper.addMapping(self.useClientCertBox, 11) self.mapper.addMapping(self.certFileEdit, 12) self.mapper.addMapping(self.certKeyfileEdit, 13) self.mapper.addMapping(self.validateBox, 14) # Workaround to ensure model being updated (Mac OS X bug) self.aliasBox.clicked.connect(self.aliasBox.setFocus) self.baseDNBox.clicked.connect(self.baseDNBox.setFocus) self.bindAnonBox.clicked.connect(self.bindAnonBox.setFocus) self.useClientCertBox.clicked.connect(self.useClientCertBox.setFocus) # Select the first servers (as the serverlistview does) self.mapper.setCurrentIndex(0) self.setBaseDN() # Let the mapper know when another server is selected in the list self.serverListView.selectionModel().currentRowChanged.connect(self.mapper.setCurrentModelIndex) # Enable checks for SSL enabled but with a non-standard port. self.encryptionBox.activated[int].connect(self.checkSSLport) # Used by the connection-test self.testProgress = QProgressDialog("Trying to connect to server.", "Abort", 0, 0, self) self.testProgress.setWindowModality(Qt.WindowModal) # If a servername is supplied we try to get its index, # And make it selected, else we select the first server # in the model) if not server is None: serverIndex = self.__serverList.getIndexByName(server) if serverIndex == -1: serverIndex = 0 index = self.serverListView.model().index(serverIndex, 0) else: index = self.serverListView.model().index(0, 0) # Select it in the view self.serverListView.selectionModel().select(index, QItemSelectionModel.ClearAndSelect) self.serverListView.selectionModel().setCurrentIndex(index, QItemSelectionModel.ClearAndSelect) def checkSSLport(self, index): """ If SSL is choosen with a port other than 636, confirm this with the user """ if index == ServerEncryptionMethod.SSL and self.portSpinBox.value() != 636: ans = QMessageBox.information(self, QCoreApplication.translate("ServerDialog","SSL") ,QCoreApplication.translate("ServerDialog","You have choosen to use SSL but with a port other than 636.\n Do you want this automatically changed?") ,QMessageBox.Yes|QMessageBox.No) if ans == QMessageBox.Yes: self.portSpinBox.setValue(636) if index == ServerEncryptionMethod.Unencrypted and self.portSpinBox.value() != 389: ans = QMessageBox.information(self, QCoreApplication.translate("ServerDialog","Unencrypted") ,QCoreApplication.translate("ServerDialog","You have choosen to use unencryped LDAP but with a port other than 389.\n Do you want this automatically changed?") ,QMessageBox.Yes|QMessageBox.No) if ans == QMessageBox.Yes: self.portSpinBox.setValue(389) def wasChanged(self): """Slot to register that some server settings is changed. """ self.isChanged = True def addBaseDN(self): """Slot for adding a base DN """ tmpBaseDN = unicode(self.baseDNEdit.text()).strip() if tmpBaseDN == u"": return self.baseDNListWidget.addItem(QListWidgetItem(tmpBaseDN)) #Add to list # Save the list of baseDNs serverIndex = self.serverListView.selectedIndexes()[0] index = self.slm.createIndex(serverIndex.row(), 5) # 5 = column for baseDNs self.serverDelegate.setModelData(self.baseDNListWidget, self.slm, index) #save to model self.baseDNEdit.clear() #Clear textfield self.mapper.submit() #Force push to model def deleteBaseDN(self): """Slot for deleting a base DN """ # Delete every selected baseDN for tmpItem in self.baseDNListWidget.selectedItems(): if not (None == tmpItem): index = self.baseDNListWidget.indexFromItem(tmpItem) #get the index to the basedn d = self.baseDNListWidget.takeItem(index.row()) #delete (actually steal) the baseDN from the list if d != 0: del d # Per the QT-docs, someone needs to delete it # Save to model (see addBaseDN()) serverIndex = self.serverListView.selectedIndexes()[0] index = self.slm.createIndex(serverIndex.row(), 5) self.serverDelegate.setModelData(self.baseDNListWidget, self.slm, index) self.mapper.submit() #Force push changes to model def setBaseDN(self): """Slot for setting the base DN-list. """ serverIndex = self.serverListView.selectedIndexes() if len(serverIndex) > 0: index = self.slm.createIndex(serverIndex[0].row(), 5) self.serverDelegate.setEditorData(self.baseDNListWidget, index) def addServer(self): """Create a new ServerObject and add it to the model, and thus the server list. """ name, ok = QInputDialog.getText(self, self.tr('Add server'), self.tr('Name:')) if ok: if len(name) < 1 or self.__serverList.getServerObject(name) != None: QMessageBox.information(self, self.tr('Error'), self.tr("Invalid name or already used.")) return sO = ServerObject() sO.name = unicode(name) # Insert into the model m = self.serverListView.model() success, index = m.addServer(sO) if success: # Display the added server self.serverListView.selectionModel().select(index, QItemSelectionModel.ClearAndSelect) #Select it self.serverListView.selectionModel().setCurrentIndex(index, QItemSelectionModel.ClearAndSelect) #Mark it as current self.mapper.setCurrentIndex(index.row()) # Update the mapper self.tabWidget.setEnabled(True) # Make sure editing is enabled self.testConnectionButton.setEnabled(True) def deleteServer(self): """Delete a server from the model/list """ if self.serverListView.selectionModel().currentIndex().row() < 0: #No server selected return re = QMessageBox.question(self, self.tr('Delete'), self.tr("Are you sure?"), QMessageBox.Yes, QMessageBox.No) if re == QMessageBox.Yes: index = self.serverListView.selectionModel().currentIndex() #Currently selected # Delete the server if self.serverListView.model().delServerAtIndex(index): # When deleting, the view gets updated and selects a new current. # Get it and give it to the mapper newIndex = self.serverListView.selectionModel().currentIndex() self.mapper.setCurrentIndex(newIndex.row()) if not self.slm.hasServers(): self.tabWidget.setEnabled(False) #Disable editing if no servers left self.testConnectionButton.setEnabled(False) def saveServerlist(self): """Called when the Save-button is clicked """ self.mapper.submit() if not self.baseDNsOK(): if not self.isBaseDNsOkMessage(): # If we got here, we DO NOT WANT TO SAVE/QUIT return False self.__serverList.writeServerList() self.__serverListCopy = copy.deepcopy(self.__serverList) return True def reject(self): """Called when the users clicks cancel or presses escape """ # If no changes: just quit if not self.isChanged: QDialog.reject(self) return # Really quit? r = QMessageBox.question(self, self.tr("Exit?"), self.tr("Are you sure you want to exit the server editor?\n Any unsaved changes will be lost!"), QMessageBox.Ok | QMessageBox.Cancel) if not r == QMessageBox.Ok: # Don't quit return # If "save" has been clicked, return the saved list by calling accept() if self.__serverListCopy: #This is non-None if Save has been clicked. self.__returnList = self.__serverListCopy # Return the saved on instead QDialog.accept(self) # Closes the window while indicating the caller needs to get the new list (self.__returnList) return QDialog.reject(self) def accept(self): """Called when OK-button is clicked """ if not self.saveServerlist(): # DO NOT QUIT return self.__returnList = self.__serverList QDialog.accept(self) def isBaseDNsOkMessage(self): r = QMessageBox.question(self, self.tr("BaseDNs not defined"), self.tr("One or more server(s) are setup to use custom base DNs without specifying any.\nDo you still want to save?"), QMessageBox.Yes | QMessageBox.No) if r == QMessageBox.No: return False else: return True def baseDNsOK(self): for server in self.__serverList.getTable(): if server.autoBase == False and len(server.baseDN) < 1: return False return True def getResult(self): return self.__returnList def certFileDialog(self): """Slot for selecting a certificate file. """ certFile = QFileDialog.getOpenFileName(self, self.trUtf8('Select certificate file'), '') if not certFile is None: self.certFileEdit.setText(certFile) self.mapper.submit() def certKeyfileDialog(self): """Slot for selecting a certificate keyfile. """ certKeyfile = QFileDialog.getOpenFileName(self, self.trUtf8('Select certificate keyfile'), '') if not certKeyfile is None: self.certKeyfileEdit.setText(certKeyfile) self.mapper.submit() def testConnection(self): """ Tries to bind to the currently selected server. """ currentServerId = self.serverListView.currentIndex().row() sO = self.__serverList.getServerObjectByIndex(currentServerId) # Busy-dialog self.testProgress.reset() self.testProgress.show() # Try to bind conn = LumaConnectionWrapper(sO, self) conn.bindFinished.connect(self.testFinished) conn.bindAsync(sO.name) #Send the serverName as identifier @pyqtSlot(bool, Exception, str) def testFinished(self, success, exception, serverName): # Unparent the LumaConnectionParent from this object # so that it is GCed (that is the only reference to it.) self.sender().setParent(None) self.testProgress.hide() if self.testProgress.wasCanceled(): return if success: # Success-message QMessageBox.information(self, serverName, unicode(self.tr("Bind to {0} successful!")).format(serverName)) else: # Error-message if exception[0]["desc"] == "Invalid credentials": QMessageBox.warning(self, serverName, unicode(self.tr("Bind to {0} failed:\n{1}\n\n(You do not have to spesify passwords here -- you will be asked when needed.)")).format(serverName,exception[0]["desc"])) return QMessageBox.warning(self, serverName, unicode(self.tr("Bind to {0} failed:\n{1}")).format(serverName, exception[0]["desc"]))
class MainWindow(QMainWindow, fatture_ui.Ui_MainWindow): FIRST, PREV, NEXT, LAST = range(4) def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setupUi(self) self.setupMenu() self.restoreWinSettings() self.editindex = None self.filename = None self.db = QSqlDatabase.addDatabase("QSQLITE") self.loadInitialFile() self.setupUiSignals() def mmUpdate(self): row = self.mapper.currentIndex() id = self.mModel.data(self.mModel.index(row,MID)).toString() self.sModel.setFilter("mmid=%s" % id) self.sModel.select() self.sTableView.setColumnHidden(SID, True) self.sTableView.setColumnHidden(SMID, True) def addDdtRecord(self): if not self.db.isOpen(): self.statusbar.showMessage( "Database non aperto...", 5000) return row = self.mModel.rowCount() self.mapper.submit() self.mModel.insertRow(row) self.mapper.setCurrentIndex(row) self.dateEdit.setDate(QDate.currentDate()) self.dateEdit.setFocus() self.mmUpdate() def delDdtRecord(self): if not self.db.isOpen(): self.statusbar.showMessage( "Database non aperto...", 5000) return row = self.mapper.currentIndex() if row == -1: self.statusbar.showMessage( "Nulla da cancellare...", 5000) return record = self.mModel.record(row) id = record.value(MID).toInt()[0] fatt = record.value(MDOC).toString() if(QMessageBox.question(self, "Cancella Scaffale", "Vuoi cancellare il ddt N': {0} ?".format(fatt), QMessageBox.Yes|QMessageBox.No) == QMessageBox.No): self.statusbar.showMessage( "Cancellazione ddt annullata...", 5000) return # cancella scaffale self.mModel.removeRow(row) self.mModel.submitAll() if row + 1 >= self.mModel.rowCount(): row = self.mModel.rowCount() - 1 self.mapper.setCurrentIndex(row) if self.mModel.rowCount() == 0: self.cauLineEdit.setText(QString("")) self.noteLineEdit.setText(QString("")) self.ddtLineEdit.setText(QString("")) self.cliComboBox.setCurrentIndex(-1) # cancella tutti gli articoli che si riferiscono # allo scaffale cancellato self.sModel.setFilter("mmid=%s" % id) self.sModel.select() self.sModel.removeRows(0, self.sModel.rowCount()) self.sModel.submitAll() self.statusbar.showMessage( "Cancellazione eseguita...", 5000) self.mmUpdate() def addDettRecord(self): if not self.db.isOpen(): self.statusbar.showMessage( "Database non aperto...", 5000) return rowfatt = self.mapper.currentIndex() record = self.mModel.record(rowfatt) masterid = record.value(MID).toInt()[0] if masterid < 1: self.statusbar.showMessage( "Scaffale non valido o non confermato...", 5000) self.dateEdit.setFocus() return # aggiunge la nuova riga alla vista self.sModel.submitAll() self.sModel.select() row = self.sModel.rowCount() self.sModel.insertRow(row) self.sModel.setData(self.sModel.index(row, SMID), QVariant(masterid)) self.sModel.setData(self.sModel.index(row, SQT), QVariant(1)) self.sModel.setData(self.sModel.index(row, SDESC), QVariant("")) self.sModel.setData(self.sModel.index(row, SIMP), QVariant(0.0)) self.sModel.setData(self.sModel.index(row, SIVA), QVariant(20.0)) self.editindex = self.sModel.index(row, SQT) self.sTableView.setCurrentIndex(self.editindex) self.sTableView.edit(self.editindex) def delDettRecord(self): if not self.db.isOpen(): self.statusbar.showMessage( "Database non aperto...", 5000) return selrows = self.sItmSelModel.selectedRows() if not selrows: self.statusbar.showMessage( "No articles selected to delete...", 5000) return if(QMessageBox.question(self, "Cancellazione righe", "Vuoi cancellare: {0} righe?".format(len(selrows)), QMessageBox.Yes|QMessageBox.No) == QMessageBox.No): return QSqlDatabase.database().transaction() query = QSqlQuery() query.prepare("DELETE FROM fattslave WHERE id = :val") for i in selrows: if i.isValid(): query.bindValue(":val", QVariant(i.data().toInt()[0])) query.exec_() QSqlDatabase.database().commit() self.sModel.revertAll() self.mmUpdate() def setupMenu(self): # AboutBox self.connect(self.action_About, SIGNAL("triggered()"), self.showAboutBox) # FileNew self.connect(self.action_New_File, SIGNAL("triggered()"), self.newFile) # FileLoad self.connect(self.action_Load_File, SIGNAL("triggered()"), self.openFile) # Edit customers self.connect(self.action_Add_Customers, SIGNAL("triggered()"), self.editCustomers) def editCustomers(self): relpath = os.path.dirname(__file__) if relpath: relpath = "%s/" % relpath subprocess.call(['python',os.path.join("%s../clienti/" % relpath, "clienti.py")]) self.setupModels() self.setupMappers() self.setupTables() self.mmUpdate() def showAboutBox(self): dlg = aboutfatt.AboutBox(self) dlg.exec_() def creaStrutturaDB(self): query = QSqlQuery() if not ("tipofatt" in self.db.tables()): if not query.exec_("""CREATE TABLE tipofatt ( id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, tfatt VARCHAR(50) NOT NULL)"""): QMessageBox.warning(self, "Gestione Fatture", QString("Creazione tabella tipofatt fallita!")) return False else: # aggiungi voci !!!! query.exec_("""INSERT INTO tipofatt VALUES (NULL,'Fattura Semplice')""") query.exec_("""INSERT INTO tipofatt VALUES (NULL,'Fattura Accompagnatoria')""") query.exec_("""INSERT INTO tipofatt VALUES (NULL,'Nota Accredito')""") if not ("fattmaster" in self.db.tables()): if not query.exec_("""CREATE TABLE fattmaster ( id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, data DATE NOT NULL, doc VARCHAR(50) NOT NULL, idtdoc INTEGER NOT NULL, idcli INTEGER NOT NULL, tpag VARCHAR(50) NOT NULL DEFAULT 'Contanti', causale VARCHAR(200), note VARCHAR(200))"""): QMessageBox.warning(self, "Gestione Fatture", QString("Creazione tabella master fallita!")) return False if not ("fattslave" in self.db.tables()): if not query.exec_("""CREATE TABLE fattslave ( id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, qt INTEGER NOT NULL DEFAULT '1', desc VARCHAR(200) NOT NULL, imp DOUBLE NOT NULL DEFAULT '0.0', iva DOUBLE NOT NULL DEFAULT '20.0', mmid INTEGER NOT NULL, FOREIGN KEY (mmid) REFERENCES master)"""): QMessageBox.warning(self, "Gestione Fatture", QString("Creazione tabella slave fallita!")) return False QMessageBox.information(self, "Gestione Fatture", QString("Database Creato!")) return True if not ("clienti" in self.db.tables()): if not query.exec_("""CREATE TABLE clienti ( id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, ragsoc VARCHAR(200) NOT NULL, indirizzo VARCHAR(200) NOT NULL, piva VARCHAR(15), cf VARCHAR(15), tel VARCHAR(30), fax VARCHAR(30), cell VARCHAR(30), email VARCHAR(50))"""): QMessageBox.warning(self, "Gestione Fatture", QString("Creazione tabella clienti fallita!")) return False return True def loadFile(self, fname=None): if fname is None: return if self.db.isOpen(): self.db.close() self.db.setDatabaseName(QString(fname)) if not self.db.open(): QMessageBox.warning(self, "Gestione Fatture", QString("Database Error: %1") .arg(db.lastError().text())) else: if not self.creaStrutturaDB(): return self.filename = unicode(fname) self.setWindowTitle("Gestione Fatture - %s" % self.filename) self.setupModels() self.setupMappers() self.setupTables() #self.setupItmSignals() self.restoreTablesSettings() self.mmUpdate() def loadInitialFile(self): settings = QSettings() fname = unicode(settings.value("Settings/lastFile").toString()) if fname and QFile.exists(fname): self.loadFile(fname) def openFile(self): dir = os.path.dirname(self.filename) \ if self.filename is not None else "." fname = QFileDialog.getOpenFileName(self, "Gestione Fatture - Scegli database", dir, "*.db") if fname: self.loadFile(fname) def newFile(self): dir = os.path.dirname(self.filename) \ if self.filename is not None else "." fname = QFileDialog.getSaveFileName(self, "Gestione Fatture - Scegli database", dir, "*.db") if fname: self.loadFile(fname) def restoreWinSettings(self): settings = QSettings() self.restoreGeometry( settings.value("MainWindow/Geometry").toByteArray()) def restoreTablesSettings(self): settings = QSettings(self) # per la tablelview for column in range(1, self.sModel.columnCount()-1): width = settings.value("Settings/sTableView/%s" % column, QVariant(60)).toInt()[0] self.sTableView.setColumnWidth(column, width if width > 0 else 60) def keyPressEvent(self, event): if event.key() == Qt.Key_Down: self.addDettRecord() else: QMainWindow.keyPressEvent(self, event) def closeEvent(self, event): self.mapper.submit() settings = QSettings() settings.setValue("MainWindow/Geometry", QVariant( self.saveGeometry())) if self.filename is not None: settings.setValue("Settings/lastFile", QVariant(self.filename)) if self.db.isOpen(): # salva larghezza colonne tabella for column in range(1, self.sModel.columnCount()-1): width = self.sTableView.columnWidth(column) if width: settings.setValue("Settings/sTableView/%s" % column, QVariant(width)) self.db.close() del self.db def setupModels(self): """ Initialize all the application models """ # setup slaveModel self.sModel = MyQSqlTableModel(self) self.sModel.setTable(QString("fattslave")) self.sModel.setHeaderData(SID, Qt.Horizontal, QVariant("ID")) self.sModel.setHeaderData(SQT, Qt.Horizontal, QVariant("Qt")) self.sModel.setHeaderData(SDESC, Qt.Horizontal, QVariant("Descrizione")) self.sModel.setHeaderData(SIMP, Qt.Horizontal, QVariant("Importo")) self.sModel.setHeaderData(SIVA, Qt.Horizontal, QVariant("Iva")) self.sModel.setHeaderData(SMID, Qt.Horizontal, QVariant("idlegato")) self.sModel.setEditStrategy(QSqlTableModel.OnRowChange) self.sModel.select() # setup masterModel self.mModel = QSqlRelationalTableModel(self) self.mModel.setTable(QString("fattmaster")) self.mModel.setSort(MDATA, Qt.AscendingOrder) self.mModel.setRelation(MIDCLI, QSqlRelation("clienti", "id", "ragsoc")) self.mModel.setRelation(MIDTDOC, QSqlRelation("tipofatt", "id", "tfatt")) self.mModel.select() def setupMappers(self): ''' Initialize all the application mappers ''' self.mapper = QDataWidgetMapper(self) self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit) self.mapper.setModel(self.mModel) self.mapper.setItemDelegate(QSqlRelationalDelegate(self)) self.mapper.addMapping(self.dateEdit, MDATA) self.mapper.addMapping(self.fattLineEdit, MDOC) relationModel = self.mModel.relationModel(MIDTDOC) relationModel.setSort(1, Qt.AscendingOrder) relationModel.select() self.tipoFattComboBox.setModel(relationModel) self.tipoFattComboBox.setModelColumn(relationModel.fieldIndex("tfatt")) self.mapper.addMapping(self.tipoFattComboBox, MIDTDOC) relationModel = self.mModel.relationModel(MIDCLI) relationModel.setSort(CRAGSOC, Qt.AscendingOrder) relationModel.select() self.cliComboBox.setModel(relationModel) self.cliComboBox.setModelColumn(relationModel.fieldIndex("ragsoc")) self.mapper.addMapping(self.cliComboBox, MIDCLI) self.mapper.addMapping(self.tipoPagLineEdit, MPAG) self.mapper.addMapping(self.cauLineEdit, MCAU) self.mapper.addMapping(self.noteLineEdit, MNOTE) self.mapper.toFirst() def setupTables(self): """ Initialize all the application tablesview """ self.sTableView.setModel(self.sModel) self.sTableView.setColumnHidden(SID, True) self.sTableView.setColumnHidden(SMID, True) self.sTableView.setWordWrap(True) self.sTableView.resizeRowsToContents() self.sTableView.setAlternatingRowColors(True) self.sItmSelModel = QItemSelectionModel(self.sModel) self.sTableView.setSelectionModel(self.sItmSelModel) self.sTableView.setSelectionBehavior(QTableView.SelectRows) self.sTableView.setTabKeyNavigation(False) self.myDelegate = MyQSqlRelationalDelegate(self) self.sTableView.setItemDelegate(self.myDelegate) self.connect(self.myDelegate, SIGNAL("addDettRecord()"), self.addDettRecord) def setupUiSignals(self): self.connect(self.printPushButton, SIGNAL("clicked()"), self.printFatt) self.connect(self.addMPushButton, SIGNAL("clicked()"), self.addDdtRecord) self.connect(self.delMPushButton, SIGNAL("clicked()"), self.delDdtRecord) self.connect(self.addSPushButton, SIGNAL("clicked()"), self.addDettRecord) self.connect(self.delSPushButton, SIGNAL("clicked()"), self.delDettRecord) self.connect(self.firstMPushButton, SIGNAL("clicked()"), lambda: self.saveRecord(MainWindow.FIRST)) self.connect(self.prevMPushButton, SIGNAL("clicked()"), lambda: self.saveRecord(MainWindow.PREV)) self.connect(self.nextMPushButton, SIGNAL("clicked()"), lambda: self.saveRecord(MainWindow.NEXT)) self.connect(self.lastMPushButton, SIGNAL("clicked()"), lambda: self.saveRecord(MainWindow.LAST)) def saveRecord(self, where): if not self.db.isOpen(): self.statusbar.showMessage( "Database non aperto...", 5000) return row = self.mapper.currentIndex() self.mapper.submit() self.sModel.revertAll() if where == MainWindow.FIRST: row=0 elif where == MainWindow.PREV: row = 0 if row <= 1 else row - 1 elif where == MainWindow.NEXT: row += 1 if row >= self.mModel.rowCount(): row = self.mModel.rowCount() -1 elif where == MainWindow.LAST: row = self.mModel.rowCount()- 1 self.mapper.setCurrentIndex(row) self.mmUpdate() def printFatt(self): ''' Print Inventory ''' if not self.db.isOpen(): self.statusbar.showMessage( "Database non aperto...", 5000) return def makeFATT(copia="Copia Cliente"): qmaster = QSqlQuery() qcli = QSqlQuery() qslave = QSqlQuery() curidx = self.mapper.currentIndex() currec = self.mModel.record(curidx) masterid = currec.value("id").toInt()[0] qmaster.exec_("SELECT id,data,doc,idtdoc,idcli,causale,note " "FROM fattmaster WHERE doc = '%s'" % (currec.value("doc").toString())) qmaster.next() curcli = qmaster.value(4).toInt()[0] qcli.exec_("SELECT id,ragsoc,indirizzo,piva " "FROM clienti WHERE id = %d" % (curcli)) qslave.exec_("SELECT mmid,qt,desc,imp,iva " "FROM fattslave WHERE mmid = '%s'" % (masterid)) qcli.next() # variabili utili alla stampa del report datadoc = currec.value("data").toDate().toString(DATEFORMAT) causaledoc = currec.value("causale").toString() notedoc = currec.value("note").toString() tipodoc = currec.value(3).toString() numdoc = currec.value("doc").toString() cliragsoc = qcli.value(1).toString() cliind = qcli.value(2).toString() clipiva = qcli.value(3).toString() from reportlab.pdfgen.canvas import Canvas from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import cm from reportlab.lib.enums import TA_LEFT,TA_RIGHT,TA_CENTER from reportlab.platypus import Spacer, SimpleDocTemplate, Table, TableStyle, Paragraph, KeepTogether from reportlab.rl_config import defaultPageSize from reportlab.lib import colors from reportlab.lib.pagesizes import letter, A4 from reportlab.lib import textsplit PAGE_WIDTH, PAGE_HEIGHT=defaultPageSize styles = getSampleStyleSheet() styleN = styles['Normal'] styleH = styles['Heading1'] styleH.alignment=TA_CENTER Elements = [] #add some flowables p=Paragraph ps=ParagraphStyle Author = "Stefano Zamprogno" URL = "http://www.zamprogno.it/" email = "*****@*****.**" pageinfo = "%s / %s" % (Author, email) def myLaterPages(c, doc): c.saveState() c.setFont("Times-Bold", 82) c.rotate(45) c.setFillColorRGB(0.9,0.9,0.9) c.drawString(11*cm,2*cm, copia) c.rotate(-45) c.setFillColorRGB(0,0,0) # HEADER if tipodoc == "Fattura Accompagnatoria": subt = 0 else: subt = 3 c.setLineWidth(0.1*cm) c.setStrokeColorRGB(0,0,0) c.line(1.8*cm,(6.2-subt)*cm,19.5*cm,(6.2-subt)*cm) c.setStrokeColorRGB(0.5,0.5,0.5) c.line(1.9*cm,(6.1-subt)*cm,19.6*cm,(6.1-subt)*cm) # cerchi carta c.circle(0.9*cm,6*cm,0.3*cm, fill=1) c.circle(0.9*cm,24*cm,0.3*cm, fill=1) c.setFont("Times-Bold", 14) c.drawCentredString(5*cm, 28*cm, r1) c.setFont("Times-Bold", 9) c.drawCentredString(5*cm, 27.5*cm, r2) c.drawCentredString(5*cm, 27*cm, r3) c.drawCentredString(5*cm, 26.5*cm, r4) c.drawCentredString(5*cm, 26*cm, r5) # numero ddt e descrizione copia c.setFont("Times-Bold", 12) c.drawCentredString(18*cm, 28*cm, "DOC N: %s" % (numdoc)) c.setFont("Times-Bold", 7) c.drawCentredString(18*cm, 27.6*cm, "(%s)" % (copia)) c.drawCentredString(18*cm, 27.2*cm, "%s" % (tipodoc.toUpper())) # Data e causale c.setFont("Times-Bold", 10) c.drawString(1.8*cm, 25*cm, "Data:") c.drawString(1.8*cm, 24.5*cm, "Causale:") c.setFont("Times-Roman", 10) c.drawString(4*cm, 25*cm, unicode(datadoc)) c.drawString(4*cm, 24.5*cm, unicode(causaledoc)) # Cliente c.setFont("Times-Bold", 10) c.drawString(11*cm, 25*cm, "Destinatario:") c.setFont("Times-Roman", 10) c.drawCentredString(16*cm, 25*cm, unicode(cliragsoc)) c.drawCentredString(16*cm, 24.5*cm, unicode(cliind)) c.drawCentredString(16*cm, 24*cm, unicode(clipiva)) # FOOTER c.setFont("Times-Bold", 10) c.setLineWidth(0.01*cm) c.drawString(1.8*cm, (5.5-subt)*cm, "Note:") c.setFont("Times-Roman", 10) strt = (5.5-subt)*cm for i in textsplit.wordSplit(unicode(notedoc),6*cm, "Times-Roman", 10): c.drawString(3*cm, strt, i[1]) strt -= 0.5*cm if tipodoc == "Fattura Accompagnatoria": c.setFont("Times-Bold", 10) c.drawString(12*cm, 5.5*cm, "Data inizio trasporto:") c.line(15.5*cm,5.4*cm,19*cm,5.4*cm) c.drawString(12*cm, 5*cm, "Aspetto dei beni:") c.line(15*cm,4.9*cm,19*cm,4.9*cm) c.drawString(12*cm, 4.5*cm, "Numero colli:") c.line(15*cm,4.4*cm,19*cm,4.4*cm) c.drawString(12*cm, 3.8*cm, "Conducente:") c.line(15*cm,3.7*cm,19*cm,3.7*cm) c.drawString(12*cm, 3*cm, "Destinatario:") c.line(15*cm,2.9*cm,19*cm,2.9*cm) c.drawString(1.8*cm, 4*cm, "Trasporto a Mezzo:") c.line(2.3*cm,3*cm,7*cm,3*cm) # note pie' pagina c.setFont('Times-Roman',9) c.drawString(12.4*cm, 1.5*cm, "Pagina %d %s" % (doc.page, pageinfo)) c.restoreState() # crea il body del ddt data = [['Qt', 'Descrizione dei beni, natura e qualità', 'Importo', 'IVA'],] totimp = 0 totiva = 0 totesiva = 0 while qslave.next(): if qslave.value(4).toDouble()[0]!= 0: totimp += qslave.value(3).toDouble()[0] totiva += (qslave.value(3).toDouble()[0]* qslave.value(4).toDouble()[0] / 100.0) else: totesiva += qslave.value(3).toDouble()[0] data.append([qslave.value(1).toInt()[0], p(unicode(qslave.value(2).toString()), ps(name='Normal')), "€ %.2f" % qslave.value(3).toDouble()[0], "%.2f %%" % qslave.value(4).toDouble()[0]]) Elements.append(Table(data,colWidths=(1*cm,12.5*cm,2*cm,2*cm),repeatRows=1, style=( ['LINEBELOW', (0,0), (-1,0), 1, colors.black], ['BACKGROUND',(0,0),(-1,0), colors.lightgrey], ['GRID',(0,0),(-1,-1), 0.2, colors.black], ['FONT', (0, 0), (-1, 0), 'Helvetica-Bold', 10], ['VALIGN', (0,0), (-1,-1), 'TOP'], ['ALIGN', (0,0), (-1,0), 'CENTER'], ['ALIGN', (2,1), (3,-1), 'RIGHT'], ))) summary = [] summary.append(Spacer(0.5*cm, 0.5*cm)) summary.append(Paragraph("<para align=right><b>___________________________________" "</b></para>", styleN)) summary.append(Paragraph("<para align=right><b>TOTALE IMPONIBILE: " "€ %.2f</b></para>" % totimp, styleN)) summary.append(Paragraph("<para align=right><b>TOTALE IVA: " "€ %.2f</b></para>" % totiva, styleN)) summary.append(Paragraph("<para align=right><b>TOTALE Es.IVA: " "€ %.2f</b></para>" % totesiva, styleN)) summary.append(Spacer(0.5*cm, 0.5*cm)) summary.append(Paragraph("<para align=right><b>TOTALE GENERALE: " "€ %.2f</b></para>" % (totesiva+totimp+totiva), styleN)) Elements.append(KeepTogether(summary)) # 'depure' numddt numdoc = numdoc.replace("/",".") if tipodoc == "Fattura Accompagnatoria": doc = SimpleDocTemplate(os.path.join(os.path.dirname(__file__), "fatt%s.%s.pdf" % (numdoc, copia.replace(" ","."))),topMargin=6.2*cm, bottomMargin=6.2*cm) else: doc = SimpleDocTemplate(os.path.join(os.path.dirname(__file__), "fatt%s.%s.pdf" % (numdoc, copia.replace(" ","."))),topMargin=6.2*cm, bottomMargin=3*cm) doc.build(Elements,onFirstPage=myLaterPages,onLaterPages=myLaterPages) subprocess.Popen(['gnome-open',os.path.join(os.path.dirname(__file__), "fatt%s.%s.pdf" % (numdoc, copia.replace(" ",".")))]) if self.copiaCliCheckBox.isChecked(): makeFATT() if self.copiaIntCheckBox.isChecked(): makeFATT(copia="Copia Interna") if self.copiaVettCheckBox.isChecked(): makeFATT(copia="Copia Vettore")
class MainWindow(QMainWindow, magazzino_ui.Ui_MainWindow): FIRST, PREV, NEXT, LAST = range(4) Clipboard = [] # lista di oggetti def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setupUi(self) self.setupMenu() self.restoreWinSettings() self.editindex = None self.filename = None self.db = QSqlDatabase.addDatabase("QSQLITE") self.loadInitialFile() self.setupUiSignals() def keyPressEvent(self, event): if event.key() == Qt.Key_Down: self.addDettRecord() else: QMainWindow.keyPressEvent(self, event) def creaStrutturaDB(self): query = QSqlQuery() if not ("magamaster" in self.db.tables()): if not query.exec_("""CREATE TABLE magamaster ( id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, scaff VARCHAR(10) NOT NULL)"""): QMessageBox.warning(self, "Magazzino", QString("Creazione tabella fallita!")) return False if not ("magaslave" in self.db.tables()): if not query.exec_("""CREATE TABLE magaslave ( id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, datains DATE NOT NULL, abbi VARCHAR(50), angro VARCHAR(50), desc VARCHAR(100), qt INTEGER NOT NULL DEFAULT '1', imp DOUBLE NOT NULL DEFAULT '0.0', equiv VARCHAR(100), mmid INTEGER NOT NULL, fatt VARCHAR(50), note VARCHAR(200), FOREIGN KEY (mmid) REFERENCES magamaster)"""): QMessageBox.warning(self, "Magazzino", QString("Creazione tabella fallita!")) return False QMessageBox.information(self, "Magazzino", QString("Database Creato!")) return True def loadFile(self, fname=None): if fname is None: return if self.db.isOpen(): self.db.close() self.db.setDatabaseName(QString(fname)) if not self.db.open(): QMessageBox.warning(self, "Magazzino", QString("Database Error: %1") .arg(self.db.lastError().text())) else: if not self.creaStrutturaDB(): return self.filename = unicode(fname) self.setWindowTitle("Gestione Magazzino - %s" % self.filename) self.setupModels() self.setupMappers() self.setupTables() #self.setupItmSignals() self.restoreTablesSettings() self.mmUpdate() def loadInitialFile(self): settings = QSettings() fname = unicode(settings.value("Settings/lastFile").toString()) if fname and QFile.exists(fname): self.loadFile(fname) def openFile(self): dir = os.path.dirname(self.filename) \ if self.filename is not None else "." fname = QFileDialog.getOpenFileName(self, "Gestione Magazzino - Scegli database", dir, "*.db") if fname: self.loadFile(fname) def newFile(self): dir = os.path.dirname(self.filename) \ if self.filename is not None else "." fname = QFileDialog.getSaveFileName(self, "Gestione Magazzino - Scegli database", dir, "*.db") if fname: self.loadFile(fname) def setupMenu(self): # AboutBox self.connect(self.actionA_bout, SIGNAL("triggered()"), self.showAboutBox) # FileNew self.connect(self.action_New_File, SIGNAL("triggered()"), self.newFile) # FileLoad self.connect(self.action_Load_File, SIGNAL("triggered()"), self.openFile) def showAboutBox(self): dlg = aboutmaga.AboutBox(self) dlg.exec_() def printInventory(self): ''' Print Inventory ''' if not self.db.isOpen(): self.statusbar.showMessage( "Database non aperto...", 5000) return querygrp = QSqlQuery() querydett = QSqlQuery() querygrp.exec_("SELECT abbi,qt,imp,sum(qt*imp) " "FROM magaslave GROUP BY abbi") querydett.prepare("SELECT datains,abbi,angro,desc,qt,imp " "FROM magaslave WHERE abbi = :abbi AND " "qt > 0 ORDER BY datains") from reportlab.pdfgen.canvas import Canvas from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import cm from reportlab.lib.enums import TA_LEFT,TA_RIGHT,TA_CENTER from reportlab.platypus import Spacer, SimpleDocTemplate from reportlab.platypus import Table, TableStyle, Paragraph from reportlab.rl_config import defaultPageSize from reportlab.lib import colors PAGE_WIDTH, PAGE_HEIGHT=defaultPageSize styles = getSampleStyleSheet() styleN = styles['Normal'] styleH = styles['Heading1'] styleH.alignment=TA_CENTER Elements = [] #add some flowables p=Paragraph ps=ParagraphStyle Title = unicode(self.prtTitleLineEdit.text()) Year = unicode(self.prtDateLineEdit.text()) Author = "Stefano Zamprogno" URL = "http://www.zamprogno.it/" email = "*****@*****.**" pageinfo = "%s / %s / %s" % (Author, email, Title) def myFirstPage(canvas, doc): canvas.saveState() canvas.setStrokeColorRGB(0.50,0.50,0.50) canvas.setLineWidth(10) canvas.line(45,72,45,PAGE_HEIGHT-72) #canvas.setFont('Times-Bold',16) #canvas.drawCentredString(3*cm, 1.5*cm,Title) canvas.setFont('Times-Roman',9) canvas.drawString(3*cm, 1.5*cm, "First Page / %s" % pageinfo) canvas.restoreState() def myLaterPages(canvas, doc): canvas.saveState() canvas.setStrokeColorRGB(0.50,0.50,0.50) canvas.setLineWidth(5) canvas.line(45,72,45,PAGE_HEIGHT-72) canvas.setFont('Times-Roman',9) canvas.drawString(3*cm, 1.5*cm, "Page %d %s" % (doc.page, pageinfo)) canvas.restoreState() Elements.append(Paragraph(Title, styleH)) Elements.append(Paragraph(Year,styleN)) Elements.append(Spacer(0.5*cm, 0.5*cm)) tot=0 while querygrp.next(): tot += querygrp.value(3).toDouble()[0] querydett.bindValue(":abbi", QVariant(querygrp.value(0).toString())) querydett.exec_() data = [['Abbi', 'Angro', 'Descrizione', 'Qt', 'Imp'],] while querydett.next(): data.append([ p(unicode(querydett.value(1).toString()), ps(name='Normal')), p(unicode(querydett.value(2).toString()), ps(name='Normal')), p(unicode(querydett.value(3).toString()), ps(name='Normal')), querydett.value(4).toInt()[0], unicode("%.2f" % querydett.value(5).toDouble()[0])]) data.append([None, None, unicode("GRUPPO '%s'" % querygrp.value(0).toString()), unicode("Subtotale:"), unicode("€ %.2f" % querygrp.value(3).toDouble()[0])]) Elements.append(Table(data,repeatRows=1, style=(['LINEBELOW', (3,-2), (-1,-2), 1, colors.black], ['LINEBELOW', (0,0), (-1,0), 1, colors.black], ['ALIGN', (1,0), (3,-1),'CENTER'], ['ALIGN', (4,0), (-1,0),'RIGHT'], ['VALIGN', (0,0), (-1,-1), 'TOP'], ['ALIGN', (4,0), (-1,-1), 'RIGHT'], # ['TEXTCOLOR', (0,0), (-1,0), # colors.red], ['BACKGROUND',(0,0),(-1,0), colors.lightgrey], ['GRID',(0,0),(-1,-1), 0.2, colors.black], ['FONT', (0, 0), (-1, 0), 'Helvetica-Bold', 10], ['FONT', (3, -1), (3, -1), 'Helvetica-Bold', 10]))) Elements.append(Spacer(0.5*cm, 0.5*cm)) Elements.append(Paragraph("<para align=right><b>TOTALE GENERALE:" "€ %.2f</b></para>" % tot, styleN)) doc = SimpleDocTemplate(os.path.join(os.path.dirname(__file__), 'mydoc.pdf')) doc.build(Elements,onFirstPage=myFirstPage, onLaterPages=myLaterPages) subprocess.Popen(['gnome-open',os.path.join(os.path.dirname(__file__), 'mydoc.pdf')]) def setupMappers(self): ''' Initialize all the application mappers ''' self.mapper = QDataWidgetMapper(self) self.mapper.setModel(self.mModel) self.mapper.addMapping(self.scaffLineEdit, SCAFF) self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit) self.mapper.toFirst() def setupTables(self): """ Initialize all the application tablesview """ self.sTableView.setModel(self.sModel) self.sTableView.setItemDelegate(MSDelegate(self)) self.sTableView.setColumnHidden(ID, True) self.sTableView.setColumnHidden(MMID, True) self.sTableView.setWordWrap(True) self.sTableView.resizeRowsToContents() self.sTableView.setAlternatingRowColors(True) self.sItmSelModel = QItemSelectionModel(self.sModel) self.sTableView.setSelectionModel(self.sItmSelModel) self.sTableView.setSelectionBehavior(QTableView.SelectRows) #self.sTableView.setTabKeyNavigation(True) self.fTableView.setModel(self.fModel) self.fTableView.setColumnHidden(ID, True) self.fTableView.setWordWrap(True) self.fTableView.resizeRowsToContents() self.fTableView.setAlternatingRowColors(True) self.fItmSelModel = QItemSelectionModel(self.fModel) self.fTableView.setSelectionModel(self.fItmSelModel) def setupModels(self): """ Initialize all the application models """ # setup slaveModel self.sModel = ssModel(self) self.sModel.setTable(QString("magaslave")) self.sModel.setHeaderData(ID, Qt.Horizontal, QVariant("ID")) self.sModel.setHeaderData(DATAINS, Qt.Horizontal, QVariant("DataIns")) self.sModel.setHeaderData(ABBI, Qt.Horizontal, QVariant("Abbi")) self.sModel.setHeaderData(ANGRO, Qt.Horizontal, QVariant("Angro")) self.sModel.setHeaderData(DESC, Qt.Horizontal, QVariant("Desc")) self.sModel.setHeaderData(QT, Qt.Horizontal, QVariant("Qt")) self.sModel.setHeaderData(IMP, Qt.Horizontal, QVariant("Imp")) self.sModel.setHeaderData(EQUIV, Qt.Horizontal, QVariant("Equiv")) self.sModel.setHeaderData(MMID, Qt.Horizontal, QVariant("ScaffId")) self.sModel.setHeaderData(FATT, Qt.Horizontal, QVariant("Fatt")) self.sModel.setHeaderData(NOTE, Qt.Horizontal, QVariant("Note")) self.sModel.setSort(DATAINS, Qt.AscendingOrder) self.sModel.setEditStrategy(QSqlTableModel.OnRowChange) self.sModel.select() # setup masterModel self.mModel = QSqlTableModel(self) self.mModel.setTable(QString("magamaster")) self.mModel.setSort(SCAFF, Qt.AscendingOrder) self.mModel.setHeaderData(ID, Qt.Horizontal, QVariant("ID")) self.mModel.setHeaderData(SCAFF, Qt.Horizontal, QVariant("Scaff")) self.mModel.select() # setup findModel self.fModel = QSqlRelationalTableModel(self) self.fModel.setTable(QString("magaslave")) self.fModel.setHeaderData(ID, Qt.Horizontal, QVariant("ID")) self.fModel.setHeaderData(DATAINS, Qt.Horizontal, QVariant("DataIns")) self.fModel.setHeaderData(ABBI, Qt.Horizontal, QVariant("Abbi")) self.fModel.setHeaderData(ANGRO, Qt.Horizontal, QVariant("Angro")) self.fModel.setHeaderData(DESC, Qt.Horizontal, QVariant("Desc")) self.fModel.setHeaderData(QT, Qt.Horizontal, QVariant("Qt")) self.fModel.setHeaderData(IMP, Qt.Horizontal, QVariant("Imp")) self.fModel.setHeaderData(EQUIV, Qt.Horizontal, QVariant("Equiv")) self.fModel.setHeaderData(MMID, Qt.Horizontal, QVariant("ScaffId")) self.fModel.setHeaderData(FATT, Qt.Horizontal, QVariant("Fatt")) self.fModel.setHeaderData(NOTE, Qt.Horizontal, QVariant("Note")) self.fModel.setSort(MMID, Qt.AscendingOrder) self.fModel.setRelation(MMID, QSqlRelation("magamaster", "id", "scaff")) self.fModel.select() def clipCopy(self): self.Clipboard = self.sTableView.selectedIndexes() selrows = self.sItmSelModel.selectedRows() # TODO : da usare: selrows = self.sItmSelModel.selectedRows() print(selrows, len(selrows)) print(len(self.Clipboard)) # FIXME : bla bla bla def clipDel(self): self.delDettRecord() def clipPaste(self): pass def ctxtMenu(self, point): menu = QMenu(self) copyAction = menu.addAction("&Copy") self.connect(copyAction, SIGNAL("triggered()"), self.clipCopy) delAction = menu.addAction("&Del") self.connect(delAction, SIGNAL("triggered()"), self.clipDel) if len(self.Clipboard) > 0: pasteAction = menu.addAction("&Paste") self.connect(pasteAction, SIGNAL("triggered()"), self.clipPaste) menu.exec_(self.sTableView.mapToGlobal(point)) def setupUiSignals(self): self.sTableView.setContextMenuPolicy(Qt.CustomContextMenu) self.connect(self.sTableView, SIGNAL( "customContextMenuRequested(const QPoint &)"), self.ctxtMenu) self.connect(self.scaffLineEdit, SIGNAL("returnPressed()"), lambda: self.saveRecord(MainWindow.FIRST)) self.connect(self.findLineEdit, SIGNAL("returnPressed()"), self.globalFilter) self.connect(self.printPushButton, SIGNAL("clicked()"), self.printInventory) self.connect(self.createFilterPushButton, SIGNAL("clicked()"), self.createFilter) self.connect(self.findPushButton, SIGNAL("clicked()"), self.applyFilter) self.connect(self.gSearchPushButton, SIGNAL("clicked()"), self.globalFilter) self.connect(self.addscaffPushButton, SIGNAL("clicked()"), self.addScaffRecord) self.connect(self.adddettPushButton, SIGNAL("clicked()"), self.addDettRecord) self.connect(self.deldettPushButton, SIGNAL("clicked()"), self.delDettRecord) self.connect(self.delscaffPushButton, SIGNAL("clicked()"), self.delScaffRecord) self.connect(self.scaffFirstPushButton, SIGNAL("clicked()"), lambda: self.saveRecord(MainWindow.FIRST)) self.connect(self.scaffPrevPushButton, SIGNAL("clicked()"), lambda: self.saveRecord(MainWindow.PREV)) self.connect(self.scaffNextPushButton, SIGNAL("clicked()"), lambda: self.saveRecord(MainWindow.NEXT)) self.connect(self.scaffLastPushButton, SIGNAL("clicked()"), lambda: self.saveRecord(MainWindow.LAST)) def globalFilter(self): if not self.db.isOpen(): self.statusbar.showMessage( "Database non aperto...", 5000) return txt = self.findLineEdit.text() qry = ("(datains like '%s') OR " "(abbi like '%s') OR " "(angro like '%s') OR " "(desc like '%s') OR " "(equiv like '%s') OR" "(fatt like '%s') OR" "(note like '%s')") % ((txt,)*7) self.fModel.setFilter(qry) self.updateFilter() def updateFilter(self): self.fModel.select() self.fTableView.setColumnHidden(ID, True) def applyFilter(self): if not self.db.isOpen(): self.statusbar.showMessage( "Database non aperto...", 5000) return self.fModel.setFilter(self.findLineEdit.text()) self.updateFilter() def createFilter(self): if not self.db.isOpen(): self.statusbar.showMessage( "Database non aperto...", 5000) return headerDef = ("datains VARCHAR(100)", "abbi VARCHAR(100)", "angro VARCHAR(100)", "desc VARCHAR(100)", "qt VARCHAR(100)", "imp VARCHAR(100)", "equiv VARCHAR(100)", "fatt VARCHAR(100)", "note VARCHAR(100)") dlg = filterdialog.FilterDialog(headerDef, QSqlDatabase.database(), self) if(dlg.exec_()): self.findLineEdit.setText(dlg.filterDone() if dlg.filterDone() else "") self.applyFilter() #~ def editEsc(self, idxcur, idxold): #~ if self.editindex and self.editindex.isValid(): #~ if idxcur.row() != self.editindex.row(): #~ self.sModel.revertAll() #~ self.editindex = None def mmUpdate(self): row = self.mapper.currentIndex() id = self.mModel.data(self.mModel.index(row,ID)).toString() self.sModel.setFilter("mmid=%s" % id) self.sModel.select() self.sTableView.setColumnHidden(ID, True) self.sTableView.setColumnHidden(MMID, True) def saveRecord(self, where): if not self.db.isOpen(): self.statusbar.showMessage( "Database non aperto...", 5000) return row = self.mapper.currentIndex() self.mapper.submit() self.sModel.revertAll() if where == MainWindow.FIRST: row=0 elif where == MainWindow.PREV: row = 0 if row <= 1 else row - 1 elif where == MainWindow.NEXT: row += 1 if row >= self.mModel.rowCount(): row = self.mModel.rowCount() -1 elif where == MainWindow.LAST: row = self.mModel.rowCount()- 1 self.mapper.setCurrentIndex(row) self.mmUpdate() def addScaffRecord(self): if not self.db.isOpen(): self.statusbar.showMessage( "Database non aperto...", 5000) return row = self.mModel.rowCount() self.mapper.submit() self.mModel.insertRow(row) self.mapper.setCurrentIndex(row) self.scaffLineEdit.setFocus() self.mmUpdate() def addDettRecord(self): if not self.db.isOpen(): self.statusbar.showMessage( "Database non aperto...", 5000) return rowscaff = self.mapper.currentIndex() record = self.mModel.record(rowscaff) masterid = record.value(ID).toInt()[0] if masterid < 1: self.statusbar.showMessage( "Scaffale non valido o non confermato...", 5000) self.scaffLineEdit.setFocus() return # aggiunge la nuova riga alla vista self.sModel.submitAll() self.sModel.select() row = self.sModel.rowCount() self.sModel.insertRow(row) if row > 1: precfatt = self.sModel.data(self.sModel.index(row-1, FATT)) else: precfatt = '' if row > 1: lastData = self.sModel.data(self.sModel.index(row-1, DATAINS)) else: lastData = '' self.sModel.setData(self.sModel.index(row, MMID), QVariant(masterid)) self.sModel.setData(self.sModel.index(row, QT), QVariant(1)) self.sModel.setData(self.sModel.index(row, IMP), QVariant(0.0)) self.sModel.setData(self.sModel.index(row, FATT), QVariant(precfatt)) self.editindex = self.sModel.index(row, DATAINS) self.sTableView.setCurrentIndex(self.editindex) self.sTableView.edit(self.editindex) def delDettRecord(self): if not self.db.isOpen(): self.statusbar.showMessage( "Database non aperto...", 5000) return selrows = self.sItmSelModel.selectedRows() if not selrows: self.statusbar.showMessage( "No articles selected to delete...", 5000) return if(QMessageBox.question(self, "Cancella Articoli", "Vuoi cancellare: {0} articoli?".format(len(selrows)), QMessageBox.Yes|QMessageBox.No) == QMessageBox.No): return QSqlDatabase.database().transaction() query = QSqlQuery() query.prepare("DELETE FROM magaslave WHERE id = :val") for i in selrows: if i.isValid(): query.bindValue(":val", QVariant(i.data().toInt()[0])) query.exec_() QSqlDatabase.database().commit() self.sModel.revertAll() self.mmUpdate() def delScaffRecord(self): if not self.db.isOpen(): self.statusbar.showMessage( "Database non aperto...", 5000) return row = self.mapper.currentIndex() if row == -1: self.statusbar.showMessage( "Nulla da cancellare...", 5000) return record = self.mModel.record(row) id = record.value(ID).toInt()[0] scaff = record.value(SCAFF).toString() if(QMessageBox.question(self, "Cancella Scaffale", "Vuoi cancellare lo scaffale: {0} ?".format(scaff), QMessageBox.Yes|QMessageBox.No) == QMessageBox.No): self.statusbar.showMessage( "Cancellazione scaffale annullata...", 5000) return # cancella scaffale self.mModel.removeRow(row) self.mModel.submitAll() if row + 1 >= self.mModel.rowCount(): row = self.mModel.rowCount() - 1 self.mapper.setCurrentIndex(row) if self.mModel.rowCount() == 0: self.scaffLineEdit.setText(QString("")) # cancella tutti gli articoli che si riferiscono # allo scaffale cancellato self.sModel.setFilter("mmid=%s" % id) self.sModel.select() self.sModel.removeRows(0, self.sModel.rowCount()) self.sModel.submitAll() self.statusbar.showMessage( "Cancellazione eseguita...", 5000) self.mmUpdate() def restoreTablesSettings(self): settings = QSettings(self) if self.saveTableGeometryCheckBox.isChecked(): # per la tabella slave for c in range(1, self.sModel.columnCount()-1): width = settings.value("Settings/sTableView/%s" % c, QVariant(60)).toInt()[0] self.sTableView.setColumnWidth(c, width if width > 0 else 60) # per la tabella find for c in range(1, self.fModel.columnCount()): width = settings.value("Settings/fTableView/%s" % c, QVariant(60)).toInt()[0] self.fTableView.setColumnWidth(c, width if width > 0 else 60) def restoreWinSettings(self): settings = QSettings() self.prtTitleLineEdit.setText(QString(settings.value( "Settings/printTitle", QVariant( "Situazione Magazzino - TIME di Stefano Zamprogno")).toString())) self.prtDateLineEdit.setText(QString(settings.value( "Settings/printDate", QVariant( "Al 31/12/2008")).toString())) self.saveWinPosCheckBox.setChecked( settings.value("Settings/saveWinPos", QVariant(True)).toBool()) self.saveTableGeometryCheckBox.setChecked( settings.value("Settings/saveTableGeometry", QVariant(True)).toBool()) self.restoreGeometry( settings.value("MainWindow/Geometry").toByteArray()) def closeEvent(self, event): settings = QSettings() if self.filename is not None: settings.setValue("Settings/lastFile", QVariant(self.filename)) settings.setValue("MainWindow/Geometry", QVariant( self.saveGeometry())) settings.setValue("Settings/saveWinPos", QVariant( self.saveWinPosCheckBox.isChecked())) settings.setValue("Settings/saveTableGeometry", QVariant( self.saveTableGeometryCheckBox.isChecked())) settings.setValue("Settings/printTitle", QVariant( self.prtTitleLineEdit.text())) settings.setValue("Settings/printDate", QVariant( self.prtDateLineEdit.text())) if self.db.isOpen(): # salva larghezza colonne tabella slave for c in range(1, self.sModel.columnCount()-1): width = self.sTableView.columnWidth(c) if width: settings.setValue("Settings/sTableView/%s" % c, QVariant(width)) # salva larghezza colonne tabella find for c in range(1, self.fModel.columnCount()): width = self.fTableView.columnWidth(c) if width: settings.setValue("Settings/fTableView/%s" % c, QVariant(width)) self.db.close() del self.db