2019-08-12 17:29:22 +02:00
"""
2019-07-09 16:13:16 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* CNIRevelator *
* *
* Desc : Application launcher graphical interface *
* *
* Copyright © 2018 - 2019 Adrien Bourmault ( neox95 ) *
* *
* This file is part of CNIRevelator . *
* *
* CNIRevelator is free software : you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation , either version 3 of the License , or *
* any later version . *
* *
* CNIRevelator is distributed in the hope that it will be useful , *
* but WITHOUT ANY WARRANTY * without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the *
* GNU General Public License for more details . *
* *
* You should have received a copy of the GNU General Public License *
* along with CNIRevelator . If not , see < https : * www . gnu . org / licenses / > . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
"""
from tkinter import *
2019-08-12 17:07:37 +02:00
import webbrowser
2019-07-09 16:13:16 +02:00
from tkinter . messagebox import *
from tkinter import filedialog
from tkinter import ttk
2019-08-07 15:30:22 +02:00
import cv2
import PIL . Image , PIL . ImageTk
2019-08-12 17:07:37 +02:00
import traceback
2019-07-09 16:13:16 +02:00
import logger # logger.py
import globs # globs.py
2019-08-12 17:07:37 +02:00
import lang # lang.py
2019-07-09 16:13:16 +02:00
2019-07-19 17:17:30 +02:00
2019-08-05 15:52:02 +02:00
controlKeys = [ " Escape " , " Right " , " Left " , " Up " , " Down " , " Home " , " End " , " BackSpace " , " Delete " , " Inser " , " Shift_L " , " Shift_R " , " Control_R " , " Control_L " ]
2019-07-19 17:17:30 +02:00
class DocumentAsk ( Toplevel ) :
def __init__ ( self , parent , choices ) :
self . choice = 0
vals = [ 0 , 1 ]
super ( ) . __init__ ( parent )
2019-08-12 17:07:37 +02:00
self . title ( " {} : " . format ( lang . all [ globs . CNIRlang ] [ " Choose the identity document " ] ) )
2019-07-19 17:17:30 +02:00
ttk . Radiobutton ( self , text = choices [ 0 ] , command = self . register0 , value = vals [ 0 ] ) . pack ( )
ttk . Radiobutton ( self , text = choices [ 1 ] , command = self . register1 , value = vals [ 1 ] ) . pack ( )
self . button = Button ( self , text = ' OK ' , command = ( self . ok ) ) . pack ( )
self . resizable ( width = False , height = False )
ws = self . winfo_screenwidth ( )
hs = self . winfo_screenheight ( )
w = hs / 3
h = ws / 20
self . update ( )
if getattr ( sys , ' frozen ' , False ) :
self . iconbitmap ( sys . _MEIPASS + ' \\ id-card.ico \\ id-card.ico ' )
else :
self . iconbitmap ( ' id-card.ico ' )
x = ws / 2 - w / 2
y = hs / 2 - h / 2
self . geometry ( ' %d x %d + %d + %d ' % ( w , h , x , y ) )
def register0 ( self ) :
self . choice = 0
def register1 ( self ) :
self . choice = 1
def ok ( self ) :
self . destroy ( )
2019-08-12 17:07:37 +02:00
2019-08-10 19:59:16 +02:00
class OpenScanDialog ( Toplevel ) :
2019-07-19 17:17:30 +02:00
2019-08-10 19:59:16 +02:00
def __init__ ( self , parent , text ) :
super ( ) . __init__ ( parent )
self . parent = parent
2019-08-12 17:07:37 +02:00
self . title ( lang . all [ globs . CNIRlang ] [ " OCR Detection Validation " ] )
2019-08-10 19:59:16 +02:00
self . resizable ( width = False , height = False )
self . termtext = Text ( self , state = ' normal ' , width = 45 , height = 2 , wrap = ' none ' , font = ' Terminal 17 ' , fg = ' #121f38 ' )
self . termtext . grid ( column = 0 , row = 0 , sticky = ' NEW ' , padx = 5 , pady = 5 )
self . termtext . insert ( ' end ' , text + ' \n ' )
2019-08-12 17:07:37 +02:00
self . button = Button ( self , text = lang . all [ globs . CNIRlang ] [ " Validate " ] , command = ( self . valid ) )
2019-08-10 19:59:16 +02:00
self . button . grid ( column = 0 , row = 1 , sticky = ' S ' , padx = 5 , pady = 5 )
self . update ( )
hs = self . winfo_screenheight ( )
w = int ( self . winfo_width ( ) )
h = int ( self . winfo_height ( ) )
ws = self . winfo_screenwidth ( )
hs = self . winfo_screenheight ( )
x = ws / 2 - w / 2
y = hs / 2 - h / 2
self . geometry ( ' %d x %d + %d + %d ' % ( w , h , x , y ) )
if getattr ( sys , ' frozen ' , False ) :
self . iconbitmap ( sys . _MEIPASS + ' \\ id-card.ico \\ id-card.ico ' )
else :
self . iconbitmap ( ' id-card.ico ' )
def valid ( self ) :
self . parent . validatedtext = self . termtext . get ( ' 1.0 ' , ' end ' )
texting = self . parent . validatedtext . replace ( ' ' , ' ' ) . replace ( ' \r ' , ' ' ) . split ( ' \n ' )
for i in range ( len ( texting ) ) :
for char in texting [ i ] :
if char not in ' ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789< ' :
2019-08-12 17:07:37 +02:00
showerror ( lang . all [ globs . CNIRlang ] [ " Validation Error " ] , lang . all [ globs . CNIRlang ] [ " The submitted MRZ contains invalid characters " ] , parent = self )
2019-08-10 19:59:16 +02:00
self . parent . validatedtext = ' '
self . destroy ( )
2019-08-12 17:07:37 +02:00
2019-07-09 16:13:16 +02:00
class LoginDialog ( Toplevel ) :
def __init__ ( self , parent ) :
self . key = ' '
self . login = ' '
super ( ) . __init__ ( parent )
2019-08-12 17:07:37 +02:00
self . title ( lang . all [ globs . CNIRlang ] [ " Connection " ] )
2019-07-09 16:13:16 +02:00
Label ( self , text = ' IPN : ' ) . pack ( )
self . entry_login = Entry ( self )
self . entry_login . insert ( 0 , ' ' )
self . entry_login . pack ( )
2019-08-12 17:07:37 +02:00
Label ( self , text = ' {} : ' . format ( lang . all [ globs . CNIRlang ] [ " Password " ] ) ) . pack ( )
2019-07-09 16:13:16 +02:00
self . entry_pass = Entry ( self , show = ' * ' )
self . entry_pass . insert ( 0 , ' ' )
self . entry_pass . pack ( )
2019-08-12 17:07:37 +02:00
Button ( self , text = lang . all [ globs . CNIRlang ] [ " Connection " ] , command = ( self . connecti ) ) . pack ( )
2019-07-09 16:13:16 +02:00
self . resizable ( width = False , height = False )
ws = self . winfo_screenwidth ( )
hs = self . winfo_screenheight ( )
w = hs / 10
h = ws / 18
self . update ( )
if getattr ( sys , ' frozen ' , False ) :
self . iconbitmap ( sys . _MEIPASS + ' \\ id-card.ico \\ id-card.ico ' )
else :
self . iconbitmap ( ' id-card.ico ' )
x = ws / 2 - w / 2
y = hs / 2 - h / 2
self . geometry ( ' %d x %d + %d + %d ' % ( w , h , x , y ) )
2019-08-01 16:52:36 +02:00
self . bind ( " <Return> " , self . connecti )
2019-07-09 16:13:16 +02:00
2019-08-02 11:08:53 +02:00
def connecti ( self , event = None ) :
2019-07-09 16:13:16 +02:00
self . login = self . entry_login . get ( ) . strip ( )
self . key = self . entry_pass . get ( ) . strip ( )
self . destroy ( )
class LauncherWindow ( Tk ) :
def __init__ ( self ) :
# Initialize the tkinter main class
Tk . __init__ ( self )
self . resizable ( width = False , height = False )
# Setting up the geometry
ws = self . winfo_screenwidth ( )
hs = self . winfo_screenheight ( )
2019-08-06 16:01:01 +02:00
wheight = 274
wwidth = 480
# Centering
x = ws / 2 - wwidth / 2
y = hs / 2 - wheight / 2
self . geometry ( ' %d x %d + %d + %d ' % ( wwidth , wheight , x , y ) )
2019-07-09 16:13:16 +02:00
# Creating objects
2019-08-07 15:30:22 +02:00
# Load an image using OpenCV
2019-08-07 16:39:37 +02:00
# if getattr(sys, 'frozen', False):
# cv_img = cv2.imread(sys._MEIPASS + r"\background.png\background.png")
# else:
cv_img = cv2 . imread ( " background.png " )
2019-08-07 15:30:22 +02:00
cv_img = cv2 . imread ( " background.png " )
cv_img = cv2 . cvtColor ( cv_img , cv2 . COLOR_BGR2RGB )
cv_img = cv2 . blur ( cv_img , ( 15 , 15 ) )
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
height , width , no_channels = cv_img . shape
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
height , width , no_channels = cv_img . shape
# Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage
self . photo = PIL . ImageTk . PhotoImage ( image = PIL . Image . fromarray ( cv_img ) )
2019-08-06 16:01:01 +02:00
self . mainCanvas = Canvas ( self , width = wwidth , height = wheight , bg = globs . CNIRLColor , highlightthickness = 0 )
2019-08-07 15:30:22 +02:00
self . mainCanvas . create_image ( wwidth / 2 , wheight / 2 , image = self . photo )
2019-07-09 16:13:16 +02:00
2019-08-06 16:01:01 +02:00
# Column
self . mainCanvas . grid_rowconfigure ( 0 , weight = 1 , minsize = ( wheight / 10 * 9 ) )
self . mainCanvas . grid_rowconfigure ( 1 , weight = 1 , minsize = ( wheight / 10 * 1 ) )
2019-07-09 16:13:16 +02:00
self . mainCanvas . create_text ( ( wwidth / 2 ) , ( wheight / 3 ) , text = ( globs . CNIRName ) , font = ' Helvetica 30 ' , fill = ' white ' )
2019-08-06 11:27:10 +02:00
self . mainCanvas . create_text ( ( wwidth / 2 ) , ( wheight / 2 ) , text = " version " + ( globs . verstring_full ) , font = ' Helvetica 8 ' , fill = ' white ' )
2019-08-12 17:07:37 +02:00
self . msg = self . mainCanvas . create_text ( ( wwidth / 2 ) , ( wheight / 1.20 ) , text = lang . all [ globs . CNIRlang ] [ " Booting up... " ] , font = ' Helvetica 9 ' , fill = ' white ' )
2019-07-09 16:13:16 +02:00
2019-08-06 16:01:01 +02:00
#self.pBarZone = Frame(self.mainCanvas, width=wwidth, height=wheight/10)
self . update ( )
self . progressBar = ttk . Progressbar ( self . mainCanvas , orient = HORIZONTAL , length = wwidth , mode = ' determinate ' )
2019-07-09 16:13:16 +02:00
self . wm_title ( globs . CNIRName )
2019-08-06 16:01:01 +02:00
self . mainCanvas . grid ( row = 0 )
self . update ( )
self . progressBar . grid ( row = 1 , sticky = ' S ' )
2019-07-09 16:13:16 +02:00
if getattr ( sys , ' frozen ' , False ) :
self . iconbitmap ( sys . _MEIPASS + ' \\ id-card.ico \\ id-card.ico ' )
else :
self . iconbitmap ( ' id-card.ico ' )
logfile = logger . logCur
logfile . printdbg ( ' Launcher IHM successful ' )
2019-08-12 17:07:37 +02:00
self . protocol ( ' WM_DELETE_WINDOW ' , lambda : 0 )
2019-07-09 16:13:16 +02:00
self . update ( )
2019-07-10 16:50:40 +02:00
def printmsg ( self , msg ) :
self . mainCanvas . itemconfigure ( self . msg , text = ( msg ) )
2019-08-07 15:30:22 +02:00
def exit ( self ) :
self . after ( 1000 , self . destroy )
class ResizeableCanvas ( Canvas ) :
def __init__ ( self , parent , * * kwargs ) :
Canvas . __init__ ( self , parent , * * kwargs )
self . bind ( " <Configure> " , self . on_resize )
self . height = self . winfo_reqheight ( )
self . width = self . winfo_reqwidth ( )
def on_resize ( self , event ) :
# determine the ratio of old width/height to new width/height
wscale = float ( event . width ) / self . width
hscale = float ( event . height ) / self . height
self . width = event . width
self . height = event . height
# rescale all the objects tagged with the "all" tag
self . scale ( " all " , 0 , 0 , wscale , hscale )
2019-08-12 17:07:37 +02:00
def crashCNIR ( ) :
"""
last solution
"""
# Global handler
logfile = logger . logCur
# hide main window
root = Tk ( )
root . withdraw ( )
logfile . printerr ( " FATAL ERROR : see traceback below. \n {} " . format ( traceback . format_exc ( ) ) )
showerror ( lang . all [ globs . CNIRlang ] [ " CNIRevelator Fatal Eror " ] , lang . all [ globs . CNIRlang ] [ " CNIRevelator crashed because a fatal error occured. View log for more infos and please open an issue on Github " ] )
res = askquestion ( lang . all [ globs . CNIRlang ] [ " CNIRevelator Fatal Eror " ] , lang . all [ globs . CNIRlang ] [ " Would you like to open an issue on Github to report this bug ? " ] )
if res == " yes " :
webbrowser . open_new ( " https://github.com/neox95/CNIRevelator/issues " )
root . destroy ( )
2019-07-09 16:13:16 +02:00
## Global Handler
launcherWindowCur = LauncherWindow ( )