503 lines
18 KiB
Python
503 lines
18 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
|
||
|
# Per la generazione dei reports:
|
||
|
# - https://www.reportlab.com/
|
||
|
# - https://pythonhosted.org/PollyReports/tutorial.html
|
||
|
# - https://pbpython.com/pdf-reports.html
|
||
|
|
||
|
# Smart Card
|
||
|
# - https://pyscard.sourceforge.io/
|
||
|
# - https://www.mmxforge.net/index.php/sviluppo/python/item/9-lettura-dei-dati-della-tessera-sanitaria-con-python
|
||
|
|
||
|
|
||
|
import tkinter as tk
|
||
|
import tkinter.ttk as ttk
|
||
|
import tkinter.messagebox as tkMessagebox
|
||
|
|
||
|
from locale import (setlocale, LC_ALL)
|
||
|
|
||
|
from PIL import Image
|
||
|
from PIL import ImageDraw
|
||
|
from PIL import ImageTk
|
||
|
|
||
|
from db import Db
|
||
|
from datepicker import Datepicker
|
||
|
from const import MESSAGE_BOX_TITLE
|
||
|
from iscritto import Iscritto
|
||
|
|
||
|
FRM_PADX = 5
|
||
|
FRM_PADY = 3
|
||
|
|
||
|
FRA_PADX = 5
|
||
|
FRA_PADY = 3
|
||
|
|
||
|
LBL_PADX = 3
|
||
|
LBL_PADY = 3
|
||
|
|
||
|
TXT_PADX = 5
|
||
|
TXT_PADY = 3
|
||
|
|
||
|
IMG_PADX = 5
|
||
|
IMG_PADY = 3
|
||
|
|
||
|
BTN_PADX = 5
|
||
|
BTN_PADY = 3
|
||
|
|
||
|
setlocale(LC_ALL, '')
|
||
|
|
||
|
class Iscritti():
|
||
|
|
||
|
def __init__(self, parent):
|
||
|
self.parent = parent
|
||
|
self.larghezza_firma = 800
|
||
|
self.altezza_firma = 300
|
||
|
self.img_firma_color_fg = "black"
|
||
|
self.img_firma_color_bg = "white"
|
||
|
self.img_firma_penwidth = 5
|
||
|
self.iscritto = Iscritto(self.larghezza_firma,
|
||
|
self.altezza_firma,
|
||
|
self.img_firma_color_fg,
|
||
|
self.img_firma_color_bg)
|
||
|
self.create_widgets()
|
||
|
parent.update()
|
||
|
return
|
||
|
|
||
|
def create_widgets(self):
|
||
|
self.configure_master()
|
||
|
|
||
|
self.crea_master_widgets()
|
||
|
return
|
||
|
|
||
|
def configure_master(self):
|
||
|
# Crea la finestra a tutto schermo
|
||
|
# (non funziona su Mint 19.1)
|
||
|
# self.parent.wm_state('zoomed')
|
||
|
self.parent.focus_set()
|
||
|
self.parent.title("GOLEM - Iscritti")
|
||
|
self.parent.rowconfigure(0, weight=1)
|
||
|
self.parent.columnconfigure(0, weight=1)
|
||
|
self.parent.protocol("WM_DELETE_WINDOW", self.esci)
|
||
|
return
|
||
|
|
||
|
def crea_master_widgets(self):
|
||
|
self.fra_master = ttk.Frame(self.parent)
|
||
|
|
||
|
row_number = 0
|
||
|
|
||
|
s1 = ttk.Separator(self.fra_master, orient=tk.HORIZONTAL)
|
||
|
s1.grid(row=row_number, column=0, sticky=tk.W + tk.E)
|
||
|
row_number += 1
|
||
|
|
||
|
self.crea_frame_pulsanti(self.fra_master, row_number)
|
||
|
self.fra_master.rowconfigure(row_number, weight=0)
|
||
|
row_number += 1
|
||
|
|
||
|
s2 = ttk.Separator(self.fra_master, orient=tk.HORIZONTAL)
|
||
|
s2.grid(row=row_number, column=0, sticky=tk.W + tk.E)
|
||
|
row_number += 1
|
||
|
|
||
|
self.crea_frame_dati(self.fra_master, row_number)
|
||
|
self.fra_master.rowconfigure(row_number, weight=1)
|
||
|
row_number += 1
|
||
|
|
||
|
self.fra_master.columnconfigure(0, weight=1)
|
||
|
|
||
|
self.fra_master.grid(row=0,
|
||
|
column=0,
|
||
|
padx=FRA_PADX,
|
||
|
pady=FRA_PADX,
|
||
|
sticky=tk.N + tk.W + tk.S + tk.E)
|
||
|
return
|
||
|
|
||
|
def crea_frame_pulsanti(self, parent, row_number):
|
||
|
self.fra_pulsanti = ttk.Frame(parent)
|
||
|
self.fra_pulsanti.grid(row=row_number,
|
||
|
column=0,
|
||
|
padx=FRA_PADX,
|
||
|
pady=FRA_PADX,
|
||
|
sticky=tk.N + tk.W + tk.S + tk.E)
|
||
|
|
||
|
child_row = 0
|
||
|
|
||
|
self.crea_widgets_pulsanti(self.fra_pulsanti, child_row)
|
||
|
self.fra_pulsanti.rowconfigure(0, weight=1)
|
||
|
child_row += 1
|
||
|
|
||
|
return
|
||
|
|
||
|
def crea_widgets_pulsanti(self, parent, row_number):
|
||
|
child_column = 0
|
||
|
self.btn_nuovo = ttk.Button(parent, text="Nuovo", command=self.nuovo)
|
||
|
self.btn_nuovo.grid(row=row_number,
|
||
|
column=child_column,
|
||
|
padx=BTN_PADX,
|
||
|
pady=BTN_PADX,
|
||
|
sticky=tk.N + tk.W + tk.S + tk.E)
|
||
|
parent.columnconfigure(child_column, weight=1)
|
||
|
|
||
|
# Funzionalita' ricerca da implementare (datagrid in tkinter???)
|
||
|
# child_column += 1
|
||
|
# self.btn_cerca = ttk.Button(parent, text="Cerca", command=self.cerca)
|
||
|
# self.btn_cerca.grid(row=row_number,
|
||
|
# column=child_column,
|
||
|
# padx=BTN_PADX,
|
||
|
# pady=BTN_PADX,
|
||
|
# sticky=tk.N + tk.W + tk.S + tk.E)
|
||
|
# parent.columnconfigure(child_column, weight=1)
|
||
|
|
||
|
child_column += 1
|
||
|
self.btn_salva = ttk.Button(parent, text="Salva", command=self.salva)
|
||
|
self.btn_salva.grid(row=row_number,
|
||
|
column=child_column,
|
||
|
padx=BTN_PADX,
|
||
|
pady=BTN_PADX,
|
||
|
sticky=tk.N + tk.W + tk.S + tk.E)
|
||
|
parent.columnconfigure(child_column, weight=1)
|
||
|
|
||
|
child_column += 1
|
||
|
self.btn_esci = ttk.Button(parent, text="Esci", command=self.esci)
|
||
|
self.btn_esci.grid(row=row_number,
|
||
|
column=child_column,
|
||
|
padx=BTN_PADX,
|
||
|
pady=BTN_PADX,
|
||
|
sticky=tk.N + tk.W + tk.S + tk.E)
|
||
|
parent.columnconfigure(child_column, weight=1)
|
||
|
return
|
||
|
|
||
|
def crea_frame_dati(self, parent, row_number):
|
||
|
self.fra_dati = ttk.Frame(parent)
|
||
|
self.fra_dati.grid(row=row_number,
|
||
|
column=0,
|
||
|
padx=FRA_PADX,
|
||
|
pady=FRA_PADX,
|
||
|
sticky=tk.N + tk.W + tk.S + tk.E)
|
||
|
|
||
|
child_row = 0
|
||
|
|
||
|
self.crea_widgets_id(self.fra_dati, child_row)
|
||
|
self.fra_dati.rowconfigure(child_row, weight=1)
|
||
|
child_row += 1
|
||
|
|
||
|
self.crea_widgets_cognome(self.fra_dati, child_row)
|
||
|
self.fra_dati.rowconfigure(child_row, weight=1)
|
||
|
child_row += 1
|
||
|
|
||
|
self.crea_widgets_nome(self.fra_dati, child_row)
|
||
|
self.fra_dati.rowconfigure(child_row, weight=1)
|
||
|
child_row += 1
|
||
|
|
||
|
self.crea_widgets_data_nascita(self.fra_dati, child_row)
|
||
|
self.fra_dati.rowconfigure(child_row, weight=1)
|
||
|
child_row += 1
|
||
|
|
||
|
self.crea_widgets_comune_nascita(self.fra_dati, child_row)
|
||
|
self.fra_dati.rowconfigure(child_row, weight=1)
|
||
|
child_row += 1
|
||
|
|
||
|
self.crea_widgets_email(self.fra_dati, child_row)
|
||
|
self.fra_dati.rowconfigure(child_row, weight=1)
|
||
|
child_row += 1
|
||
|
|
||
|
self.crea_widgets_occupazione(self.fra_dati, child_row)
|
||
|
self.fra_dati.rowconfigure(child_row, weight=1)
|
||
|
child_row += 1
|
||
|
|
||
|
self.crea_widgets_fonte(self.fra_dati, child_row)
|
||
|
self.fra_dati.rowconfigure(child_row, weight=1)
|
||
|
child_row += 1
|
||
|
|
||
|
self.crea_widgets_data_firma(self.fra_dati, child_row)
|
||
|
self.fra_dati.rowconfigure(child_row, weight=1)
|
||
|
child_row += 1
|
||
|
|
||
|
self.crea_widgets_firma(self.fra_dati, child_row)
|
||
|
self.fra_dati.rowconfigure(child_row, weight=1)
|
||
|
child_row += 1
|
||
|
|
||
|
self.fra_dati.columnconfigure(0, weight=0)
|
||
|
self.fra_dati.columnconfigure(1, weight=1)
|
||
|
self.fra_dati.columnconfigure(2, weight=1)
|
||
|
|
||
|
return
|
||
|
|
||
|
def crea_widgets_id(self, parent, row_number):
|
||
|
|
||
|
self.lbl_id = ttk.Label(parent, text="Id", anchor=tk.W)
|
||
|
self.lbl_id.grid(row=row_number,
|
||
|
column=0,
|
||
|
padx=LBL_PADX,
|
||
|
pady=LBL_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
|
||
|
self.txt_id = ttk.Entry(parent,
|
||
|
textvariable=self.iscritto.id,
|
||
|
state="readonly")
|
||
|
self.txt_id.grid(row=row_number,
|
||
|
column=1,
|
||
|
columnspan=2,
|
||
|
padx=TXT_PADX,
|
||
|
pady=TXT_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
return
|
||
|
|
||
|
def crea_widgets_cognome(self, parent, row_number):
|
||
|
|
||
|
self.lbl_cognome = ttk.Label(parent, text="Cognome", anchor=tk.W)
|
||
|
self.lbl_cognome.grid(row=row_number,
|
||
|
column=0,
|
||
|
padx=LBL_PADX,
|
||
|
pady=LBL_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
|
||
|
self.txt_cognome = ttk.Entry(parent, textvariable=self.iscritto.cognome)
|
||
|
self.txt_cognome.grid(row=row_number,
|
||
|
column=1,
|
||
|
columnspan=2,
|
||
|
padx=TXT_PADX,
|
||
|
pady=TXT_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
return
|
||
|
|
||
|
def crea_widgets_nome(self, parent, row_number):
|
||
|
|
||
|
self.lbl_nome = ttk.Label(parent, text="Nome", anchor=tk.W)
|
||
|
self.lbl_nome.grid(row=row_number,
|
||
|
column=0,
|
||
|
padx=LBL_PADX,
|
||
|
pady=LBL_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
|
||
|
self.txt_nome = ttk.Entry(parent, textvariable=self.iscritto.nome)
|
||
|
self.txt_nome.grid(row=row_number,
|
||
|
column=1,
|
||
|
columnspan=2,
|
||
|
padx=TXT_PADX,
|
||
|
pady=TXT_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
return
|
||
|
|
||
|
def crea_widgets_data_nascita(self, parent, row_number):
|
||
|
|
||
|
self.lbl_data_nascita = ttk.Label(parent,
|
||
|
text="Data di nascita",
|
||
|
anchor=tk.W)
|
||
|
self.lbl_data_nascita.grid(row=row_number,
|
||
|
column=0,
|
||
|
padx=LBL_PADX,
|
||
|
pady=LBL_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
|
||
|
self.txt_data_nascita = Datepicker(parent,
|
||
|
dateformat="%x",
|
||
|
datevar=self.iscritto.data_nascita)
|
||
|
self.txt_data_nascita.grid(row=row_number,
|
||
|
column=1,
|
||
|
columnspan=2,
|
||
|
padx=TXT_PADX,
|
||
|
pady=TXT_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
return
|
||
|
|
||
|
def crea_widgets_comune_nascita(self, parent, row_number):
|
||
|
|
||
|
self.lbl_comune_nascita = ttk.Label(parent,
|
||
|
text="Comune di nascita",
|
||
|
anchor=tk.W)
|
||
|
self.lbl_comune_nascita.grid(row=row_number,
|
||
|
column=0,
|
||
|
padx=LBL_PADX,
|
||
|
pady=LBL_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
|
||
|
self.txt_comune_nascita = ttk.Entry(
|
||
|
parent, textvariable=self.iscritto.comune_nascita)
|
||
|
self.txt_comune_nascita.grid(row=row_number,
|
||
|
column=1,
|
||
|
columnspan=2,
|
||
|
padx=TXT_PADX,
|
||
|
pady=TXT_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
return
|
||
|
|
||
|
def crea_widgets_email(self, parent, row_number):
|
||
|
|
||
|
self.lbl_email = ttk.Label(parent, text="E-mail", anchor=tk.W)
|
||
|
self.lbl_email.grid(row=row_number,
|
||
|
column=0,
|
||
|
padx=LBL_PADX,
|
||
|
pady=LBL_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
|
||
|
self.txt_email = ttk.Entry(parent, textvariable=self.iscritto.email)
|
||
|
self.txt_email.grid(row=row_number,
|
||
|
column=1,
|
||
|
columnspan=2,
|
||
|
padx=TXT_PADX,
|
||
|
pady=TXT_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
return
|
||
|
|
||
|
def crea_widgets_occupazione(self, parent, row_number):
|
||
|
|
||
|
self.lbl_occupazione = ttk.Label(parent,
|
||
|
text="Occupazione",
|
||
|
anchor=tk.W)
|
||
|
self.lbl_occupazione.grid(row=row_number,
|
||
|
column=0,
|
||
|
padx=LBL_PADX,
|
||
|
pady=LBL_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
|
||
|
self.txt_occupazione = ttk.Entry(parent,
|
||
|
textvariable=self.iscritto.occupazione)
|
||
|
self.txt_occupazione.grid(row=row_number,
|
||
|
column=1,
|
||
|
columnspan=2,
|
||
|
padx=TXT_PADX,
|
||
|
pady=TXT_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
return
|
||
|
|
||
|
def crea_widgets_fonte(self, parent, row_number):
|
||
|
|
||
|
self.lbl_fonte = ttk.Label(parent, text="Fonte", anchor=tk.W)
|
||
|
self.lbl_fonte.grid(row=row_number,
|
||
|
column=0,
|
||
|
padx=LBL_PADX,
|
||
|
pady=LBL_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
|
||
|
self.txt_fonte = ttk.Entry(parent, textvariable=self.iscritto.fonte)
|
||
|
self.txt_fonte.grid(row=row_number,
|
||
|
column=1,
|
||
|
columnspan=2,
|
||
|
padx=TXT_PADX,
|
||
|
pady=TXT_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
return
|
||
|
|
||
|
def crea_widgets_data_firma(self, parent, row_number):
|
||
|
|
||
|
self.lbl_data_firma = ttk.Label(parent, text="Data firma", anchor=tk.W)
|
||
|
self.lbl_data_firma.grid(row=row_number,
|
||
|
column=0,
|
||
|
padx=LBL_PADX,
|
||
|
pady=LBL_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
|
||
|
self.txt_data_firma = Datepicker(parent,
|
||
|
dateformat="%x",
|
||
|
datevar=self.iscritto.data_firma)
|
||
|
self.txt_data_firma.grid(row=row_number,
|
||
|
column=1,
|
||
|
columnspan=2,
|
||
|
padx=TXT_PADX,
|
||
|
pady=TXT_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
return
|
||
|
|
||
|
def crea_widgets_firma(self, parent, row_number):
|
||
|
# https://www.youtube.com/watch?v=rhvJ_M218EQ
|
||
|
self.img_firma_old_x = None
|
||
|
self.img_firma_old_y = None
|
||
|
|
||
|
self.lbl_firma = ttk.Label(parent, text="Firma", anchor=tk.N + tk.W)
|
||
|
self.lbl_firma.grid(row=row_number,
|
||
|
column=0,
|
||
|
padx=LBL_PADX,
|
||
|
pady=LBL_PADY,
|
||
|
sticky=tk.N + tk.S + tk.E + tk.W)
|
||
|
larghezza = self.larghezza_firma
|
||
|
altezza = self.altezza_firma
|
||
|
self.cv_firma = tk.Canvas(
|
||
|
parent,
|
||
|
width=larghezza,
|
||
|
height=altezza,
|
||
|
border=1,
|
||
|
background=self.img_firma_color_bg,
|
||
|
relief=tk.SUNKEN)
|
||
|
self.cv_firma.bind("<B1-Motion>", self.img_firma_paint)
|
||
|
self.cv_firma.bind("<ButtonRelease-1>", self.img_firma_reset)
|
||
|
self.cv_firma.grid(row=row_number,
|
||
|
column=1,
|
||
|
padx=IMG_PADX,
|
||
|
pady=IMG_PADY,
|
||
|
sticky=tk.N + tk.W)
|
||
|
self.draw_frirma = ImageDraw.Draw(self.iscritto.img_firma)
|
||
|
|
||
|
self.fra_pulsanti_firma = ttk.Frame(parent)
|
||
|
self.fra_pulsanti_firma.columnconfigure(0, weight=1)
|
||
|
self.fra_pulsanti_firma.grid(row=row_number,
|
||
|
column=2,
|
||
|
padx=FRA_PADX,
|
||
|
pady=FRA_PADX,
|
||
|
sticky=tk.N + tk.W + tk.S + tk.E)
|
||
|
|
||
|
self.btn_firma_clear = ttk.Button(self.fra_pulsanti_firma,
|
||
|
text="Pulisci")
|
||
|
self.btn_firma_clear.bind("<Button-1>", self.img_firma_clear)
|
||
|
self.btn_firma_clear.grid(row=0,
|
||
|
column=0,
|
||
|
padx=BTN_PADX,
|
||
|
pady=BTN_PADX,
|
||
|
sticky=tk.N + tk.W + tk.S + tk.E)
|
||
|
return
|
||
|
|
||
|
def img_firma_paint(self, e):
|
||
|
if self.img_firma_old_x and self.img_firma_old_y:
|
||
|
self.cv_firma.create_line(self.img_firma_old_x,
|
||
|
self.img_firma_old_y,
|
||
|
e.x,
|
||
|
e.y,
|
||
|
width=self.img_firma_penwidth,
|
||
|
fill=self.img_firma_color_fg,
|
||
|
capstyle=tk.ROUND,
|
||
|
smooth=True)
|
||
|
xy = [self.img_firma_old_x, self.img_firma_old_y, e.x, e.y]
|
||
|
self.draw_frirma.line(xy,
|
||
|
width=self.img_firma_penwidth,
|
||
|
fill=self.img_firma_color_fg)
|
||
|
self.img_firma_old_x = e.x
|
||
|
self.img_firma_old_y = e.y
|
||
|
return
|
||
|
|
||
|
def img_firma_reset(self, e):
|
||
|
self.img_firma_old_x = None
|
||
|
self.img_firma_old_y = None
|
||
|
return
|
||
|
|
||
|
def img_firma_clear(self, e):
|
||
|
self.cv_firma.delete("all")
|
||
|
return
|
||
|
|
||
|
def nuovo(self):
|
||
|
self.iscritto.new()
|
||
|
# # Alla canvas non e' associata nessuna tkinger.Variable()
|
||
|
# # quindi lavoro direttamente sul widget
|
||
|
self.cv_firma.delete("all")
|
||
|
self.draw_frirma = ImageDraw.Draw(self.iscritto.img_firma)
|
||
|
return
|
||
|
|
||
|
def cerca(self):
|
||
|
tkMessagebox.showinfo(MESSAGE_BOX_TITLE, "valido, salvo!")
|
||
|
pass
|
||
|
|
||
|
def salva(self):
|
||
|
if self.iscritto.is_valid():
|
||
|
salva = tkMessagebox.askyesno(MESSAGE_BOX_TITLE,
|
||
|
"Convermi salvataggio?")
|
||
|
if salva:
|
||
|
db = Db()
|
||
|
db.insert_new(self.iscritto)
|
||
|
self.nuovo()
|
||
|
else:
|
||
|
tkMessagebox.showinfo(MESSAGE_BOX_TITLE,
|
||
|
"non valido e quindi non posso salvare!")
|
||
|
self.parent.update()
|
||
|
|
||
|
def esci(self):
|
||
|
if tkMessagebox.askyesno(MESSAGE_BOX_TITLE, "Esco?"):
|
||
|
self.parent.update()
|
||
|
self.parent.destroy()
|
||
|
return
|