Como vimos nosso arquivo principal usa outros arquivos do projeto, é claro. Estes arquivos seguem o mesmo modelo, com exceção do funcoes.py que não define nenhuma classe, apenas, como o nome já diz, tem funções e variáveis que usaremos globalmente no aplicativo. A principal função deste arquivo é a conexão com o banco, além das funções auxiliares.
Arquivo: funcoes.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Importação das bibliotecas
import pygtk
pygtk.require('2.0')
import gtk
from gtk import glade
from sqlite3 import *
#Conexão com o banco
cnx = connect('/opt/gfpopen/gfp.sqlite')
query = cnx.cursor()
#Variáveis globais
CaminhoGlade = '/opt/gfpopen/glade/'
#Variáveis do usuário logado
usuariologadoid = 0
usuariologadouser = ''
usuariologadonome = ''
#Mostra caixa de mensagem
def Mensagem(pai, S):
dialog = gtk.MessageDialog(pai,
gtk.DIALOG_MODAL |
gtk.DIALOG_DESTROY_WITH_PARENT,
gtk.MESSAGE_INFO, gtk.BUTTONS_OK,
S)
dialog.set_title("Informação")
dialog.run()
dialog.destroy()
#Mostra mensagem de confirmação
def MsgConfirmacao(pai, S):
dialog = gtk.MessageDialog(pai,
gtk.DIALOG_MODAL |
gtk.DIALOG_DESTROY_WITH_PARENT,
gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO,
S)
dialog.set_title("Confirmação")
R = dialog.run()
dialog.destroy()
if R == gtk.RESPONSE_YES:
return True
else:
return False
#Coloca edit em maiúsculo
def StrToMais(edt):
new_text = TiraAspa(edt.get_text().upper())
edt.set_text(new_text)
#Limpa espaços em branco
def StrToTrim(edt):
new_text = TiraAspa(edt.get_text().strip())
edt.set_text(new_text)
def TiraAspa(s):
return s.replace("'", "")
Este arquivo é simples e creio que com a ajuda dos comentários ele se auto-explica. Só vou detalhar sobre a conexão com o banco, como ela é simples, começa pela importação da biblioteca pro SQLite:
from sqlite3 import *
A conexão é simples. O meio de campo é feito através de um cursor, que funciona semelhante a uma mysql_query do PHP, por exemplo. Eu inclusive usei o nome da variável como query pra ficar mais cômodo.
#Conexão com o banco
cnx = connect('/opt/gfpopen/gfp.sqlite')
query = cnx.cursor()
Como ler os resultados retornados e como executar comandos SQL no banco, embora já tenha aparecido no arquivo principal, vai ser mostrado logo em seguida.
Cadastro de usuários
Quando executamos o nosso programa logo na tela de login temos um botão pra chamar a tela para cadastrar um usuário, tela esta que é chamada la no gfp.py na função AbreCadastroUsu através do comando:
usuarioscadastro.UsuariosCadastro(widget, True, 0, winLogin, self)
Estamos chamando diretamente a classe e executando seu método construtor. Note que os parâmetros que passamos são os mesmos que lá na classe UsuariosCadastro são declarados em:
def __init__(self, widget, novo, id, pai, paiclasse):
Agora vamos direto ao arquivo completo.
Arquivo: usuarioscadastro.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Importação das bibliotecas
import pygtk
pygtk.require('2.0')
import gtk
from gtk import glade
import gobject
from sqlite3 import *
#Importa arquivos do projeto
import funcoes as f
import usuarioslista
class UsuariosCadastro(gtk.Window):
#Construtor
def __init__(self, widget, novo, id, pai, paiclasse):
#Inicializar
super(UsuariosCadastro, self).__init__()
self.AbreCadUser(widget, novo, id, pai, paiclasse)
#Cria a tela
def AbreCadUser(self, widget, novo, id, pai, paiclasse):
#Associa arquivo glade
GLADE_FILE = f.CaminhoGlade + 'usuarioslista.glade'
gui = glade.XML(GLADE_FILE, 'winUserCadastro')
#Associa controles
self.win = gui.get_widget('winUserCadastro')
self.edtSenha = gui.get_widget('edtSenha')
self.edtConfirmar = gui.get_widget('edtConfirmar')
self.edtNome = gui.get_widget('edtNome')
self.lblDicaUser = gui.get_widget('lblSomenteLetras')
self.edtUsuario = gui.get_widget('edtUsuario')
self.btnSair = gui.get_widget('btnCancelar')
self.imgSenha = gui.get_widget('imgAlertaSenha')
self.btnSalvar = gui.get_widget('btnOk')
self.myNovo = novo
self.MyId = id
self.MyPai = pai
self.MyPaiClasse = paiclasse
#Formata controles
self.lblDicaUser.set_markup("(somente letras, sem espaços ou acentos)")
#Associa evento dos controles
self.edtUsuario.connect("changed", lambda *a: f.StrToMais(self.edtUsuario))
self.edtUsuario.connect("focus_out_event", lambda *a: f.StrToTrim(self.edtUsuario))
self.edtNome.connect("focus_out_event", lambda *a: f.StrToTrim(self.edtNome))
self.edtSenha.connect("focus_out_event", lambda *a: self.AlertaSenha(widget))
self.edtSenha.connect("changed", lambda *a: self.edtSenha.set_text(f.TiraAspa(self.edtSenha.get_text())))
self.edtConfirmar.connect("focus_out_event", lambda *a: self.AlertaSenha(widget))
self.edtConfirmar.connect("changed", lambda *a: f.TiraAspa(self.edtConfirmar.get_text()))
self.btnSair.connect('clicked', lambda *a: self.Fechar(widget))
self.btnSalvar.connect('clicked', lambda *a: self.VerificaDigitacao(widget))
#Configura modo de edição do form
if self.myNovo == False:
self.edtUsuario.set_editable(False)
self.edtUsuario.set_can_focus(False)
self.lblDicaUser.set_markup("(não pode ser alterado)")
#Executa query
f.query.execute('SELECT user, nome, senha FROM usuarios WHERE id =' + str(self.MyId))
#Preenche os controles
for row in f.query:
self.edtUsuario.set_text(row[0])
self.edtNome.set_text(row[1])
self.edtSenha.set_text(row[2])
self.edtConfirmar.set_text(row[2])
self.win.set_focus(self.edtSenha)
#Abre janela
self.win.show_all()
self.imgSenha.set_visible(False)
return True
#Fechar janela
def Fechar(self, widget):
self.win.destroy() == True
#Alerta de senha
def AlertaSenha(self, widget):
if self.edtConfirmar.get_text() != '':
if self.edtSenha.get_text() != self.edtConfirmar.get_text():
self.imgSenha.set_visible(True)
else:
self.imgSenha.set_visible(False)
#Verificação das digitações
def VerificaDigitacao(self, widget):
#Verifica usuário
if self.edtUsuario.get_text() == '':
f.Mensagem(self.win, 'Informe o usuário.')
self.win.set_focus(self.edtUsuario)
return
#Verifica a senha
if self.edtSenha.get_text() == '' or self.edtSenha.get_text() != self.edtConfirmar.get_text():
f.Mensagem(self.win, 'Verifique a senha.')
self.win.set_focus(self.edtSenha)
return
#Verifica nome
if self.edtNome.get_text() == '':
f.Mensagem(self.win, 'Informe o nome completo.')
self.win.set_focus(self.edtNome)
return
#Verifica se o usuário já existe
if self.myNovo == True:
f.query.execute("SELECT id, user, nome FROM usuarios WHERE user = '" + self.edtUsuario.get_text() + "'")
userExiste = False
for row in f.query:
userExiste = True
if userExiste:
f.Mensagem(self.win, 'Já existe um usuário ' + self.edtUsuario.get_text() + ' cadastrado.')
self.win.set_focus(self.edtUsuario)
else:
if self.myNovo == True:
sAcao = 'cadastrado'
f.query.execute("INSERT INTO usuarios (user, nome, senha)\
VALUES('" + self.edtUsuario.get_text() + "',\
'" + self.edtNome.get_text() + "',\
'" + self.edtSenha.get_text() + "')")
else:
sAcao = 'alterado'
f.query.execute("UPDATE usuarios\
SET nome = '" + self.edtNome.get_text() + "',\
senha = '" + self.edtSenha.get_text() + "'\
WHERE id = " + str(self.MyId))
f.cnx.commit()
f.Mensagem(self.MyPai, 'Usuário ' + sAcao + ' com sucesso.')
self.MyPaiClasse.ListaUsers()
self.win.destroy() == True
Demonstrado por inteiro, através dos comentários também vemos o que cada bloco faz. Mas aqui quero destacar as instruções com o banco de dados. Logo após a seção inicial do arquivo onde montamos e chamamos a tela, por ser um cadastro verificamos se o parâmetro chamamos para inserção ou edição, e se for edição selecionamos o registro a editar e exibimos os campos nos controle. Isso nós fazemos na instrução abaixo. Note que lemos o resultados da query num for e "pegamos" o valor dos campos de acordo com o índice referente à posição que passamos os campos no SQL.
Esse método usando loop é o mesmo que usamos na listagem de todos os usuários (conforme veremos adiante), e mesmo sendo apenas um registro (como fica óbvio) não tem problema usar o for pois ele também só vai executar as instruções pra atribuir os valores aos campos uma vez, pois só um registro é retornado no nosso
SQL.
#Configura modo de edição do form
if self.myNovo == False:
self.edtUsuario.set_editable(False)
self.edtUsuario.set_can_focus(False)
self.lblDicaUser.set_markup("(não pode ser alterado)")
#Executa query
f.query.execute('SELECT user, nome, senha FROM usuarios WHERE id =' + str(self.MyId))
#Preenche os controles
for row in f.query:
self.edtUsuario.set_text(row[0])
self.edtNome.set_text(row[1])
self.edtSenha.set_text(row[2])
self.edtConfirmar.set_text(row[2])
E na instrução mais abaixo vamos como dar INSERT e UPDATE (o mesmo serve pro DELETE, conforme vermos no arquivo seguinte). A diferença é que estas instruções precisam de um commit no final, pois alteram registros no banco.
if self.myNovo == True:
sAcao = 'cadastrado'
f.query.execute("INSERT INTO usuarios (user, nome, senha)\
VALUES('" + self.edtUsuario.get_text() + "',\
'" + self.edtNome.get_text() + "',\
'" + self.edtSenha.get_text() + "')")
else:
sAcao = 'alterado'
f.query.execute("UPDATE usuarios\
SET nome = '" + self.edtNome.get_text() + "',\
senha = '" + self.edtSenha.get_text() + "'\
WHERE id = " + str(self.MyId))
f.cnx.commit()