# -*- coding: utf-8 -*- import os import ConfigParser from shutil import copyfile from PyQt4 import QtGui, QtCore from global_functions import app_dir, titleFont, validar_cnpj from models import conn, cursor class InstitutionDataWidget(QtGui.QWidget): """ Creates the frame that contains the form to insert institution data. """ def __init__(self): """ Setup widgets and select data from de .ini file. """ super(InstitutionDataWidget, self).__init__() # Defines all layouts self.mainLayout = QtGui.QVBoxLayout() self.formLayout = QtGui.QFormLayout() # Initialize ConfigParser self.Config = ConfigParser.ConfigParser() # Window config self.titleLabel = QtGui.QLabel(u"Dados da Instituição", self) self.titleLabel.setFont(titleFont) # Name field self.instName = QtGui.QLabel(u"Nome da Instituição", self) self.instNameLineEdit = QtGui.QLineEdit(self) self.formLayout.addRow(self.instName, self.instNameLineEdit) # Register field self.instID = QtGui.QLabel(u"CNPJ", self) self.instIDLineEdit = QtGui.QLineEdit(self) # Mask for brazilian CNPJ self.instIDLineEdit.setInputMask(u"99.999.999/9999-99") self.formLayout.addRow(self.instID, self.instIDLineEdit) # Phone field self.instPhone = QtGui.QLabel(u"Telefone", self) self.instPhoneLineEdit = QtGui.QLineEdit(self) self.instPhoneLineEdit.setInputMask(u"(99) 09999-9999") self.formLayout.addRow(self.instPhone, self.instPhoneLineEdit) # Address field self.instAddress = QtGui.QLabel(u"Endereço", self) self.instAddressTextEdit = QtGui.QTextEdit(self) self.formLayout.addRow(self.instAddress, self.instAddressTextEdit) # Logo field self.instLogo = QtGui.QLabel(u"Logo da Instituição", self) self.instLogoBtn = QtGui.QPushButton(u"Upload") self.instLogoBtn.clicked.connect(self.upload_logo) self.instLogoName = QtGui.QLabel(u"Faça o upload de uma imagem", self) # Add logo buttons and labels to an horizontal layout self.logoLayout = QtGui.QHBoxLayout() self.logoLayout.addWidget(self.instLogoBtn) self.logoLayout.addWidget(self.instLogoName) self.formLayout.addRow(self.instLogo, self.logoLayout) # A label for showing errors self.errorMsg = QtGui.QLabel(u"", self) self.errorMsg.setStyleSheet("color: red; font-weight: bold;") # Verifies if the .ini file exists try: # If there is existing info in the .ini file # fills the form with it # Read the .ini file self.Config.read(os.path.join(app_dir, "institution.ini")) # Fills the Main info self.instNameLineEdit.setText( unicode(self.Config.get("Main", "name")) ) self.instIDLineEdit.setText( unicode(self.Config.get("Main", "id")) ) self.instLogoName.setText( unicode(self.Config.get("Main", "logo")) ) # Fills the Contact info self.instPhoneLineEdit.setText( unicode(self.Config.get("Contact", "phone")) ) self.instAddressTextEdit.setText( unicode(self.Config.get("Contact", "address")) ) except: pass # Save button self.saveBtn = QtGui.QPushButton(u"Salvar") self.saveBtn.clicked.connect(self.save_data) # Add all widgets to the mainLayout self.mainLayout.addWidget(self.titleLabel) self.mainLayout.addLayout(self.formLayout) self.mainLayout.addWidget(self.errorMsg) self.mainLayout.addWidget(self.saveBtn) # Set the mainLayout as the visible layout self.setLayout(self.mainLayout) def upload_logo(self): """ Uploads and stores the logo file. """ # Grabs the file filename = QtGui.QFileDialog.getOpenFileName( self, u"Escolher", "", u"Image files (*.png *.jpg *.gif)" ) # Verifies if the user chose a path or cancelled if filename != u"": # Split to get only the filename only_file = os.path.basename(unicode(filename)) # Shows the filename in the form, as uploaded self.instLogoName.setText(only_file) # Verifies if there is another logo in the images file img_files = os.listdir(os.path.join(app_dir, "images")) for fl in img_files: if "logo" in fl: # If another logo exists, remove it os.remove(os.path.join(app_dir, "images", fl)) # Change the filename of the new logo to "logo.extension" ext = filename.split(".")[-1] new_filename = os.path.join(app_dir, "images", "logo.{0}".format(ext)) # Copy the logo file to the images folder copyfile(filename, new_filename) def save_data(self): """ Saves the institution data in the .ini file. """ # Verifies if all main fields were filled if unicode(self.instNameLineEdit.text()) == "": self.errorMsg.setText(u"O nome precisa estar preenchido!") elif validar_cnpj(unicode(self.instIDLineEdit.text())) is False: self.errorMsg.setText(u"O CNPJ é inválido!") elif unicode(self.instLogoName.text()) == \ u"Faça o upload de uma imagem": self.errorMsg.setText(u"É necessário fazer upload " u"da logo para o certificado!") else: # Open the .ini file cfgfile = open(os.path.join(app_dir, "institution.ini"), "w") # If the sections of the .ini file already exists, do nothing # else, create the section try: self.Config.add_section("Main") self.Config.add_section("Contact") except: pass # Fill the Main section self.Config.set("Main", "name", str(self.instNameLineEdit.text())) self.Config.set("Main", "id", str(self.instIDLineEdit.text())) # Fill the Contact section self.Config.set("Contact", "phone", str(self.instPhoneLineEdit.text())) self.Config.set("Contact", "address", str(self.instAddressTextEdit.toPlainText())) if unicode(self.instLogoName.text()) != \ u"Faça o upload de uma imagem": # If we uploaded the logo, then save it's original name # just for showing the user what file we are using self.Config.set("Main", "logo", str(self.instLogoName.text())) else: # If we did not upload the logo, then there is no name self.Config.set("Main", "logo", "") # Write changes to the .ini file self.Config.write(cfgfile) cfgfile.close() self.errorMsg.setText(u"Salvo!") class ConfigMailWidget(QtGui.QWidget): """ A frame with a form to fill the email info, so the app can send emails using the institution account. """ def __init__(self): """ Setup widgets and connect to the .ini file. """ super(ConfigMailWidget, self).__init__() # Defines all layouts self.mainLayout = QtGui.QVBoxLayout() self.formLayout = QtGui.QFormLayout() # Initialize the ConfigParser self.Config = ConfigParser.ConfigParser() # Window config self.titleLabel = QtGui.QLabel(u"Configuração de email", self) self.titleLabel.setFont(titleFont) # Server field self.mailServer = QtGui.QLabel(u"Servidor SMTP") self.mailServerLineEdit = QtGui.QLineEdit(self) self.mailServerLineEdit.setPlaceholderText(u"Ex: smtp.gmail.com") self.formLayout.addRow(self.mailServer, self.mailServerLineEdit) # Port field self.mailPort = QtGui.QLabel(u"Porta SMTP") self.mailPortLineEdit = QtGui.QLineEdit(self) self.mailPortLineEdit.setPlaceholderText(u"Ex: 587") self.mailPortLineEdit.setValidator(QtGui.QIntValidator(0, 9999, self)) self.formLayout.addRow(self.mailPort, self.mailPortLineEdit) # Email field self.mailEmail = QtGui.QLabel(u"Email") self.mailEmailLineEdit = QtGui.QLineEdit(self) self.mailEmailLineEdit.setPlaceholderText(u"Ex: seu@email.com") self.formLayout.addRow(self.mailEmail, self.mailEmailLineEdit) # Password field self.mailPswd = QtGui.QLabel(u"Password") self.mailPswdLineEdit = QtGui.QLineEdit(self) self.mailPswdLineEdit.setEchoMode(QtGui.QLineEdit.Password) self.formLayout.addRow(self.mailPswd, self.mailPswdLineEdit) # A label for showing errors self.errorMsg = QtGui.QLabel(u"", self) self.errorMsg.setStyleSheet("color: red; font-weight: bold;") # Save button self.saveBtn = QtGui.QPushButton(u"Salvar") self.saveBtn.clicked.connect(self.save_data) # Verifies if the .ini file exists try: # If the .ini file exists, fill the form # with the info saved in it # Read the .ini file self.Config.read(os.path.join(app_dir, "institution.ini")) # Get Mail info self.mailServerLineEdit.setText( unicode(self.Config.get("Mail", "server")) ) self.mailPortLineEdit.setText( unicode(self.Config.get("Mail", "port")) ) self.mailEmailLineEdit.setText( unicode(self.Config.get("Mail", "email")) ) self.mailPswdLineEdit.setText( unicode(self.Config.get("Mail", "password")) ) except: pass # Add all widgets to the mainLayout self.mainLayout.addWidget(self.titleLabel) self.mainLayout.addLayout(self.formLayout) self.mainLayout.addWidget(self.errorMsg) self.mainLayout.addWidget(self.saveBtn) self.mainLayout.addStretch() # Set the mainLayout as the visible layout self.setLayout(self.mainLayout) def save_data(self): """ Saves the mail data in the .ini file. """ # Verifies if all fields are filled if unicode(self.mailServerLineEdit.text()) == "": self.errorMsg.setText(u"O servidor precisa estar preenchido!") elif unicode(self.mailPortLineEdit.text()) == "": self.errorMsg.setText(u"A porta precisa estar preenchida!") elif unicode(self.mailEmailLineEdit.text()) == "": self.errorMsg.setText(u"O email precisa estar preenchido!") elif unicode(self.mailPswdLineEdit.text()) == "": self.errorMsg.setText(u"A senha precisa estar preenchida!") else: # Open the .ini file cfgfile = open(os.path.join(app_dir, "institution.ini"), "w") # Verifies if the Mail section already exists # If not, creates it try: self.Config.add_section("Mail") except: pass # Fill the Mail section self.Config.set("Mail", "server", str(self.mailServerLineEdit.text())) self.Config.set("Mail", "port", str(self.mailPortLineEdit.text())) self.Config.set("Mail", "email", str(self.mailEmailLineEdit.text())) self.Config.set("Mail", "password", str(self.mailPswdLineEdit.text())) # Write the data self.Config.write(cfgfile) cfgfile.close() self.errorMsg.setText(u"Salvo!") class SignaturesListWidget(QtGui.QWidget): """ A frame to show a list of existing signatures and CRUD options. """ def __init__(self): """ Setup widgets and select signatures data from the database. """ super(SignaturesListWidget, self).__init__() # Defines all layouts self.mainLayout = QtGui.QVBoxLayout() self.listLayout = QtGui.QHBoxLayout() self.btnsLayout = QtGui.QVBoxLayout() # Window config self.titleLabel = QtGui.QLabel(u"Assinaturas cadastradas", self) self.titleLabel.setFont(titleFont) # Creates the btnsLayout and adds CRUD buttons self.addBtn = QtGui.QPushButton(u"Adicionar") self.addBtn.clicked.connect(self.add_signature) self.editBtn = QtGui.QPushButton(u"Editar") self.editBtn.clicked.connect(self.update_signature) self.removeBtn = QtGui.QPushButton(u"Remover") self.removeBtn.clicked.connect(self.remove_signature) self.btnsLayout.addWidget(self.addBtn) self.btnsLayout.addWidget(self.editBtn) self.btnsLayout.addWidget(self.removeBtn) self.btnsLayout.addStretch() # Create a list widget for showing existing signatures self.signaturesList = QtGui.QListWidget() # Loads all signatures self.load_list() # A label for showing errors self.errorMsg = QtGui.QLabel(u"", self) self.errorMsg.setStyleSheet("color: red; font-weight: bold;") # Add widgets to an horizontal layout self.listLayout.addWidget(self.signaturesList) self.listLayout.addLayout(self.btnsLayout) # Add all widgets to the mainLayout self.mainLayout.addWidget(self.titleLabel) self.mainLayout.addLayout(self.listLayout) self.mainLayout.addWidget(self.errorMsg) # Set the mainLayout as the visible layout self.setLayout(self.mainLayout) def load_list(self): """ Updates the list widget with the signatures data. """ # Clear the list widget to add new data self.signaturesList.clear() # Select all signatures cursor.execute("SELECT * FROM signatures ORDER BY name ASC") self.signatures = cursor.fetchall() # Add all signatures to the list widget for sig in self.signatures: self.signaturesList.addItem(unicode(sig[1])) def add_signature(self): """ Register a new signature. """ # Open a dialog with a form for creating a new signature self.add_sig_widget = SignaturesDialog(self) self.add_sig_widget.show() def update_signature(self): """ Edit an existing signature. """ # Verifies if there is a selectd signature try: # Gets the selected signature id sig_id = self.signatures[self.signaturesList.currentRow()][0] # Opens a dialog with a form filled with the signature data self.update_sig_widget = SignaturesDialog(self, sig_id) self.update_sig_widget.show() except IndexError: self.errorMsg.setText(u"Selecione um registro existente!") def remove_signature(self): """ Delete an existing signature. """ # Verifies if there is a selected signature try: # Gets the selected signature id sig_id = self.signatures[self.signaturesList.currentRow()][0] # Asks if the user really wants to delete the signature choice = QtGui.QMessageBox.question( self, u"Apagar assinatura", u"Tem certeza que deseja apagar esta assinatura?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No ) if choice == QtGui.QMessageBox.Yes: os.remove(os.path.join(app_dir, "signatures", "{0}.png".format(str(sig_id)))) cursor.execute( "DELETE FROM signatures WHERE id=?", (str(sig_id),) ) conn.commit() else: pass # Updates the signatures list self.load_list() except IndexError: self.errorMsg.setText(u"Selecione um registro existente!") class SignaturesDialog(QtGui.QDialog): """ A dialog with a form for register or update signatures. """ def __init__(self, sig_list_instance, sig_id=None): """ Setup widgets. """ super(SignaturesDialog, self).__init__() # Window config self.setGeometry(450, 300, 450, 150) self.sig_id = sig_id self.sig_list_instance = sig_list_instance self.filename = None sig_name = str(self.sig_id)+".png" # Define all layouts self.mainLayout = QtGui.QVBoxLayout() self.formLayout = QtGui.QFormLayout() self.uploadLayout = QtGui.QHBoxLayout() # Name field self.sigName = QtGui.QLabel(u"Nome Completo", self) self.sigNameLineEdit = QtGui.QLineEdit(self) self.sigNameLineEdit.setPlaceholderText(u"Ex: Fulano da Silva") self.formLayout.addRow(self.sigName, self.sigNameLineEdit) # Role field self.sigRole = QtGui.QLabel(u"Cargo", self) self.sigRoleLineEdit = QtGui.QLineEdit(self) self.sigRoleLineEdit.setPlaceholderText(u"Ex: Presidente") self.formLayout.addRow(self.sigRole, self.sigRoleLineEdit) # Register (civil ID) field self.sigRegister = QtGui.QLabel(u"CPF", self) self.sigRegisterLineEdit = QtGui.QLineEdit(self) # Mask for brazilian CPF self.sigRegisterLineEdit.setInputMask(u"999.999.999-99") self.formLayout.addRow(self.sigRegister, self.sigRegisterLineEdit) # Email field self.sigEmail = QtGui.QLabel(u"Email", self) self.sigEmailLineEdit = QtGui.QLineEdit(self) self.sigEmailLineEdit.setPlaceholderText(u"Ex: seu@email.com") self.formLayout.addRow(self.sigEmail, self.sigEmailLineEdit) # Upload field self.sigUpload = QtGui.QLabel(u"Upload da Assinatura", self) self.sigUploadBtn = QtGui.QPushButton(u"Upload") self.sigUploadBtn.clicked.connect(self.upload_signature) self.uploadLayout.addWidget(self.sigUploadBtn) if sig_name not in os.listdir(os.path.join(app_dir, "signatures")): self.sigUploadName = QtGui.QLabel( u"Faça o upload da assinatura", self) self.uploadLayout.addWidget(self.sigUploadName) else: self.sigUploadName = QtGui.QLabel("", self) self.formLayout.addRow(self.sigUpload, self.uploadLayout) # A label for showing errors self.errorMsg = QtGui.QLabel(u"", self) self.errorMsg.setStyleSheet("color: red; font-weight: bold;") # Save button self.saveBtn = QtGui.QPushButton(u"Salvar") self.saveBtn.clicked.connect(self.save_data) # Verifies if the user is creating or updating the signature # If updating, fills the form with the record data if self.sig_id: # Window config self.setWindowTitle(u"Editar assinatura") self.titleLabel = QtGui.QLabel(u"Editar assinatura", self) self.titleLabel.setFont(titleFont) # Select the signature data cursor.execute( "SELECT * FROM signatures WHERE id=?", (str(self.sig_id),) ) data = cursor.fetchone() # Fills the form with the data self.sigNameLineEdit.setText(unicode(data[1])) self.sigRoleLineEdit.setText(unicode(data[2])) self.sigEmailLineEdit.setText(unicode(data[3])) self.sigRegisterLineEdit.setText(unicode(data[4])) else: # Window config self.setWindowTitle(u"Cadastrar assinatura") self.titleLabel = QtGui.QLabel(u"Cadastrar assinatura", self) self.titleLabel.setFont(titleFont) # Add all widgets to the mainLayout self.mainLayout.addWidget(self.titleLabel) self.mainLayout.addLayout(self.formLayout) self.mainLayout.addWidget(self.errorMsg) self.mainLayout.addWidget(self.saveBtn) # Set the mainLayout as the visible layout self.setLayout(self.mainLayout) def upload_signature(self): """ Uploads the signature image. """ # Asks for the signature image file self.filename = QtGui.QFileDialog.getOpenFileName( self, u"Escolher", "", u"Image files (*.png)" ) # Verifies if the user chose a path or cancelled if self.filename != u"": # Gets only the filename only_file = os.path.basename(unicode(self.filename)) self.sigUploadName.setText(only_file) def save_data(self): """ Save the signature data. """ # Verifies if all fields are filled if unicode(self.sigNameLineEdit.text()) == "": self.errorMsg.setText(u"O nome precisa estar preenchido!") elif unicode(self.sigRoleLineEdit.text()) == "": self.errorMsg.setText(u"O cargo precisa estar preenchido!") elif unicode(self.sigEmailLineEdit.text()) == "": self.errorMsg.setText(u"O email precisa estar preenchido!") elif unicode(self.sigUploadName.text()) == \ u"Faça o upload da assinatura": self.errorMsg.setText(u"É necessário fazer upload " u"da assinatura em .png!") else: # Verifies if creating or updating the signature if self.sig_id: # Updates the signature in the database cursor.execute( "UPDATE signatures SET name=?, role=?, email=?, \ register=? WHERE id=?", ( unicode(self.sigNameLineEdit.text()), unicode(self.sigRoleLineEdit.text()), unicode(self.sigEmailLineEdit.text()), unicode(self.sigRegisterLineEdit.text()), unicode(self.sig_id) ) ) # Replace signature image for the new one if self.filename: new_filename = os.path.join( app_dir, "signatures", "{0}.png".format(str(self.sig_id)) ) copyfile(self.filename, new_filename) # Save changes to the database conn.commit() # Updates the signatures list self.sig_list_instance.load_list() # Hide the dialog self.hide() else: # Verifies if the signature already exists cursor.execute( "SELECT id FROM signatures WHERE register=?", (str(self.sigRegisterLineEdit.text()),) ) existing_user = cursor.fetchone() if existing_user: # If the signature exists, show an error message error = QtGui.QMessageBox() error.setIcon(QtGui.QMessageBox.Critical) error.setText(u"A assinatura já está cadastrada!") error.setInformativeText(u"Já existe uma assinatura " u"com este CPF cadastrada " u"no programa.") error.setWindowTitle(u"Assinatura já cadastrada!") error.setStandardButtons(QtGui.QMessageBox.Ok) error.exec_() else: # Else, insert data in the database cursor.execute( "INSERT INTO signatures VALUES (NULL,?,?,?,?)", ( unicode(self.sigNameLineEdit.text()), unicode(self.sigRoleLineEdit.text()), unicode(self.sigEmailLineEdit.text()), unicode(self.sigRegisterLineEdit.text()) ) ) self.sig_id = cursor.lastrowid # Create the new signature file if self.filename: new_filename = os.path.join( app_dir, "signatures", "{0}.png".format(str(self.sig_id)) ) copyfile(self.filename, new_filename) # Save changes to the database conn.commit() # Updates the signatures list self.sig_list_instance.load_list() # Hide the dialog self.hide()