2013-02-15 19:28:32 +01:00
import tkinter , tkinter . filedialog , tkinter . messagebox , tkinter . simpledialog
2013-03-23 18:58:37 +01:00
import tempfile , json , datetime , re , sys
2013-02-15 19:28:32 +01:00
class Text ( tkinter . Text ) :
def __init__ ( self , * args , * * kwargs ) :
tkinter . Text . __init__ ( self , * args , * * kwargs )
def evidenzia ( self , pattern , tag , inizio = " 1.0 " , fine = " end " , regex = True ) :
inizio = self . index ( inizio )
fine = self . index ( fine )
self . mark_set ( " matchStart " , inizio )
self . mark_set ( " matchEnd " , inizio )
self . mark_set ( " searchLimit " , fine )
occorrenze = tkinter . IntVar ( )
while True :
2013-03-23 14:13:09 +01:00
indice = self . search ( pattern , " matchEnd " , " searchLimit " , count = occorrenze , regexp = regex )
2013-02-15 19:28:32 +01:00
if indice == " " :
break
self . mark_set ( " matchStart " , indice )
self . mark_set ( " matchEnd " , " %s + %s c " % ( indice , occorrenze . get ( ) ) )
self . tag_add ( tag , " matchStart " , " matchEnd " )
class applicazione ( tkinter . Frame ) :
def __init__ ( self , finestra ) :
tkinter . Frame . __init__ ( self , finestra )
2013-03-23 14:13:09 +01:00
2013-02-15 19:28:32 +01:00
#Variabili
2013-03-23 18:58:37 +01:00
self . temp = tempfile . TemporaryFile ( mode = " w+t " )
2013-02-15 19:28:32 +01:00
self . testo = tkinter . StringVar ( )
2013-03-22 16:33:41 +01:00
self . file = " "
2013-02-15 19:28:32 +01:00
self . opzionifile = {
" parent " : finestra ,
" filetypes " : [ ( " text files " , " .txt " ) ] ,
" defaultextension " : " .txt " ,
" initialfile " : " file.txt "
}
self . opzionichat = {
" font " : ( " Monaco " , 13 ) ,
" borderwidth " : 2 ,
" highlightthickness " : 0
}
2013-03-23 18:58:37 +01:00
#Gestione delle preferenze
2013-02-15 19:28:32 +01:00
try :
self . preferenze = json . load ( open ( " preferenze.json " ) )
except FileNotFoundError :
2013-03-23 14:13:09 +01:00
tkinter . messagebox . showwarning ( " Dropchat " , " File delle preferenze non trovato! " , detail = " Preferenze di default ricostruite. " )
2013-02-15 19:28:32 +01:00
self . creapreferenze ( )
2013-03-22 16:33:41 +01:00
2013-02-15 19:28:32 +01:00
#Gestione della finestra
finestra . geometry ( self . preferenze [ " Geometria " ] )
finestra . configure ( background = " #a8a8a8 " )
finestra . columnconfigure ( 1 , weight = 1 )
finestra . rowconfigure ( 0 , weight = 1 )
finestra . protocol ( ' WM_DELETE_WINDOW ' , self . chiudi )
self . grid ( )
2013-03-23 14:13:09 +01:00
2013-03-23 18:58:37 +01:00
#Inizzializzazione
2013-02-15 19:28:32 +01:00
self . cambiatitolo ( )
self . widgets ( )
self . leggi ( )
2013-03-23 18:58:37 +01:00
#Gestione delle ultime conversazioni
try :
self . cancellanontrovati ( )
self . file = self . preferenze [ " Chat " ] [ - 1 ]
except IndexError :
if tkinter . messagebox . askquestion ( " Dropchat " , " Nessuna conversazione trovata. " , detail = " Crearne una nuova ? " ) == " yes " :
self . nuovofile ( )
#Loop principale
2013-02-15 19:28:32 +01:00
self . loop ( )
#Widget della finestra
def widgets ( self ) :
self . menubar = tkinter . Menu ( finestra )
2013-03-23 14:13:09 +01:00
self . chat = Text ( finestra , width = 100 , height = 30 , relief = " sunken " , insertbackground = " #fff " , * * self . opzionichat )
self . sidebar = tkinter . Listbox ( finestra , width = 20 , borderwidth = 0 , background = " #dce0e8 " )
self . casella = tkinter . Entry ( finestra , textvariable = self . testo , * * self . opzionichat )
self . chat . grid ( column = 1 , row = 0 , sticky = " nswe " , pady = ( 6 , 3 ) , padx = 6 )
self . casella . grid ( column = 1 , row = 1 , sticky = " nswe " , pady = ( 3 , 6 ) , padx = 6 )
self . sidebar . grid ( column = 0 , row = 0 , sticky = " nswe " , rowspan = 2 )
2013-02-15 19:28:32 +01:00
#Bindings
self . chat . bind ( " <KeyPress> " , " break " )
self . sidebar . bind ( " <Double-Button-1> " , self . cambiafile )
self . sidebar . bind ( " <Button-2> " , self . mostramenu )
self . casella . bind ( " <Return> " , self . scrivi )
#Barra dei menu
self . menubar = tkinter . Menu ( self )
menu = tkinter . Menu ( self . menubar )
#Primo menu
2013-03-23 14:13:09 +01:00
self . menubar . add_cascade ( label = " Conversazione " , menu = menu )
menu . add_command ( label = " Nuovo file " , command = self . nuovofile )
menu . add_command ( label = " Apri file... " , command = self . aprifile )
2013-02-15 19:28:32 +01:00
#Secondo menu
menu = tkinter . Menu ( self . menubar )
2013-03-23 14:13:09 +01:00
self . menubar . add_cascade ( label = " Profilo " , menu = menu )
menu . add_command ( label = " Nome utente " , command = lambda : self . modificapreferenza ( " Utente " , tkinter . simpledialog . askstring ( " Nome Utente " , " Scrivi il nome: " , initialvalue = self . preferenze [ " Utente " ] , parent = finestra ) ) )
menu . add_command ( label = " Chiave " , command = lambda : self . modificapreferenza ( " Chiave " , tkinter . filedialog . askopenfilename ( title = " Scegli un file... " , message = " Apri una chiave di decodifica. " , * * self . opzionifile ) ) )
2013-02-15 19:28:32 +01:00
#Terzo menu
menu = tkinter . Menu ( self . menubar )
self . menubar . add_cascade ( label = " Modifica " , menu = menu )
2013-03-23 14:13:09 +01:00
menu . add_command ( label = " Taglia " , command = lambda : finestra . focus_get ( ) . event_generate ( " <<Cut>> " ) )
menu . add_command ( label = " Copia " , command = lambda : finestra . focus_get ( ) . event_generate ( " <<Copy>> " ) )
menu . add_command ( label = " Incolla " , command = lambda : finestra . focus_get ( ) . event_generate ( " <<Paste>> " ) )
2013-02-15 19:28:32 +01:00
finestra . config ( menu = self . menubar )
#Menu contestuale 1
self . menu1 = tkinter . Menu ( self )
2013-03-23 14:13:09 +01:00
self . menu1 . add_command ( label = " Apri " , command = self . cambiafile )
self . menu1 . add_command ( label = " Cancella " , command = self . cancellafile )
2013-02-15 19:28:32 +01:00
self . menu1 . add_separator ( )
2013-03-23 14:13:09 +01:00
self . menu1 . add_command ( label = " Nuovo file " , command = self . nuovofile )
self . menu1 . add_command ( label = " Ricarica " , command = lambda : self . sidebar . delete ( 0 , " end " ) )
2013-02-15 19:28:32 +01:00
#Menu contestuale 2
self . menu2 = tkinter . Menu ( self )
2013-03-23 14:13:09 +01:00
self . menu2 . add_command ( label = " Nuovo file " , command = self . nuovofile )
self . menu2 . add_command ( label = " Ricarica " , command = lambda : self . sidebar . delete ( 0 , " end " ) )
2013-02-15 19:28:32 +01:00
#Legge il file dal buffer e lo scrive nella chat
def leggi ( self ) :
self . aggiorna ( )
self . temp . seek ( 0 )
self . chat . delete ( 0.0 , " end " )
self . chat . insert ( " end " , self . temp . read ( ) )
self . colora ( )
#Scrive un messaggio nel file
def scrivi ( self , event ) :
if self . file != " " :
with open ( self . file , " a " ) as file :
if self . testo . get ( ) != " " :
2013-03-23 14:46:07 +01:00
riga = " [ %s ] %s : %s \n " % ( datetime . datetime . now ( ) . strftime ( " %d - % m- % y % H: % M " ) , self . preferenze [ " Utente " ] , self . testo . get ( ) )
2013-02-15 19:28:32 +01:00
self . testo . set ( " " )
file . write ( riga )
#copia il file nel buffer
def aggiorna ( self ) :
2013-03-23 18:58:37 +01:00
self . temp . close ( )
self . temp = tempfile . TemporaryFile ( mode = " w+t " )
2013-02-15 19:28:32 +01:00
if self . file != " " :
with open ( self . file ) as testo :
self . temp . write ( testo . read ( ) )
def cambiatitolo ( self ) :
file = re . search ( " ([^/]*)$ " , self . file )
if self . file == " " :
finestra . title ( " Dropchat " )
else :
finestra . title ( " Dropchat - " + file . group ( 0 ) )
#Colora il testo della chat
def colora ( self ) :
2013-03-23 14:13:09 +01:00
self . chat . tag_configure ( " data " , foreground = " #005d8f " )
self . chat . tag_configure ( " nome " , foreground = " #648f00 " )
self . chat . tag_configure ( " altronome " , foreground = " #de7a31 " )
2013-02-15 19:28:32 +01:00
self . chat . evidenzia ( " \ [ \ d+- \ d+- \ d+ \ d+: \ d+ \ ] " , " data " )
for nome in re . findall ( " ([a-zA-Z]+): " , self . chat . get ( 0.0 , " end " ) ) :
if nome == self . preferenze [ " Utente " ] :
self . chat . evidenzia ( nome , " nome " )
else :
self . chat . evidenzia ( nome , " altronome " )
#Gestisce i menu contestuali
def mostramenu ( self , event ) :
self . sidebar . indice = self . sidebar . nearest ( event . y )
if self . sidebar . indice < 0 :
self . menu2 . post ( event . x_root , event . y_root )
return
self . sidebar . activate ( self . sidebar . indice )
_ , offset , _ , altezza = self . sidebar . bbox ( self . sidebar . indice )
if event . y > altezza + offset + self . sidebar . size ( ) :
self . menu2 . post ( event . x_root , event . y_root )
else :
self . menu1 . post ( event . x_root , event . y_root )
#Scrive i file aperti nella sidebar
def filerecenti ( self ) :
for x , file in enumerate ( self . preferenze [ " Chat " ] ) :
file = " - " + re . search ( " ([^/]*)$ " , file ) . group ( 0 )
if file not in self . sidebar . get ( x ) :
self . sidebar . insert ( x , file )
#Cancella il file selezionato nella sidebar
def cancellafile ( self ) :
if self . preferenze [ " Chat " ] [ self . sidebar . indice ] == self . file :
self . file = " "
del self . preferenze [ " Chat " ] [ self . sidebar . indice ]
json . dump ( self . preferenze , open ( " preferenze.json " , " w " ) )
self . leggi ( )
self . cambiatitolo ( )
#Apre il file selezionato nella sidebar
def cambiafile ( self , _ = None ) :
file = self . preferenze [ " Chat " ] [ int ( self . sidebar . curselection ( ) [ 0 ] ) ]
if self . file != file :
self . file = file
self . leggi ( )
self . cambiatitolo ( )
#Apre un file
def aprifile ( self ) :
2013-03-23 18:58:37 +01:00
if sys . platform == " darwin " :
2013-03-23 14:13:09 +01:00
file = tkinter . filedialog . askopenfilename ( title = " Scegli un file... " , message = " Apri una conversazione esistente. " , * * self . opzionifile )
2013-02-17 04:27:32 +01:00
else :
2013-03-23 14:13:09 +01:00
file = tkinter . filedialog . askopenfilename ( title = " Scegli un file... " , * * self . opzionifile )
2013-02-15 19:28:32 +01:00
if file not in self . preferenze [ " Chat " ] and file != " " :
self . preferenze [ " Chat " ] + = file ,
json . dump ( self . preferenze , open ( " preferenze.json " , " w " ) )
self . file = file
self . leggi ( )
self . cambiatitolo ( )
#Crea un nuovo file e lo apre
def nuovofile ( self ) :
2013-03-23 18:58:37 +01:00
if sys . platform == " darwin " :
2013-03-23 14:13:09 +01:00
file = tkinter . filedialog . asksaveasfilename ( title = " Crea un file... " , message = " Scegli il nome della nuova conversazione. " , * * self . opzionifile )
2013-02-17 04:27:32 +01:00
else :
2013-03-23 14:13:09 +01:00
file = tkinter . filedialog . asksaveasfilename ( title = " Crea un file... " , * * self . opzionifile )
2013-02-15 19:28:32 +01:00
if file != " " :
self . file = file
2013-03-23 18:58:37 +01:00
open ( self . file , " w " ) . close ( )
2013-03-22 16:33:41 +01:00
if self . file not in self . preferenze [ " Chat " ] :
self . preferenze [ " Chat " ] + = self . file ,
json . dump ( self . preferenze , open ( " preferenze.json " , " w " ) )
self . leggi ( )
self . cambiatitolo ( )
2013-02-15 19:28:32 +01:00
#Cancella i file non trovati dalle preferenze
def cancellanontrovati ( self ) :
for x , file in enumerate ( self . preferenze [ " Chat " ] ) :
try :
open ( file )
self . file = file
except FileNotFoundError :
del self . preferenze [ " Chat " ] [ x ]
continue
json . dump ( self . preferenze , open ( " preferenze.json " , " w " ) )
#Ricrea le preferenze se vengono cancellate
def creapreferenze ( self ) :
default = {
" Utente " : " Nomeutente " ,
" Chat " : [ " chat.txt " ] ,
" Chiave " : " chiave.key " ,
" Geometria " : " 800x500+500+250 "
}
json . dump ( default , open ( " preferenze.json " , " w " ) )
self . preferenze = json . load ( open ( " preferenze.json " ) )
#Cambia una preferenze e la salva
def modificapreferenza ( self , chiave , preferenza ) :
if preferenza != " " :
self . preferenze [ chiave ] = preferenza
json . dump ( self . preferenze , open ( " preferenze.json " , " w " ) )
#Salva la geometria della finestra e la chiude
def chiudi ( self ) :
self . modificapreferenza ( " Geometria " , finestra . geometry ( ) )
self . temp . close ( )
finestra . destroy ( )
#Loop principale
def loop ( self ) :
self . filerecenti ( )
self . leggi ( )
self . after ( 200 , self . loop )
finestra = tkinter . Tk ( )
app = applicazione ( finestra )
2013-03-23 18:58:37 +01:00
app . mainloop ( )