1- import sys , os , pyperclip , glob , json , typing
1+ import sys , os , pyperclip , glob , json
2+ from PyQt5 .QtWidgets import QWidget
23import traceback , importlib , requests , subprocess
3- import nltk , base64 , hashlib , cryptography
44
5- from PyQt5 import QtCore , QtGui , QtWidgets
5+ from PyQt5 import QtCore
66from PyQt5 .QtCore import *
77from PyQt5 .QtGui import *
88from PyQt5 .QtWidgets import *
9- from typing import (List as list ,
10- Tuple as tuple ,
11- Dict as dict ,
12- Callable )
9+ from typing import Callable , Iterator , Tuple
1310from uibld import *
1411from uibld .settings import *
1512from uibld .style import *
1613
1714
1815#Global variables declaration
1916gitHubLink = 'https://github.com/StarterCraft/sicrypt'
20- version = 'v1.2'
17+ version = 'v1.3'
18+ ciphers = []
19+ categories = []
2120
2221
2322class Window (QMainWindow ):
@@ -27,7 +26,7 @@ class Window(QMainWindow):
2726 #Translate function to simplify translation
2827 translate = QApplication .translate
2928
30- def __init__ (self , UIClass : ( Ui_MainWindowVertical , Ui_MainWindowHorizontal ) , config ):
29+ def __init__ (self , UIClass : Ui_MainWindowVertical | Ui_MainWindowHorizontal , config ):
3130 QMainWindow .__init__ (self )
3231 self .ui = UIClass ()
3332 self .ui .setupUi (self )
@@ -108,6 +107,7 @@ class PlainTextEdit(QPlainTextEdit):
108107 def __init__ (self , * args , ** kwargs ):
109108 super ().__init__ (* args , ** kwargs )
110109
110+
111111 def setTabPolicy (self , policy : int ) -> None :
112112 '''
113113 Set the text field's tab policy. Auxilary method.
@@ -331,10 +331,12 @@ def applyConfig(self, root: Window, onInit: bool = False) -> None:
331331
332332 #False for default vertical position,
333333 #True for horizontal position
334- if (type (self .ui ) == Ui_MainWindowHorizontal ) != self .config ['textFields' ]['position' ] and not onInit :
335- messageBox (root , QMessageBox .Information ,
336- root .translate ('TextFieldsPositionChangedDialog' , 'Text fields` position has been changed' ),
337- root .translate ('TextFieldsPositionChangedDialog' , 'Text fields` position has been changed, changes`ll be applied after restart' ))
334+ if (not onInit ):
335+ print (('Гориз сейчас' if type (root .ui ) == Ui_MainWindowHorizontal else 'Верт сейчас' ), "хочу" , ('гориз' if self .config ['textFields' ]['position' ] else 'верт' ))
336+ if (type (root .ui ) == Ui_MainWindowHorizontal ) != self .config ['textFields' ]['position' ]:
337+ root .ui = (Ui_MainWindowHorizontal if self .config ['textFields' ]['position' ] else Ui_MainWindowVertical )()
338+ root .ui .setupUi (root )
339+ initUi (root , self )
338340
339341 #Setting font
340342 root .ui .ptx_SourceText .setStyleSheet (f'font: { config ["font" ][0 ]} ' )
@@ -394,6 +396,18 @@ def handleDialogAcception(self, root: Window) -> None:
394396 self .applyConfig (root )
395397
396398
399+ class CipherLoadingDialog (QDialog ):
400+ def __init__ (self ):
401+ QDialog .__init__ ()
402+
403+ self .setStyleSheet (styleSheet )
404+
405+ self .label = QLabel (self .tr ('Загрузка шифров... Пожалуйста, подождите.' ))
406+ self .pgbar = QProgressBar ()
407+
408+ self .show ()
409+
410+
397411class Cipher :
398412 '''
399413 A representation of a cipher, allowing to add custom ciphers to the
@@ -479,6 +493,48 @@ def getInformation(self, root: Window) -> str:
479493
480494
481495#Major functions are defined below
496+ def initUi (root : Window , settings : Settings ):
497+ root .ui .cbb_Cipher .setToolTip (ciphers [0 ].getInformation (root ))
498+
499+ checkForUpdates (root )
500+
501+ #Bind functions to actions and buttons
502+ root .ui .tbt_Encrypt .clicked .connect ( lambda : encrypt (root , 'utf-8' ) )
503+ root .ui .tbt_Decrypt .clicked .connect ( lambda : decrypt (root , 'utf-8' ) )
504+ root .ui .btn_Paste .clicked .connect ( lambda : pasteSourceText (root ) )
505+ root .ui .btn_Copy .clicked .connect ( lambda : copyResultText (root ) )
506+ root .ui .btn_TransferResToSrc .clicked .connect ( lambda : transferText (root , True ) )
507+ root .ui .btn_TransferSrcToRes .clicked .connect ( lambda : transferText (root , False ) )
508+ root .ui .btn_About .clicked .connect ( lambda : info (root ) )
509+ root .ui .btn_Settings .clicked .connect ( settings .open )
510+ root .ui .tbt_OpenFile .clicked .connect ( lambda : openFileDialog (root , 'utf-8' , True , root .openFileActionGroup .actions ()[0 ].isChecked ()) )
511+ root .ui .tbt_SaveToFile .clicked .connect ( lambda : openFileDialog (root , 'utf-8' , False , root .saveToFileActionGroup .actions ()[0 ].isChecked ()) )
512+ root .ui .cbb_Cipher .currentTextChanged .connect ( lambda : switchCurrentCipher (root ) )
513+
514+ for action in root .openFileActionGroup .actions ():
515+ if action .text ()[1 :7 ] == 'Source' : action .setChecked (True )
516+
517+ for action in root .saveToFileActionGroup .actions ():
518+ if action .text ()[1 :7 ] == 'Result' : action .setChecked (True )
519+
520+ for i in range (0 , 4 ):
521+ for action in root .encodingActions [i ]:
522+ if i in range (0 , 2 ): action .triggered .connect ( lambda : openFileDialog (root , action .text ().lower (), action .data ()) )
523+ elif i == 2 : action .triggered .connect ( lambda : encrypt (root , action .text ().lower ()) )
524+ elif i == 3 : action .triggered .connect ( lambda : decrypt (root , action .text ().lower ()) )
525+
526+ for customEncodingAction in root .customEncodingActions : customEncodingAction .triggered .connect (
527+ lambda : (openFileDialog (root ,
528+ inputDialog (root , root .tr ('Custom encoding' ), root .tr ('Specify an encoding...' )).lower (), customEncodingAction .data ())
529+ if customEncodingAction .data () in range (0 , 2 ) else (customEncodingAction .triggered .connect (
530+ lambda : encrypt (root , inputDialog (root , root .tr ('Custom encoding' ), root .tr ('Specify an encoding...' )).lower ())
531+ if action .data () == 2 else customEncodingAction .triggered .connect (
532+ lambda : decrypt (root , inputDialog (root , root .tr ('Custom encoding' ), root .tr ('Specify an encoding...' )).lower ())
533+ )))))
534+
535+ addCiphersToCbbCipher (root )
536+
537+
482538def checkForUpdates (root : Window ):
483539 '''
484540 Check for updates, and if there is one, ask the user
@@ -489,25 +545,28 @@ def checkForUpdates(root: Window):
489545
490546 :returns: None
491547 '''
492- response = getRequest (root , 'https://api.github.com/repos/StarterCraft/sicrypt/releases/latest' ).json ()
493- tag = response ['tag_name' ]
494- if int (tag [1 :2 ]) > int (version [1 :2 ]) or int (tag [3 :4 ]) > int (version [3 :4 ]):
495- if messageBox (root , QMessageBox .Information ,
496- root .translate ('UpdateDialog' , 'Update available' ),
497- root .translate ('UpdateDialog' , f'Update { tag } is available, would you like to download and install it?' ),
498- details = getRequest (root , 'https://raw.githubusercontent.com/StarterCraft/sicrypt/master/changelog.txt' ).text ,
499- buttons = [QMessageBox .Yes , QMessageBox .No ]):
500- installerURL = getRequest (root , response ['assets_url' ]).json ()['browser_download_url' ]
501-
502- with requests .get (installerURL , stream = True ) as request :
503- request .raise_for_status ()
504- with open ('installer.exe' , 'wb' ) as f :
505- for chunk in request .iter_content (chunk_size = None ):
506- if chunk : f .write (chunk )
507-
508- subprocess .Popen ('installer.exe' , creationflags = subprocess .CREATE_NEW_CONSOLE )
509- exit (1 )
510- else : return
548+ try :
549+ response = getRequest (root , 'https://api.github.com/repos/StarterCraft/sicrypt/releases/latest' ).json ()
550+ tag = response ['tag_name' ]
551+ if int (tag [1 :2 ]) > int (version [1 :2 ]) or int (tag [3 :4 ]) > int (version [3 :4 ]):
552+ if messageBox (root , QMessageBox .Information ,
553+ root .translate ('UpdateDialog' , 'Update available' ),
554+ root .translate ('UpdateDialog' , f'Update { tag } is available, would you like to download and install it?' ),
555+ details = getRequest (root , 'https://raw.githubusercontent.com/StarterCraft/sicrypt/master/changelog.txt' ).text ,
556+ buttons = [QMessageBox .Yes , QMessageBox .No ]):
557+ installerURL = getRequest (root , response ['assets_url' ]).json ()['browser_download_url' ]
558+
559+ with requests .get (installerURL , stream = True ) as request :
560+ request .raise_for_status ()
561+ with open ('installer.exe' , 'wb' ) as f :
562+ for chunk in request .iter_content (chunk_size = None ):
563+ if chunk : f .write (chunk )
564+
565+ subprocess .Popen ('installer.exe' , creationflags = subprocess .CREATE_NEW_CONSOLE )
566+ exit (1 )
567+ else : return
568+ except KeyError : #github api does not return a valid message
569+ pass
511570
512571
513572def loadCiphers (root : Window , allowDownloadingNew : bool , allowDownloadingUpdates : bool ) -> None :
@@ -527,7 +586,7 @@ def loadCiphers(root: Window, allowDownloadingNew: bool, allowDownloadingUpdates
527586
528587 :returns: None
529588 '''
530- global ciphers
589+ global ciphers , categories
531590
532591 ciphers , categories , classNames = [], [], {}
533592 available = glob .glob ('ciphers/*' )
@@ -542,11 +601,15 @@ def loadCiphers(root: Window, allowDownloadingNew: bool, allowDownloadingUpdates
542601 #Find now ciphers on GitHub
543602 if allowDownloadingNew :
544603 availableOnGitHub = []
545- for file in getRequest (root , 'https://api.github.com/repos/StarterCraft/sicrypt/git/trees/master?recursive=1' ).json ()['tree' ]:
546- try :
547- if (file ['path' ][:file ['path' ].index ('/' )] == 'ciphers' and file ['path' ].endswith ('.py' )):
548- availableOnGitHub .append (file ['path' ])
549- except ValueError : continue
604+
605+ try :
606+ for file in getRequest (root , 'https://api.github.com/repos/StarterCraft/sicrypt/git/trees/master?recursive=1' ).json ()['tree' ]:
607+ try :
608+ if (file ['path' ][:file ['path' ].index ('/' )] == 'ciphers' and file ['path' ].endswith ('.py' )):
609+ availableOnGitHub .append (file ['path' ])
610+ except ValueError : continue
611+ except KeyError :
612+ pass
550613
551614 for file in availableOnGitHub :
552615 if file not in available [:]:
@@ -567,7 +630,17 @@ def loadCiphers(root: Window, allowDownloadingNew: bool, allowDownloadingUpdates
567630 savedNames .append (className )
568631 classNames .update ({fileName .replace ('/' , '.' ): savedNames })
569632
633+ loading = QProgressDialog ('Downloading ciphers...' , 'Abort' , 0 , len (classNames .items ()))
634+ loading .setWindowTitle ('Downloading ciphers...' )
635+ loading .setWindowModality (Qt .WindowModality .WindowModal )
636+ loading .setValue (0 )
637+ loading .show ()
638+ print (638 )
639+ cix = 0
640+
570641 for classFile , classNames in classNames .items ():
642+ loading .setValue (cix )
643+
571644 for className in classNames :
572645 _class = getattr (importlib .import_module (classFile [:- 3 ]), className )
573646 try :
@@ -583,14 +656,15 @@ def loadCiphers(root: Window, allowDownloadingNew: bool, allowDownloadingUpdates
583656 response = getRequest (root , f'https://raw.githubusercontent.com/StarterCraft/sicrypt/master/{ classFile .replace ("." , "/" )} ' )
584657 if response == 200 :
585658 file .write (response .text )
659+
586660 _compareClass = getattr (importlib .import_module ('ciphers.dl' ), className )
587661 if _compareClass .version == _class .version : pass
588662 elif _compareClass .version [0 ] > _class .version [0 ] or _compareClass .version [1 ] > _class .version [1 ]:
589663 with open (classFile , 'w' ) as originalFile : originalFile .write (response .text )
590664 ciphers .append (_compareClass ())
591665
592666 ciphers .append (_class ())
593- os .system ( 'del ciphers\\ dl.cache' )
667+ os .remove ( ' ciphers/ dl.cache' )
594668
595669 else : messageBox (root , QMessageBox .Critical ,
596670 root .translate ('CipherLoadingErrorMessagebox' , f'Failed to load cipher { className } ' ),
@@ -600,8 +674,17 @@ def loadCiphers(root: Window, allowDownloadingNew: bool, allowDownloadingUpdates
600674 messageBox (root , QMessageBox .Critical , root .translate ('CipherLoadingErrorMessagebox' , f'Failed to load cipher { className } ' ),
601675 root .translate ('CipherLoadingErrorMessagebox' ,
602676 f'Cipher { className } , declared in { classFile } , failed to load due to { type (exception ).__name__ } . See the details below' ),
603- details = f'Our GitHub:{ gitHubLink } \n { traceback .format_exc ()} ' )
677+ details = f'Our GitHub: { gitHubLink } \n { traceback .format_exc ()} ' )
678+
679+ cix += 1
680+
681+ if (loading .wasCanceled ()):
682+ return
683+
684+ loading .hide ()
604685
686+
687+ def addCiphersToCbbCipher (root : Window ):
605688 for cipher in ciphers :
606689 if cipher .category not in categories : categories .append (cipher .category )
607690
@@ -749,7 +832,7 @@ def pasteSourceText(root: Window) -> None:
749832
750833 :returns: None
751834 '''
752- root .ui .plainTextEdit .setPlainText (str (pyperclip .paste ()))
835+ root .ui .ptx_SourceText .setPlainText (str (pyperclip .paste ()))
753836
754837
755838def info (root : Window ) -> None :
@@ -950,7 +1033,7 @@ def getRequest(root: Window, url: str):
9501033 details = f'Our GitHub:{ gitHubLink } \n \n { traceback .format_exc ()} ' )
9511034
9521035
953- if __name__ == '__main__' :
1036+ def main () :
9541037 app = QApplication (sys .argv )
9551038 app .setStyleSheet (appStyleSheet )
9561039
@@ -965,43 +1048,10 @@ def getRequest(root: Window, url: str):
9651048 try :
9661049 #Load ciphers
9671050 loadCiphers (root , settings .config ['encryption' ]['dlnew' ], settings .config ['encryption' ]['dlupd' ])
968- root .ui .cbb_Cipher .setToolTip (ciphers [0 ].getInformation (root ))
969-
1051+
9701052 checkForUpdates (root )
9711053
972- #Bind functions to actions and buttons
973- root .ui .tbt_Encrypt .clicked .connect ( lambda : encrypt (root , 'utf-8' ) )
974- root .ui .tbt_Decrypt .clicked .connect ( lambda : decrypt (root , 'utf-8' ) )
975- root .ui .btn_Paste .clicked .connect ( lambda : pasteSourceText (root ) )
976- root .ui .btn_Copy .clicked .connect ( lambda : copyResultText (root ) )
977- root .ui .btn_TransferResToSrc .clicked .connect ( lambda : transferText (root , True ) )
978- root .ui .btn_TransferSrcToRes .clicked .connect ( lambda : transferText (root , False ) )
979- root .ui .btn_About .clicked .connect ( lambda : info (root ) )
980- root .ui .btn_Settings .clicked .connect ( settings .open )
981- root .ui .tbt_OpenFile .clicked .connect ( lambda : openFileDialog (root , 'utf-8' , True , root .openFileActionGroup .actions ()[0 ].isChecked ()) )
982- root .ui .tbt_SaveToFile .clicked .connect ( lambda : openFileDialog (root , 'utf-8' , False , root .saveToFileActionGroup .actions ()[0 ].isChecked ()) )
983- root .ui .cbb_Cipher .currentTextChanged .connect ( lambda : switchCurrentCipher (root ) )
984-
985- for action in root .openFileActionGroup .actions ():
986- if action .text ()[1 :7 ] == 'Source' : action .setChecked (True )
987-
988- for action in root .saveToFileActionGroup .actions ():
989- if action .text ()[1 :7 ] == 'Result' : action .setChecked (True )
990-
991- for i in range (0 , 4 ):
992- for action in root .encodingActions [i ]:
993- if i in range (0 , 2 ): action .triggered .connect ( lambda : openFileDialog (root , action .text ().lower (), action .data ()) )
994- elif i == 2 : action .triggered .connect ( lambda : encrypt (root , action .text ().lower ()) )
995- elif i == 3 : action .triggered .connect ( lambda : decrypt (root , action .text ().lower ()) )
996-
997- for customEncodingAction in root .customEncodingActions : customEncodingAction .triggered .connect (
998- lambda : (openFileDialog (root ,
999- inputDialog (root , root .tr ('Custom encoding' ), root .tr ('Specify an encoding...' )).lower (), customEncodingAction .data ())
1000- if customEncodingAction .data () in range (0 , 2 ) else (customEncodingAction .triggered .connect (
1001- lambda : encrypt (root , inputDialog (root , root .tr ('Custom encoding' ), root .tr ('Specify an encoding...' )).lower ())
1002- if action .data () == 2 else customEncodingAction .triggered .connect (
1003- lambda : decrypt (root , inputDialog (root , root .tr ('Custom encoding' ), root .tr ('Specify an encoding...' )).lower ())
1004- )))))
1054+ initUi (root , settings )
10051055
10061056 #Settings dialog
10071057 settings .accepted .connect ( lambda : settings .handleDialogAcception (root ) )
@@ -1022,3 +1072,6 @@ def getRequest(root: Window, url: str):
10221072 'have fixed this problem yourself, huge thanks to you, please submit a pull request with the code files '
10231073 'you have changed.' ),
10241074 details = f'Our GitHub: { gitHubLink } \n \n { traceback .format_exc ()} ' )
1075+
1076+ if __name__ == '__main__' :
1077+ main ()
0 commit comments