From c9bd900fd4c019dbdfb09d93f58f1f745b8b31f6 Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 10 Dec 2017 14:25:33 +0300 Subject: [PATCH 01/25] Initial commit --- .idea/Log_Viewer.iml | 11 ++++++ .idea/misc.xml | 4 ++ .idea/modules.xml | 8 ++++ icon.png | Bin 0 -> 1397 bytes loader.py | 29 ++++++++++++++ main_form.py | 91 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 143 insertions(+) create mode 100644 .idea/Log_Viewer.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 icon.png create mode 100644 loader.py create mode 100644 main_form.py diff --git a/.idea/Log_Viewer.iml b/.idea/Log_Viewer.iml new file mode 100644 index 0000000..6711606 --- /dev/null +++ b/.idea/Log_Viewer.iml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..88b7f69 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..be782af --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/icon.png b/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b7de9392ea18e5a8a3cc9ce3a58a9dae990bf537 GIT binary patch literal 1397 zcmV-*1&aEKP)N2bZe?^J zG%heMF*(%MvSa`N1oBBlK~z{rrPoQXRYep9V359jNF$&=MC=<74R$dib|fYeCq@S* z{tun_k4zjmaO^}9hbA&{U;{C6;xjQ0FkaVJulAwt;qe@Jl69-wwb!a$`&6B~WwBW7 z33di|1zUUlk>FDBTJTcvZ18w+Ie4d+Zw40wo@8y2PFe%;963vb$b?`aoN?C-s$HJ{)`!yc|3cJP>fU+DoB7 z9oUBR!HdC#z;+gD{MVCq6ChLD zo(GakDH6hcBF@&D<3C~=lz=%JX}9Sj)-u2LUqa*B)`@Guhcw1Lv3Kh41zVcafxIvm zu|!_DdhnkvLPGB5FR1M$%EI?)5P;mP^K>9lRwnWe^V;0rHeR@sO}G0Y{@Q{9k+4A9 zOTbQ@GFgW`gWZ|*dvnlN)0~d=VXPtT+iZrhCURXsEzhh9CMpO#%2+)-43pkL5qNjeL+s$rAfeMn2~IT zL4eQ`;BCXZU#HWH0EdStytPpTmM|aN+_v6^G+Lrts6)>^(O$!60s@rOF*uk>H}B|J z{~R0J{T)Bw#GfNM9WC^@tX@7G)#<85{CXfX-iqgfr!x8T+lUIwL>s}%uXkU3;<7jb zyy~LeuH!Q*fsG<0v)kc8B@s&};Y9c!?acc=^Q|0YdK|LM09>e=@+cOXqm|sj9d0Ac*IN+fK%ba3-je^YKdRzXlSp zw&32tB3L>YoX4>eiOyIMAurpWX@T_Q;2)*Yk~l2p^zl zCjqxsp6<44ua;~4Gksru`r%waCbZlF?ZbWwMcmK@xhZ{aNg@$A8(f|Q3=zoVV0quX zwEtSVs@Id6KLTtmTTwVY5eDPxtE5!el)@^R-kt<>6j7nbgE|FEfOAF;XyaHd@*<^b zY)eR!?3=xHfLxgb^avmm?h1Kt-;CY0*gFUOZ{X8W%vUA)$s#MlxquSkQ~RTUvx{*& zeIt$niX39|ZEO+SLVsZRbPm|c5^$o3M#4hN)Se3_c!j7J!c!smB@t-%#Yo)AW71w- z2`q2?!{SF`*Ea!78y?i0SB?A1^r`cmV z6UVmNI{ggjZ{-jHVhE^Ybccuv)OlZ!xFxt2R*S Date: Sun, 10 Dec 2017 18:39:37 +0300 Subject: [PATCH 02/25] Text field fills all space of a tab. --- main_form.py | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/main_form.py b/main_form.py index 7d2e2a0..ce1e0c7 100644 --- a/main_form.py +++ b/main_form.py @@ -18,15 +18,12 @@ def __init__(self, main_space, file_path=''): self.scroll = tkinter.Scrollbar(self.page) # объект скролбарр на вкладку self.txt = tkinter.Text(self.page, font="TextFont", yscrollcommand=self.scroll.set) # объект текстовое поле - self.page.grid(row=1, column=0, sticky='nesw') - self.page.grid_propagate() - self.txt.grid(row=1, column=0, sticky='nesw') # задаем размещение текстового поле + self.scroll.config(command=self.txt.yview) # прикрепляем скроллбар к текстовому полю - #self.txt.pack(side='left', expand=True) # задаем размещение текстового поле - #self.scroll.pack(side='right', fill=tkinter.Y) # задаем размещение скроллбара + self.txt.pack(side='left', fill='both', expand=True) # задаем размещение текстового поле + self.scroll.pack(side='right', fill=tkinter.Y) # задаем размещение скроллбара - self.scroll.grid(row=1, column=50, sticky='nse') # задаем размещение скроллбара main_space.add(self.page, text='{}'.format(self.tab_name)) # добавляем вкладку self.txt.insert(tkinter.END, self.document.get_lines()) # вставляем текст из нашего документа @@ -72,17 +69,9 @@ def add_tab(): root.config(menu=m) m.add_command(label="Open...", command=add_tab) -# gives weight to the cells in the grid -rows = 0 -while rows < 50: - root.rowconfigure(rows, weight=1) - root.columnconfigure(rows, weight=1) - rows += 1 - # Defines and places the notebook widget nb = ttk.Notebook(root) -# TODO заменить на упаковщик pack() -nb.grid(row=1, column=0, columnspan=50, rowspan=49, sticky='NESW') +nb.pack(fill='both', expand='yes') # здесь заканчивается описание UI From 75baaf956cff3d6879cd317cb45a9ee109bc6650 Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 10 Dec 2017 22:21:01 +0300 Subject: [PATCH 03/25] Change app icon --- icon.png | Bin 1397 -> 0 bytes main_form.py | 10 ++++++---- 2 files changed, 6 insertions(+), 4 deletions(-) delete mode 100644 icon.png diff --git a/icon.png b/icon.png deleted file mode 100644 index b7de9392ea18e5a8a3cc9ce3a58a9dae990bf537..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1397 zcmV-*1&aEKP)N2bZe?^J zG%heMF*(%MvSa`N1oBBlK~z{rrPoQXRYep9V359jNF$&=MC=<74R$dib|fYeCq@S* z{tun_k4zjmaO^}9hbA&{U;{C6;xjQ0FkaVJulAwt;qe@Jl69-wwb!a$`&6B~WwBW7 z33di|1zUUlk>FDBTJTcvZ18w+Ie4d+Zw40wo@8y2PFe%;963vb$b?`aoN?C-s$HJ{)`!yc|3cJP>fU+DoB7 z9oUBR!HdC#z;+gD{MVCq6ChLD zo(GakDH6hcBF@&D<3C~=lz=%JX}9Sj)-u2LUqa*B)`@Guhcw1Lv3Kh41zVcafxIvm zu|!_DdhnkvLPGB5FR1M$%EI?)5P;mP^K>9lRwnWe^V;0rHeR@sO}G0Y{@Q{9k+4A9 zOTbQ@GFgW`gWZ|*dvnlN)0~d=VXPtT+iZrhCURXsEzhh9CMpO#%2+)-43pkL5qNjeL+s$rAfeMn2~IT zL4eQ`;BCXZU#HWH0EdStytPpTmM|aN+_v6^G+Lrts6)>^(O$!60s@rOF*uk>H}B|J z{~R0J{T)Bw#GfNM9WC^@tX@7G)#<85{CXfX-iqgfr!x8T+lUIwL>s}%uXkU3;<7jb zyy~LeuH!Q*fsG<0v)kc8B@s&};Y9c!?acc=^Q|0YdK|LM09>e=@+cOXqm|sj9d0Ac*IN+fK%ba3-je^YKdRzXlSp zw&32tB3L>YoX4>eiOyIMAurpWX@T_Q;2)*Yk~l2p^zl zCjqxsp6<44ua;~4Gksru`r%waCbZlF?ZbWwMcmK@xhZ{aNg@$A8(f|Q3=zoVV0quX zwEtSVs@Id6KLTtmTTwVY5eDPxtE5!el)@^R-kt<>6j7nbgE|FEfOAF;XyaHd@*<^b zY)eR!?3=xHfLxgb^avmm?h1Kt-;CY0*gFUOZ{X8W%vUA)$s#MlxquSkQ~RTUvx{*& zeIt$niX39|ZEO+SLVsZRbPm|c5^$o3M#4hN)Se3_c!j7J!c!smB@t-%#Yo)AW71w- z2`q2?!{SF`*Ea!78y?i0SB?A1^r`cmV z6UVmNI{ggjZ{-jHVhE^Ybccuv)OlZ!xFxt2R*S Date: Sun, 10 Dec 2017 22:23:54 +0300 Subject: [PATCH 04/25] Change app icon --- icon.ico | Bin 0 -> 932 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 icon.ico diff --git a/icon.ico b/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..aeb39e4aa6e68c846c65b0515952f929bb4fe88e GIT binary patch literal 932 zcmb7@!AiqG5QhJdgOH2K#d^{Tg(P5#N0H*gXoYwZsUYU$xv$X|=>zm3dh+Z+ski#? zjys!djNoQ=+1dH#p9z})5uY>#*JIQ%a0H;> Date: Mon, 11 Dec 2017 19:06:38 +0300 Subject: [PATCH 05/25] Change size for Linux and Windows --- .idea/Log_Viewer.iml | 2 +- .idea/misc.xml | 2 +- main_form.py | 20 ++++++++++++++++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.idea/Log_Viewer.iml b/.idea/Log_Viewer.iml index 6711606..6cb58bd 100644 --- a/.idea/Log_Viewer.iml +++ b/.idea/Log_Viewer.iml @@ -2,7 +2,7 @@ - + diff --git a/.idea/misc.xml b/.idea/misc.xml index 88b7f69..18f88b2 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/main_form.py b/main_form.py index 8799d48..65828a9 100644 --- a/main_form.py +++ b/main_form.py @@ -4,6 +4,13 @@ from loader import Tail import time import threading +import os + + +APP_WIDTH_WIN = 750 +APP_HEIGHT = 400 +APP_WIDTH_LINUX = 825 + # список всех вкладок list_of_tab = [] @@ -58,12 +65,16 @@ def add_tab(): # здесь начинается описание UI root = tkinter.Tk() -app_width = 750 -app_height = 400 +if os.name == 'posix': + app_width = APP_WIDTH_LINUX +else: + app_width = APP_WIDTH_WIN + +app_height = APP_HEIGHT start_pos_x = int((root.winfo_screenwidth() / 2) - (app_width / 2)) start_pos_y = int((root.winfo_screenheight() / 2.5) - (app_height / 2)) root.title('LogViewer') -root.iconbitmap('icon.ico') +root.iconbitmap(r''.format(os.path.join(os.path.realpath(__file__), 'icon.ico'))) root.geometry('{0}x{1}+{2}+{3}'.format(app_width, app_height, start_pos_x, start_pos_y)) root.minsize(app_width, app_height) @@ -76,7 +87,8 @@ def add_tab(): nb.pack(fill='both', expand='yes') # здесь заканчивается описание UI - +#поток для обновления вкладок thread_update_tabs = threading.Thread(target=update_tabs, daemon=True, name='update_tabs') thread_update_tabs.start() + root.mainloop() # запуск отрисовки UI From 46e8dea6eca5dc3a4dfcff367ead6d2a0f91206c Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 11 Dec 2017 23:26:26 +0300 Subject: [PATCH 06/25] Path to icon. --- main_form.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/main_form.py b/main_form.py index 65828a9..a9760e2 100644 --- a/main_form.py +++ b/main_form.py @@ -63,18 +63,21 @@ def add_tab(): return -# здесь начинается описание UI -root = tkinter.Tk() if os.name == 'posix': app_width = APP_WIDTH_LINUX + path_to_icon = os.path.join(os.path.realpath(__file__), 'icon.ico') else: app_width = APP_WIDTH_WIN + path_to_icon = 'icon.ico' + +# здесь начинается описание UI +root = tkinter.Tk() app_height = APP_HEIGHT start_pos_x = int((root.winfo_screenwidth() / 2) - (app_width / 2)) start_pos_y = int((root.winfo_screenheight() / 2.5) - (app_height / 2)) root.title('LogViewer') -root.iconbitmap(r''.format(os.path.join(os.path.realpath(__file__), 'icon.ico'))) +root.iconbitmap(path_to_icon) root.geometry('{0}x{1}+{2}+{3}'.format(app_width, app_height, start_pos_x, start_pos_y)) root.minsize(app_width, app_height) From 2b3944510fa7b35d147c184afc01879390d609e7 Mon Sep 17 00:00:00 2001 From: Denis Date: Tue, 12 Dec 2017 00:42:58 +0300 Subject: [PATCH 07/25] Change app icon --- icon.xbm | 9 +++++++++ icon.xbm.mask | 9 +++++++++ main_form.py | 4 ++-- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 icon.xbm create mode 100644 icon.xbm.mask diff --git a/icon.xbm b/icon.xbm new file mode 100644 index 0000000..078f351 --- /dev/null +++ b/icon.xbm @@ -0,0 +1,9 @@ +#define icon_width 16 +#define icon_height 16 +#define icon_x_hot 0 +#define icon_y_hot 0 +static char icon_bits[] = { + 0xFF,0xFF,0xF7,0xEF,0xF3,0xCF,0xF1,0x8F,0xE1,0x87,0xC1,0x83, + 0x01,0x81,0x81,0x80,0x41,0x81,0x03,0xC0,0x07,0xE0,0x0F,0xF0, + 0x1F,0xF8,0x3F,0xFC,0x7F,0xFE,0x7F,0xFE +}; \ No newline at end of file diff --git a/icon.xbm.mask b/icon.xbm.mask new file mode 100644 index 0000000..5a46ca9 --- /dev/null +++ b/icon.xbm.mask @@ -0,0 +1,9 @@ +#define icon_width 16 +#define icon_height 16 +#define icon_x_hot 0 +#define icon_y_hot 0 +static char icon_mask_bits[] = { + 0xF8,0x1F,0xFC,0x3F,0xFE,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F,0xFC,0x3F,0xF8,0x1F, + 0xF0,0x0F,0xE0,0x07,0xE0,0x07,0xE0,0x07 +}; \ No newline at end of file diff --git a/main_form.py b/main_form.py index a9760e2..6f7109f 100644 --- a/main_form.py +++ b/main_form.py @@ -65,7 +65,7 @@ def add_tab(): if os.name == 'posix': app_width = APP_WIDTH_LINUX - path_to_icon = os.path.join(os.path.realpath(__file__), 'icon.ico') + path_to_icon = 'icon.xbm' else: app_width = APP_WIDTH_WIN path_to_icon = 'icon.ico' @@ -77,7 +77,7 @@ def add_tab(): start_pos_x = int((root.winfo_screenwidth() / 2) - (app_width / 2)) start_pos_y = int((root.winfo_screenheight() / 2.5) - (app_height / 2)) root.title('LogViewer') -root.iconbitmap(path_to_icon) +root.iconbitmap(os.path.join(os.getcwd(), path_to_icon)) root.geometry('{0}x{1}+{2}+{3}'.format(app_width, app_height, start_pos_x, start_pos_y)) root.minsize(app_width, app_height) From 0f64442f639e038c1a834f6c9c0e72f12197460e Mon Sep 17 00:00:00 2001 From: Denis Date: Tue, 12 Dec 2017 00:49:24 +0300 Subject: [PATCH 08/25] Change app icon --- .idea/Log_Viewer.iml | 2 +- .idea/misc.xml | 2 +- icon.xbm | 9 --------- icon.xbm.mask | 9 --------- main_form.py | 5 +++-- 5 files changed, 5 insertions(+), 22 deletions(-) delete mode 100644 icon.xbm delete mode 100644 icon.xbm.mask diff --git a/.idea/Log_Viewer.iml b/.idea/Log_Viewer.iml index 6cb58bd..799a15f 100644 --- a/.idea/Log_Viewer.iml +++ b/.idea/Log_Viewer.iml @@ -2,7 +2,7 @@ - + diff --git a/.idea/misc.xml b/.idea/misc.xml index 18f88b2..88b7f69 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/icon.xbm b/icon.xbm deleted file mode 100644 index 078f351..0000000 --- a/icon.xbm +++ /dev/null @@ -1,9 +0,0 @@ -#define icon_width 16 -#define icon_height 16 -#define icon_x_hot 0 -#define icon_y_hot 0 -static char icon_bits[] = { - 0xFF,0xFF,0xF7,0xEF,0xF3,0xCF,0xF1,0x8F,0xE1,0x87,0xC1,0x83, - 0x01,0x81,0x81,0x80,0x41,0x81,0x03,0xC0,0x07,0xE0,0x0F,0xF0, - 0x1F,0xF8,0x3F,0xFC,0x7F,0xFE,0x7F,0xFE -}; \ No newline at end of file diff --git a/icon.xbm.mask b/icon.xbm.mask deleted file mode 100644 index 5a46ca9..0000000 --- a/icon.xbm.mask +++ /dev/null @@ -1,9 +0,0 @@ -#define icon_width 16 -#define icon_height 16 -#define icon_x_hot 0 -#define icon_y_hot 0 -static char icon_mask_bits[] = { - 0xF8,0x1F,0xFC,0x3F,0xFE,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F,0xFC,0x3F,0xF8,0x1F, - 0xF0,0x0F,0xE0,0x07,0xE0,0x07,0xE0,0x07 -}; \ No newline at end of file diff --git a/main_form.py b/main_form.py index 6f7109f..8ceeafd 100644 --- a/main_form.py +++ b/main_form.py @@ -65,10 +65,11 @@ def add_tab(): if os.name == 'posix': app_width = APP_WIDTH_LINUX - path_to_icon = 'icon.xbm' + path_to_icon = '' else: app_width = APP_WIDTH_WIN path_to_icon = 'icon.ico' + path_to_icon = os.path.join(os.getcwd(), path_to_icon) # здесь начинается описание UI root = tkinter.Tk() @@ -77,7 +78,7 @@ def add_tab(): start_pos_x = int((root.winfo_screenwidth() / 2) - (app_width / 2)) start_pos_y = int((root.winfo_screenheight() / 2.5) - (app_height / 2)) root.title('LogViewer') -root.iconbitmap(os.path.join(os.getcwd(), path_to_icon)) +root.iconbitmap(path_to_icon) root.geometry('{0}x{1}+{2}+{3}'.format(app_width, app_height, start_pos_x, start_pos_y)) root.minsize(app_width, app_height) From d93535f7e791850638112ac0f00215287286071e Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 13 Dec 2017 07:30:47 +0300 Subject: [PATCH 09/25] Bind the button for start and stop watch the tail of file. --- main_form.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/main_form.py b/main_form.py index 8ceeafd..453415f 100644 --- a/main_form.py +++ b/main_form.py @@ -19,6 +19,7 @@ # объект вкладка class Tab: def __init__(self, main_space, file_path=''): + self.__end = 0 self.document = Tail(file_path) # создаем на вкладке объект документа, который читаем self.page = ttk.Frame(main_space) # объект вкладка self.tab_name = file_path.split('/')[-1] # имя вкладки, берем последнее значение после разделения по символу / @@ -33,11 +34,38 @@ def __init__(self, main_space, file_path=''): main_space.add(self.page, text='{}'.format(self.tab_name)) # добавляем вкладку + self.txt.bind('', self.__watch_tail) # при нажатии на кнопку END начинается просмотр последних данных + self.txt.bind('', self.__stop_watch_tail) # при 2-м клике останавливаем просмотр + self.txt.insert(tkinter.END, self.document.get_lines()) # вставляем текст из нашего документа + self.txt.config(state='disabled') # закрываем возможность редактировать + self.thread_show_last_string = threading.Thread(target=self.__shows_the_last_string, + daemon=True, + name='__watch_tail') # поток для просмотра последней строки def update_text(self): """Эта функция должна была обновлять текст на вкладке""" + self.txt.config(state='normal') self.txt.insert(tkinter.END, self.document.get_lines()) + self.txt.config(state='disabled') + + def __shows_the_last_string(self): + """На постоянке крутиться проверка для перехода к концу""" + while True: + while self.__end: + self.txt.see(tkinter.END) + time.sleep(1) + time.sleep(1) + + def __watch_tail(self, event): + """запуск потока для постоянного просмотра последнего файла""" + self.__end = 1 + if not self.thread_show_last_string.isAlive(): + self.thread_show_last_string.start() + + def __stop_watch_tail(self, event): + """останавливаем цикл, который постоянно мониторит последнюю строку""" + self.__end = 0 # диалоговое окно открытия файла, возвращает путь к файлу From bb3928379d0eb64bea45693c8f0cff13e492e058 Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 14 Dec 2017 00:29:36 +0300 Subject: [PATCH 10/25] Move class Tab to another file. Add class CustomNotebook. CustomNotebook add close button for tab. Add fillFile. This emulate regular record to file. --- custom_notebook.py | 91 ++++++++++++++++++++++++++++++++++++++++++++++ custom_tab.py | 56 ++++++++++++++++++++++++++++ fillFile.py | 46 +++++++++++++++++++++++ main_form.py | 63 +++----------------------------- 4 files changed, 199 insertions(+), 57 deletions(-) create mode 100644 custom_notebook.py create mode 100644 custom_tab.py create mode 100644 fillFile.py diff --git a/custom_notebook.py b/custom_notebook.py new file mode 100644 index 0000000..8e26275 --- /dev/null +++ b/custom_notebook.py @@ -0,0 +1,91 @@ +import tkinter +from tkinter import ttk + + +class CustomNotebook(ttk.Notebook): + """A ttk Notebook with close buttons on each tab""" + + __initialized = False + + def __init__(self, *args, **kwargs): + if not self.__initialized: + self.__initialize_custom_style() + self.__inititialized = True + + kwargs["style"] = "CustomNotebook" + ttk.Notebook.__init__(self, *args, **kwargs) + + self._active = None + + self.bind("", self.on_close_press, True) + self.bind("", self.on_close_release) + + def on_close_press(self, event): + """Called when the button is pressed over the close button""" + + element = self.identify(event.x, event.y) + + if "close" in element: + index = self.index("@%d,%d" % (event.x, event.y)) + self.state(['pressed']) + self._active = index + + def on_close_release(self, event): + """Called when the button is released over the close button""" + if not self.instate(['pressed']): + return + + element = self.identify(event.x, event.y) + index = self.index("@%d,%d" % (event.x, event.y)) + + if "close" in element and self._active == index: + self.forget(index) + self.event_generate("<>") + + self.state(["!pressed"]) + self._active = None + + def __initialize_custom_style(self): + style = ttk.Style() + self.images = ( + tkinter.PhotoImage("img_close", data=''' + R0lGODlhCAAIAMIBAAAAADs7O4+Pj9nZ2Ts7Ozs7Ozs7Ozs7OyH+EUNyZWF0ZWQg + d2l0aCBHSU1QACH5BAEKAAQALAAAAAAIAAgAAAMVGDBEA0qNJyGw7AmxmuaZhWEU + 5kEJADs= + '''), + tkinter.PhotoImage("img_closeactive", data=''' + R0lGODlhCAAIAMIEAAAAAP/SAP/bNNnZ2cbGxsbGxsbGxsbGxiH5BAEKAAQALAAA + AAAIAAgAAAMVGDBEA0qNJyGw7AmxmuaZhWEU5kEJADs= + '''), + tkinter.PhotoImage("img_closepressed", data=''' + R0lGODlhCAAIAMIEAAAAAOUqKv9mZtnZ2Ts7Ozs7Ozs7Ozs7OyH+EUNyZWF0ZWQg + d2l0aCBHSU1QACH5BAEKAAQALAAAAAAIAAgAAAMVGDBEA0qNJyGw7AmxmuaZhWEU + 5kEJADs= + ''') + ) + + style.element_create("close", "image", "img_close", + ("active", "pressed", "!disabled", "img_closepressed"), + ("active", "!disabled", "img_closeactive"), border=8, sticky='') + style.layout("CustomNotebook", [("CustomNotebook.client", {"sticky": "nswe"})]) + style.layout("CustomNotebook.Tab", [ + ("CustomNotebook.tab", { + "sticky": "nswe", + "children": [ + ("CustomNotebook.padding", { + "side": "top", + "sticky": "nswe", + "children": [ + ("CustomNotebook.focus", { + "side": "top", + "sticky": "nswe", + "children": [ + ("CustomNotebook.label", {"side": "left", "sticky": ''}), + ("CustomNotebook.close", {"side": "left", "sticky": ''}), + ] + }) + ] + }) + ] + }) + ]) \ No newline at end of file diff --git a/custom_tab.py b/custom_tab.py new file mode 100644 index 0000000..b6ffeab --- /dev/null +++ b/custom_tab.py @@ -0,0 +1,56 @@ +from loader import Tail +import tkinter +from tkinter import ttk +import threading +import time + + +class Tab: + def __init__(self, main_space, file_path=''): + self.__end = 0 + self.document = Tail(file_path) # создаем на вкладке объект документа, который читаем + self.page = ttk.Frame(main_space) # объект вкладка + self.tab_name = file_path.split('/')[-1] # имя вкладки, берем последнее значение после разделения по символу / + + self.scroll = tkinter.Scrollbar(self.page) # объект скролбарр на вкладку + self.txt = tkinter.Text(self.page, font="TextFont", yscrollcommand=self.scroll.set) # объект текстовое поле + + self.scroll.config(command=self.txt.yview) # прикрепляем скроллбар к текстовому полю + + self.txt.pack(side='left', fill='both', expand=True) # задаем размещение текстового поле + self.scroll.pack(side='right', fill=tkinter.Y) # задаем размещение скроллбара + + main_space.add(self.page, text='{}'.format(self.tab_name)) # добавляем вкладку + + self.txt.bind('', self.__watch_tail) # при нажатии на кнопку END начинается просмотр последних данных + self.txt.bind('', self.__stop_watch_tail) # при 2-м клике останавливаем просмотр + + self.txt.insert(tkinter.END, self.document.get_lines()) # вставляем текст из нашего документа + self.txt.config(state='disabled') # закрываем возможность редактировать + self.thread_show_last_string = threading.Thread(target=self.__shows_the_last_string, + daemon=True, + name='__watch_tail') # поток для просмотра последней строки + + def update_text(self): + """Эта функция должна была обновлять текст на вкладке""" + self.txt.config(state='normal') + self.txt.insert(tkinter.END, self.document.get_lines()) + self.txt.config(state='disabled') + + def __shows_the_last_string(self): + """На постоянке крутиться проверка для перехода к концу""" + while True: + while self.__end: + self.txt.see(tkinter.END) + time.sleep(1) + time.sleep(1) + + def __watch_tail(self, event): + """запуск потока для постоянного просмотра последнего файла""" + self.__end = 1 + if not self.thread_show_last_string.isAlive(): + self.thread_show_last_string.start() + + def __stop_watch_tail(self, event): + """останавливаем цикл, который постоянно мониторит последнюю строку""" + self.__end = 0 \ No newline at end of file diff --git a/fillFile.py b/fillFile.py new file mode 100644 index 0000000..f8e9064 --- /dev/null +++ b/fillFile.py @@ -0,0 +1,46 @@ +import time +import sys +import msvcrt +import threading +import os + +pressedKey = '' + + +def press_key(): + global pressedKey + while True: + pressedKey = msvcrt.getwch() + if pressedKey == 'q': + sys.exit() + time.sleep(0.5) + + +th = threading.Thread(target=press_key,name=2) + + +def fill_file(): + k = 1 + for count in range(11): + file_path = '{0}{1}{2}'.format(os.getcwd(), os.sep, 'test_{0}.log'.format(count)) + if not os.path.exists(r'{0}'.format(file_path)): + while True: + if pressedKey == 'q': + print('Stop the script') + sys.exit(0) + else: + with open('test_{0}.log'.format(count), 'a') as file: + file.writelines('Новая строка {} лога\n'.format(k)) + print('Новая строка {} лог\n'.format(k)) + k += 1 + time.sleep(1) + else: + pass + + +def starter(): + th.start() + fill_file() + + +starter() \ No newline at end of file diff --git a/main_form.py b/main_form.py index 453415f..78787f6 100644 --- a/main_form.py +++ b/main_form.py @@ -1,73 +1,21 @@ import tkinter from tkinter.filedialog import askopenfilename -from tkinter import ttk -from loader import Tail import time import threading import os +from custom_notebook import CustomNotebook +from custom_tab import Tab APP_WIDTH_WIN = 750 -APP_HEIGHT = 400 APP_WIDTH_LINUX = 825 +APP_HEIGHT = 400 # список всех вкладок list_of_tab = [] -# объект вкладка -class Tab: - def __init__(self, main_space, file_path=''): - self.__end = 0 - self.document = Tail(file_path) # создаем на вкладке объект документа, который читаем - self.page = ttk.Frame(main_space) # объект вкладка - self.tab_name = file_path.split('/')[-1] # имя вкладки, берем последнее значение после разделения по символу / - - self.scroll = tkinter.Scrollbar(self.page) # объект скролбарр на вкладку - self.txt = tkinter.Text(self.page, font="TextFont", yscrollcommand=self.scroll.set) # объект текстовое поле - - self.scroll.config(command=self.txt.yview) # прикрепляем скроллбар к текстовому полю - - self.txt.pack(side='left', fill='both', expand=True) # задаем размещение текстового поле - self.scroll.pack(side='right', fill=tkinter.Y) # задаем размещение скроллбара - - main_space.add(self.page, text='{}'.format(self.tab_name)) # добавляем вкладку - - self.txt.bind('', self.__watch_tail) # при нажатии на кнопку END начинается просмотр последних данных - self.txt.bind('', self.__stop_watch_tail) # при 2-м клике останавливаем просмотр - - self.txt.insert(tkinter.END, self.document.get_lines()) # вставляем текст из нашего документа - self.txt.config(state='disabled') # закрываем возможность редактировать - self.thread_show_last_string = threading.Thread(target=self.__shows_the_last_string, - daemon=True, - name='__watch_tail') # поток для просмотра последней строки - - def update_text(self): - """Эта функция должна была обновлять текст на вкладке""" - self.txt.config(state='normal') - self.txt.insert(tkinter.END, self.document.get_lines()) - self.txt.config(state='disabled') - - def __shows_the_last_string(self): - """На постоянке крутиться проверка для перехода к концу""" - while True: - while self.__end: - self.txt.see(tkinter.END) - time.sleep(1) - time.sleep(1) - - def __watch_tail(self, event): - """запуск потока для постоянного просмотра последнего файла""" - self.__end = 1 - if not self.thread_show_last_string.isAlive(): - self.thread_show_last_string.start() - - def __stop_watch_tail(self, event): - """останавливаем цикл, который постоянно мониторит последнюю строку""" - self.__end = 0 - - # диалоговое окно открытия файла, возвращает путь к файлу def path_to_file(): op = askopenfilename() @@ -115,11 +63,12 @@ def add_tab(): m.add_command(label="Open...", command=add_tab) # Defines and places the notebook widget -nb = ttk.Notebook(root) +nb = CustomNotebook(root) nb.pack(fill='both', expand='yes') # здесь заканчивается описание UI -#поток для обновления вкладок + +# поток для обновления вкладок thread_update_tabs = threading.Thread(target=update_tabs, daemon=True, name='update_tabs') thread_update_tabs.start() From df139ef252faf88d7a037d6515c99e8cf2f9035e Mon Sep 17 00:00:00 2001 From: nebyt Date: Fri, 15 Dec 2017 00:16:21 +0300 Subject: [PATCH 11/25] Added modal window. Show modal window when file is not text. --- main_form.py | 10 +++++++++- modal_window.py | 27 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 modal_window.py diff --git a/main_form.py b/main_form.py index 78787f6..ead8ed3 100644 --- a/main_form.py +++ b/main_form.py @@ -3,8 +3,10 @@ import time import threading import os +import mimetypes from custom_notebook import CustomNotebook from custom_tab import Tab +from modal_window import ModalWindow APP_WIDTH_WIN = 750 @@ -34,7 +36,13 @@ def update_tabs(): def add_tab(): file_path = path_to_file() if file_path: - list_of_tab.append(Tab(nb, file_path)) + type_of_file = mimetypes.guess_type(file_path) + type_of_file = type_of_file[0].split('/')[0] + if type_of_file == 'text': + list_of_tab.append(Tab(nb, file_path)) + else: + modal_window = ModalWindow() + modal_window.show() else: return diff --git a/modal_window.py b/modal_window.py new file mode 100644 index 0000000..f8dd381 --- /dev/null +++ b/modal_window.py @@ -0,0 +1,27 @@ +import tkinter +import os + + +class ModalWindow: + def __init__(self): + self.width = 200 + self.height = 100 + self.top = tkinter.Toplevel() + self.start_pos_x = int((self.top.winfo_screenwidth() / 2) - (self.width / 2)) + self.start_pos_y = int((self.top.winfo_screenheight() / 2.5) - (self.height / 2)) + self.top.title("Warning!") + self.top.geometry('{0}x{1}+{2}+{3}'.format(self.width, self.height, + self.start_pos_x, self.start_pos_y)) + self.top.maxsize(self.width, self.height) + self.top.resizable(0, 0) + if os.name == 'nt': + self.top.attributes('-toolwindow', 1) + + self.msg = tkinter.Message(self.top, text="This is does't text file!", justify='left', width=190) + self.msg.pack(side='top', fill='both', expand=True) + + self.button = tkinter.Button(self.top, text="Close", command=self.top.destroy) + self.button.pack(side='top', expand=True) + + def show(self): + self.top.mainloop() \ No newline at end of file From 58f443a5e9f42a38e9c01d33792d3bab2b477747 Mon Sep 17 00:00:00 2001 From: Denis_N Date: Fri, 15 Dec 2017 19:27:22 +0300 Subject: [PATCH 12/25] added recognize_codec function --- loader.py | 5 +++++ main_form.py | 5 +++-- modal_window.py | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/loader.py b/loader.py index 5a7479a..aac3c81 100644 --- a/loader.py +++ b/loader.py @@ -12,6 +12,11 @@ def __check_update(self): self.__last_change = os.stat(self.__path).st_mtime return self.__last_change + def __recognize_coding(self, path_to_file): + with open(r'{0}'.format(self.__path), 'rb') as file: + pass + pass + def get_lines(self): if self.__last_change <= self.__check_update(): with open(r'{0}'.format(self.__path), 'r') as file: diff --git a/main_form.py b/main_form.py index ead8ed3..c2dd598 100644 --- a/main_form.py +++ b/main_form.py @@ -37,8 +37,9 @@ def add_tab(): file_path = path_to_file() if file_path: type_of_file = mimetypes.guess_type(file_path) - type_of_file = type_of_file[0].split('/')[0] - if type_of_file == 'text': + if type_of_file[0]: + type_of_file = type_of_file[0].split('/')[0] + if type_of_file == 'text' or not type_of_file[0]: list_of_tab.append(Tab(nb, file_path)) else: modal_window = ModalWindow() diff --git a/modal_window.py b/modal_window.py index f8dd381..6210c03 100644 --- a/modal_window.py +++ b/modal_window.py @@ -17,7 +17,7 @@ def __init__(self): if os.name == 'nt': self.top.attributes('-toolwindow', 1) - self.msg = tkinter.Message(self.top, text="This is does't text file!", justify='left', width=190) + self.msg = tkinter.Message(self.top, text="This is not a text file!", justify='left', width=190) self.msg.pack(side='top', fill='both', expand=True) self.button = tkinter.Button(self.top, text="Close", command=self.top.destroy) From ee3b89d5588bc2e4db6ca5c91982ccd11c126408 Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 17 Dec 2017 13:27:17 +0300 Subject: [PATCH 13/25] Added recognition file format. Thanks http://patttern.blogspot.ru/2012/07/php-python.html --- fillFile.py | 4 +-- loader.py | 13 ++++--- main_form.py | 13 +++---- recognize_codec.py | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 13 deletions(-) create mode 100644 recognize_codec.py diff --git a/fillFile.py b/fillFile.py index f8e9064..fe03088 100644 --- a/fillFile.py +++ b/fillFile.py @@ -29,9 +29,9 @@ def fill_file(): print('Stop the script') sys.exit(0) else: - with open('test_{0}.log'.format(count), 'a') as file: + with open('test_{0}.log'.format(count), 'a', encoding='utf-8') as file: file.writelines('Новая строка {} лога\n'.format(k)) - print('Новая строка {} лог\n'.format(k)) + print('New string Новая строка {} лог\n'.format(k)) k += 1 time.sleep(1) else: diff --git a/loader.py b/loader.py index aac3c81..aeb4b04 100644 --- a/loader.py +++ b/loader.py @@ -1,4 +1,5 @@ import os +import recognize_codec class Tail: @@ -7,19 +8,21 @@ def __init__(self, path): self.__tail = 0 self.__last_change = 0 self.__log_content = '' + self.__fmt = '' def __check_update(self): self.__last_change = os.stat(self.__path).st_mtime return self.__last_change - def __recognize_coding(self, path_to_file): - with open(r'{0}'.format(self.__path), 'rb') as file: - pass - pass + def __recognize_format(self, path_to_file): + self.__fmt = recognize_codec.get_string_to_recognize(path_to_file) def get_lines(self): + print(self.__fmt) + if not self.__fmt: + self.__recognize_format(self.__path) if self.__last_change <= self.__check_update(): - with open(r'{0}'.format(self.__path), 'r') as file: + with open(r'{0}'.format(self.__path), 'r', encoding='{}'.format(self.__fmt)) as file: file.seek(self.__tail) self.__log_content = file.read() self.__tail = file.tell() diff --git a/main_form.py b/main_form.py index c2dd598..ee5f05a 100644 --- a/main_form.py +++ b/main_form.py @@ -60,12 +60,8 @@ def add_tab(): root = tkinter.Tk() app_height = APP_HEIGHT -start_pos_x = int((root.winfo_screenwidth() / 2) - (app_width / 2)) -start_pos_y = int((root.winfo_screenheight() / 2.5) - (app_height / 2)) -root.title('LogViewer') -root.iconbitmap(path_to_icon) -root.geometry('{0}x{1}+{2}+{3}'.format(app_width, app_height, start_pos_x, start_pos_y)) -root.minsize(app_width, app_height) +start_pos_x = root.winfo_screenwidth() - int((app_width / 2)) +start_pos_y = root.winfo_screenheight() - int((app_height / 2)) m = tkinter.Menu(root) root.config(menu=m) @@ -81,4 +77,9 @@ def add_tab(): thread_update_tabs = threading.Thread(target=update_tabs, daemon=True, name='update_tabs') thread_update_tabs.start() +root.title('LogViewer') +root.iconbitmap(path_to_icon) +root.geometry('{0}x{1}'.format(app_width, app_height)) +root.minsize(app_width, app_height) +root.geometry('+{0}+{1}'.format(start_pos_x, start_pos_y)) root.mainloop() # запуск отрисовки UI diff --git a/recognize_codec.py b/recognize_codec.py new file mode 100644 index 0000000..5001150 --- /dev/null +++ b/recognize_codec.py @@ -0,0 +1,87 @@ +__encodings = { + 'UTF-8': 'utf-8', + 'WIN-1251': 'windows-1251', + 'KOI8-R': 'koi8-r', + 'IBM866': 'ibm866', + 'ISO-8859-5': 'iso-8859-5', + 'MAC': 'mac', +} + +__string_massive = '' + +""" +Определение кодировки текста +""" + + +def __get_codepage(string=None): + uppercase = 1 + lowercase = 3 + utf_upper = 5 + utf_lower = 7 + code_pages = {} + for enc in __encodings.keys(): + code_pages[enc] = 0 + if string is not None and len(string) > 0: + last_simb = 0 + for simb in string: + simb_ord = simb + + """non-russian characters""" + if simb_ord < 128 or simb_ord > 256: + continue + + """UTF-8""" + if last_simb == 208 and (143 < simb_ord < 176 or simb_ord == 129): + code_pages['UTF-8'] += (utf_upper * 2) + if (last_simb == 208 and (simb_ord == 145 or 175 < simb_ord < 192)) \ + or (last_simb == 209 and (127 < simb_ord < 144)): + code_pages['UTF-8'] += (utf_lower * 2) + + """WIN-1251""" + if 223 < simb_ord < 256 or simb_ord == 184: + code_pages['WIN-1251'] += lowercase + if 191 < simb_ord < 224 or simb_ord == 168: + code_pages['WIN-1251'] += uppercase + + """KOI8-R""" + if 191 < simb_ord < 224 or simb_ord == 163: + code_pages['KOI8-R'] += lowercase + if 222 < simb_ord < 256 or simb_ord == 179: + code_pages['KOI8-R'] += uppercase + + """IBM866""" + if 159 < simb_ord < 176 or 223 < simb_ord < 241: + code_pages['IBM866'] += lowercase + if 127 < simb_ord < 160 or simb_ord == 241: + code_pages['IBM866'] += uppercase + + """ISO-8859-5""" + if 207 < simb_ord < 240 or simb_ord == 161: + code_pages['ISO-8859-5'] += lowercase + if 175 < simb_ord < 208 or simb_ord == 241: + code_pages['ISO-8859-5'] += uppercase + + """MAC""" + if 221 < simb_ord < 255: + code_pages['MAC'] += lowercase + if 127 < simb_ord < 160: + code_pages['MAC'] += uppercase + + last_simb = simb_ord + + idx = '' + maximum = 0 + for item in code_pages: + if code_pages[item] > maximum: + maximum = code_pages[item] + idx = item + if idx == 'WIN-1251': + idx = 'windows-1251' + return idx.lower() + + +def get_string_to_recognize(path): + with open(path, 'rb') as file: + string_massive = file.read(1000) + return __get_codepage(string_massive) From c0932f48e0c560e01b89411713bae1b911511b97 Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 17 Dec 2017 14:25:36 +0300 Subject: [PATCH 14/25] Little visual change --- custom_tab.py | 3 ++- loader.py | 2 +- main_form.py | 3 ++- modal_window.py | 11 +++++++---- recognize_codec.py | 6 +++--- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/custom_tab.py b/custom_tab.py index b6ffeab..be20939 100644 --- a/custom_tab.py +++ b/custom_tab.py @@ -13,7 +13,8 @@ def __init__(self, main_space, file_path=''): self.tab_name = file_path.split('/')[-1] # имя вкладки, берем последнее значение после разделения по символу / self.scroll = tkinter.Scrollbar(self.page) # объект скролбарр на вкладку - self.txt = tkinter.Text(self.page, font="TextFont", yscrollcommand=self.scroll.set) # объект текстовое поле + self.txt = tkinter.Text(self.page, font="TextFont", + spacing3=2, yscrollcommand=self.scroll.set) # объект текстовое поле self.scroll.config(command=self.txt.yview) # прикрепляем скроллбар к текстовому полю diff --git a/loader.py b/loader.py index aeb4b04..ca592ac 100644 --- a/loader.py +++ b/loader.py @@ -22,7 +22,7 @@ def get_lines(self): if not self.__fmt: self.__recognize_format(self.__path) if self.__last_change <= self.__check_update(): - with open(r'{0}'.format(self.__path), 'r', encoding='{}'.format(self.__fmt)) as file: + with open(r'{0}'.format(self.__path), 'r', encoding='{}'.format(self.__fmt), errors='replace') as file: file.seek(self.__tail) self.__log_content = file.read() self.__tail = file.tell() diff --git a/main_form.py b/main_form.py index ee5f05a..9d151d5 100644 --- a/main_form.py +++ b/main_form.py @@ -42,7 +42,8 @@ def add_tab(): if type_of_file == 'text' or not type_of_file[0]: list_of_tab.append(Tab(nb, file_path)) else: - modal_window = ModalWindow() + file_name = file_path.split('/')[-1] + modal_window = ModalWindow(file_name) modal_window.show() else: return diff --git a/modal_window.py b/modal_window.py index 6210c03..5084fc6 100644 --- a/modal_window.py +++ b/modal_window.py @@ -3,10 +3,11 @@ class ModalWindow: - def __init__(self): + def __init__(self, file_name): + self.__file_name = file_name self.width = 200 self.height = 100 - self.top = tkinter.Toplevel() + self.top = tkinter.Toplevel(padx=1, pady=1) self.start_pos_x = int((self.top.winfo_screenwidth() / 2) - (self.width / 2)) self.start_pos_y = int((self.top.winfo_screenheight() / 2.5) - (self.height / 2)) self.top.title("Warning!") @@ -17,11 +18,13 @@ def __init__(self): if os.name == 'nt': self.top.attributes('-toolwindow', 1) - self.msg = tkinter.Message(self.top, text="This is not a text file!", justify='left', width=190) + self.msg = tkinter.Message(self.top, text="{0}\n is not a text file!".format(self.__file_name), + justify='left', width=190, font='Arial 12') self.msg.pack(side='top', fill='both', expand=True) self.button = tkinter.Button(self.top, text="Close", command=self.top.destroy) self.button.pack(side='top', expand=True) def show(self): - self.top.mainloop() \ No newline at end of file + self.top.focus_set() + self.top.mainloop() diff --git a/recognize_codec.py b/recognize_codec.py index 5001150..0f80372 100644 --- a/recognize_codec.py +++ b/recognize_codec.py @@ -7,8 +7,6 @@ 'MAC': 'mac', } -__string_massive = '' - """ Определение кодировки текста """ @@ -78,10 +76,12 @@ def __get_codepage(string=None): idx = item if idx == 'WIN-1251': idx = 'windows-1251' + if not maximum: + idx = 'ASCII' return idx.lower() def get_string_to_recognize(path): with open(path, 'rb') as file: - string_massive = file.read(1000) + string_massive = file.read(25000) return __get_codepage(string_massive) From 872589c6c1a23d8d2b1f377a756a8b30a5f7b4c1 Mon Sep 17 00:00:00 2001 From: nebyt Date: Mon, 18 Dec 2017 00:23:49 +0300 Subject: [PATCH 15/25] Added skeleton of the save module. --- custom_tab.py | 1 + main_form.py | 33 +++++++++++++++++++++++++++------ saver.py | 16 ++++++++++++++++ 3 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 saver.py diff --git a/custom_tab.py b/custom_tab.py index be20939..6552f91 100644 --- a/custom_tab.py +++ b/custom_tab.py @@ -7,6 +7,7 @@ class Tab: def __init__(self, main_space, file_path=''): + self.path_to_file = file_path self.__end = 0 self.document = Tail(file_path) # создаем на вкладке объект документа, который читаем self.page = ttk.Frame(main_space) # объект вкладка diff --git a/main_form.py b/main_form.py index 9d151d5..7b83320 100644 --- a/main_form.py +++ b/main_form.py @@ -1,5 +1,6 @@ import tkinter from tkinter.filedialog import askopenfilename +from tkinter.filedialog import asksaveasfilename, asksaveasfile import time import threading import os @@ -16,14 +17,26 @@ # список всех вкладок list_of_tab = [] +paths = [] # диалоговое окно открытия файла, возвращает путь к файлу def path_to_file(): - op = askopenfilename() + op = askopenfilename(defaultextension='.log', + filetypes=(("Log files", ".log"), + ("Text files", ".txt"), + ("All files", ".*"))) return op +def save_file(): + pass + + +def save_all_file(tabs=list_of_tab): + pass + + # обновление информации на всех вкладках def update_tabs(): while True: @@ -61,12 +74,20 @@ def add_tab(): root = tkinter.Tk() app_height = APP_HEIGHT -start_pos_x = root.winfo_screenwidth() - int((app_width / 2)) -start_pos_y = root.winfo_screenheight() - int((app_height / 2)) +start_pos_x = int(root.winfo_screenwidth() / 2) - int((app_width / 2)) +start_pos_y = int(root.winfo_screenheight() / 2.5) - int((app_height / 2)) + +menubar = tkinter.Menu(root) +save_button = tkinter.Menu(root) + +root.config(menu=menubar) +menubar.add_command(label="Open..", command=add_tab) +save_menu = tkinter.Menu(menubar) -m = tkinter.Menu(root) -root.config(menu=m) -m.add_command(label="Open...", command=add_tab) +save_menu.add_command(label='Save active', command=save_file) +save_menu.add_command(label='Save all...', command=save_all_file()) +save_menu.add_separator() +menubar.add_cascade(label='Save..', menu=save_menu) # Defines and places the notebook widget nb = CustomNotebook(root) diff --git a/saver.py b/saver.py new file mode 100644 index 0000000..4d0f0e9 --- /dev/null +++ b/saver.py @@ -0,0 +1,16 @@ +import zipfile +from tkinter.filedialog import asksaveasfile, asksaveasfilename + + +class Saver: + def __init__(self, all_tabs): + self.tabs_paths = [] + for tab in all_tabs: + self.tabs_paths.append(tab.path_to_file) + self.path_to_save = asksaveasfilename(defaultextension='.zip',filetypes=("ZIP file", ".zip")) + + def save_all(self): + pass + + def save_one(self): + pass From 9f0652e9077cf3ce65fad9869650bb1c2de1ad8d Mon Sep 17 00:00:00 2001 From: nebyt Date: Tue, 19 Dec 2017 01:46:12 +0300 Subject: [PATCH 16/25] Added save module. --- main_form.py | 15 +++++++++------ saver.py | 33 ++++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/main_form.py b/main_form.py index 7b83320..1ec84fb 100644 --- a/main_form.py +++ b/main_form.py @@ -1,6 +1,5 @@ import tkinter from tkinter.filedialog import askopenfilename -from tkinter.filedialog import asksaveasfilename, asksaveasfile import time import threading import os @@ -8,6 +7,7 @@ from custom_notebook import CustomNotebook from custom_tab import Tab from modal_window import ModalWindow +from saver import Saver APP_WIDTH_WIN = 750 @@ -17,7 +17,6 @@ # список всех вкладок list_of_tab = [] -paths = [] # диалоговое окно открытия файла, возвращает путь к файлу @@ -29,12 +28,16 @@ def path_to_file(): return op -def save_file(): - pass +def save_file(tabs=list_of_tab): + tab_name = nb.tab(nb.select(), 'text') + saver = Saver(tabs, tab_name) + saver.save_one() + def save_all_file(tabs=list_of_tab): - pass + saver = Saver(tabs) + saver.save_all() # обновление информации на всех вкладках @@ -85,7 +88,7 @@ def add_tab(): save_menu = tkinter.Menu(menubar) save_menu.add_command(label='Save active', command=save_file) -save_menu.add_command(label='Save all...', command=save_all_file()) +save_menu.add_command(label='Save all...', command=save_all_file) save_menu.add_separator() menubar.add_cascade(label='Save..', menu=save_menu) diff --git a/saver.py b/saver.py index 4d0f0e9..6cb77ad 100644 --- a/saver.py +++ b/saver.py @@ -1,16 +1,39 @@ import zipfile from tkinter.filedialog import asksaveasfile, asksaveasfilename +from os.path import basename +from datetime import datetime class Saver: - def __init__(self, all_tabs): + def __init__(self, all_tabs, tab_name=''): self.tabs_paths = [] - for tab in all_tabs: + self.tab_name = tab_name + self.all_tabs = all_tabs + self.original_path = '' + for tab in self.all_tabs: self.tabs_paths.append(tab.path_to_file) - self.path_to_save = asksaveasfilename(defaultextension='.zip',filetypes=("ZIP file", ".zip")) + self.path_to_save = '' def save_all(self): - pass + current_moment = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + print(current_moment) + self.path_to_save = asksaveasfilename(title='Save archive', initialfile='{}.zip'.format(current_moment), + filetypes=(("ZIP File", "*.zip"), ("All files", "*.*"))) + #TODO added try except to empty path + with zipfile.ZipFile('{}'.format(self.path_to_save), 'a') as my_zip: + for path_file in self.tabs_paths: + my_zip.write(basename(path_file)) def save_one(self): - pass + for tab in self.all_tabs: + if tab.tab_name == self.tab_name: + self.original_path = tab.path_to_file + self.path_to_save = asksaveasfilename(title='Save file', + initialfile='{}'.format(self.tab_name), + filetypes=(("Log File", "*.log"), + ("Text File", "*.txt"), + ("All files", "*.*"))) + # TODO added try except to empty path + with open('{}'.format(self.path_to_save), 'a') as save_file: + save_file.write(self.original_path) + From 9ad9dc4e8d21ef1122d7f5f20df3e014c0a840f1 Mon Sep 17 00:00:00 2001 From: Denis Date: Tue, 19 Dec 2017 23:46:13 +0300 Subject: [PATCH 17/25] Little visual change --- custom_tab.py | 7 ++++- fillFile.py => fill_file_utilite/fillFile.py | 13 ++++---- saver.py | 33 +++++++++++++------- 3 files changed, 34 insertions(+), 19 deletions(-) rename fillFile.py => fill_file_utilite/fillFile.py (69%) diff --git a/custom_tab.py b/custom_tab.py index 6552f91..d070b26 100644 --- a/custom_tab.py +++ b/custom_tab.py @@ -9,6 +9,7 @@ class Tab: def __init__(self, main_space, file_path=''): self.path_to_file = file_path self.__end = 0 + self.all_visible_text = '' self.document = Tail(file_path) # создаем на вкладке объект документа, который читаем self.page = ttk.Frame(main_space) # объект вкладка self.tab_name = file_path.split('/')[-1] # имя вкладки, берем последнее значение после разделения по символу / @@ -55,4 +56,8 @@ def __watch_tail(self, event): def __stop_watch_tail(self, event): """останавливаем цикл, который постоянно мониторит последнюю строку""" - self.__end = 0 \ No newline at end of file + self.__end = 0 + + def get_all_text(self): + self.all_visible_text = self.txt.get(1.0, tkinter.END) + return self.all_visible_text \ No newline at end of file diff --git a/fillFile.py b/fill_file_utilite/fillFile.py similarity index 69% rename from fillFile.py rename to fill_file_utilite/fillFile.py index fe03088..f9fb0b2 100644 --- a/fillFile.py +++ b/fill_file_utilite/fillFile.py @@ -4,14 +4,13 @@ import threading import os -pressedKey = '' +pressed_key = '' def press_key(): - global pressedKey while True: - pressedKey = msvcrt.getwch() - if pressedKey == 'q': + pressed_key = msvcrt.getwch() + if pressed_key == 'q': sys.exit() time.sleep(0.5) @@ -25,12 +24,12 @@ def fill_file(): file_path = '{0}{1}{2}'.format(os.getcwd(), os.sep, 'test_{0}.log'.format(count)) if not os.path.exists(r'{0}'.format(file_path)): while True: - if pressedKey == 'q': + if pressed_key == 'q': print('Stop the script') sys.exit(0) else: - with open('test_{0}.log'.format(count), 'a', encoding='utf-8') as file: - file.writelines('Новая строка {} лога\n'.format(k)) + with open('test_{0}.log'.format(count), 'a') as file: + file.writelines('New string Новая строка {} лога\n'.format(k)) print('New string Новая строка {} лог\n'.format(k)) k += 1 time.sleep(1) diff --git a/saver.py b/saver.py index 6cb77ad..03a6b94 100644 --- a/saver.py +++ b/saver.py @@ -1,5 +1,7 @@ import zipfile -from tkinter.filedialog import asksaveasfile, asksaveasfilename +import os +from shutil import copy +from tkinter.filedialog import asksaveasfilename from os.path import basename from datetime import datetime @@ -10,19 +12,27 @@ def __init__(self, all_tabs, tab_name=''): self.tab_name = tab_name self.all_tabs = all_tabs self.original_path = '' + self.current_tab_text = '' for tab in self.all_tabs: self.tabs_paths.append(tab.path_to_file) self.path_to_save = '' def save_all(self): - current_moment = datetime.now().strftime('%Y-%m-%d %H:%M:%S') - print(current_moment) + current_moment = datetime.now().strftime('%Y%m%d_%H%M%S') self.path_to_save = asksaveasfilename(title='Save archive', initialfile='{}.zip'.format(current_moment), filetypes=(("ZIP File", "*.zip"), ("All files", "*.*"))) - #TODO added try except to empty path - with zipfile.ZipFile('{}'.format(self.path_to_save), 'a') as my_zip: - for path_file in self.tabs_paths: - my_zip.write(basename(path_file)) + if self.path_to_save: + with zipfile.ZipFile('{}'.format(self.path_to_save), 'a', + compression=zipfile.ZIP_STORED, allowZip64=True) as my_zip: + for tab in self.all_tabs: + self.current_tab_text = tab.get_all_text() + tmp_file = basename(tab.path_to_file) + with open(tmp_file, 'w') as file: + file.write(self.current_tab_text) + my_zip.write(tmp_file) + os.remove(tmp_file) + else: + return def save_one(self): for tab in self.all_tabs: @@ -33,7 +43,8 @@ def save_one(self): filetypes=(("Log File", "*.log"), ("Text File", "*.txt"), ("All files", "*.*"))) - # TODO added try except to empty path - with open('{}'.format(self.path_to_save), 'a') as save_file: - save_file.write(self.original_path) - + print(self.path_to_save) + if self.path_to_save: + copy(self.original_path, self.path_to_save) + else: + return From dd61773c3f702dcb8d4b035354f7a2cd999be2c9 Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 20 Dec 2017 00:00:26 +0300 Subject: [PATCH 18/25] Changed save module --- saver.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/saver.py b/saver.py index 03a6b94..38dcbed 100644 --- a/saver.py +++ b/saver.py @@ -37,14 +37,15 @@ def save_all(self): def save_one(self): for tab in self.all_tabs: if tab.tab_name == self.tab_name: - self.original_path = tab.path_to_file - self.path_to_save = asksaveasfilename(title='Save file', - initialfile='{}'.format(self.tab_name), - filetypes=(("Log File", "*.log"), - ("Text File", "*.txt"), - ("All files", "*.*"))) - print(self.path_to_save) - if self.path_to_save: - copy(self.original_path, self.path_to_save) - else: - return + self.current_tab_text = tab.get_all_text() + tmp_file = basename(tab.path_to_file) + self.path_to_save = asksaveasfilename(title='Save file', + initialfile='{}'.format(self.tab_name), + filetypes=(("Log File", "*.log"), + ("Text File", "*.txt"), + ("All files", "*.*"))) + if self.path_to_save: + with open(tmp_file, 'w') as file: + file.write(self.current_tab_text) + else: + return From 4114f76f28a8fc184168b6c1a38374378d4c42d8 Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 20 Dec 2017 20:00:19 +0300 Subject: [PATCH 19/25] Organized files by folders --- custom_notebook.py => UI_modules/custom_notebook.py | 0 custom_tab.py => UI_modules/custom_tab.py | 2 +- modal_window.py => UI_modules/modal_window.py | 0 icon.ico => icons/icon.ico | Bin main_form.py | 9 ++++----- loader.py => modules/loader.py | 12 ++---------- recognize_codec.py => modules/recognize_codec.py | 0 saver.py => modules/saver.py | 1 - 8 files changed, 7 insertions(+), 17 deletions(-) rename custom_notebook.py => UI_modules/custom_notebook.py (100%) rename custom_tab.py => UI_modules/custom_tab.py (99%) rename modal_window.py => UI_modules/modal_window.py (100%) rename icon.ico => icons/icon.ico (100%) rename loader.py => modules/loader.py (71%) rename recognize_codec.py => modules/recognize_codec.py (100%) rename saver.py => modules/saver.py (98%) diff --git a/custom_notebook.py b/UI_modules/custom_notebook.py similarity index 100% rename from custom_notebook.py rename to UI_modules/custom_notebook.py diff --git a/custom_tab.py b/UI_modules/custom_tab.py similarity index 99% rename from custom_tab.py rename to UI_modules/custom_tab.py index d070b26..9755038 100644 --- a/custom_tab.py +++ b/UI_modules/custom_tab.py @@ -1,4 +1,4 @@ -from loader import Tail +from modules.loader import Tail import tkinter from tkinter import ttk import threading diff --git a/modal_window.py b/UI_modules/modal_window.py similarity index 100% rename from modal_window.py rename to UI_modules/modal_window.py diff --git a/icon.ico b/icons/icon.ico similarity index 100% rename from icon.ico rename to icons/icon.ico diff --git a/main_form.py b/main_form.py index 1ec84fb..5c062c3 100644 --- a/main_form.py +++ b/main_form.py @@ -4,10 +4,10 @@ import threading import os import mimetypes -from custom_notebook import CustomNotebook -from custom_tab import Tab -from modal_window import ModalWindow -from saver import Saver +from UI_modules.custom_notebook import CustomNotebook +from UI_modules.custom_tab import Tab +from UI_modules.modal_window import ModalWindow +from modules.saver import Saver APP_WIDTH_WIN = 750 @@ -34,7 +34,6 @@ def save_file(tabs=list_of_tab): saver.save_one() - def save_all_file(tabs=list_of_tab): saver = Saver(tabs) saver.save_all() diff --git a/loader.py b/modules/loader.py similarity index 71% rename from loader.py rename to modules/loader.py index ca592ac..99ae16f 100644 --- a/loader.py +++ b/modules/loader.py @@ -1,5 +1,5 @@ import os -import recognize_codec +import modules.recognize_codec as codec class Tail: @@ -15,10 +15,9 @@ def __check_update(self): return self.__last_change def __recognize_format(self, path_to_file): - self.__fmt = recognize_codec.get_string_to_recognize(path_to_file) + self.__fmt = codec.get_string_to_recognize(path_to_file) def get_lines(self): - print(self.__fmt) if not self.__fmt: self.__recognize_format(self.__path) if self.__last_change <= self.__check_update(): @@ -28,10 +27,3 @@ def get_lines(self): self.__tail = file.tell() return self.__log_content - -if __name__ == '__main__': - import time - test_file = Tail(r'C:\Users\Denis\PycharmProjects\pyLogViewer\test.log') - for k in range(60): - print(test_file.get_lines()) - time.sleep(1) diff --git a/recognize_codec.py b/modules/recognize_codec.py similarity index 100% rename from recognize_codec.py rename to modules/recognize_codec.py diff --git a/saver.py b/modules/saver.py similarity index 98% rename from saver.py rename to modules/saver.py index 38dcbed..94c566c 100644 --- a/saver.py +++ b/modules/saver.py @@ -1,6 +1,5 @@ import zipfile import os -from shutil import copy from tkinter.filedialog import asksaveasfilename from os.path import basename from datetime import datetime From 9245c1a832de379e19941d98aeb9ce6c32a583c5 Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Dec 2017 01:36:12 +0300 Subject: [PATCH 20/25] Organized files by folders --- UI_modules/custom_notebook.py | 6 ++++-- UI_modules/custom_tab.py | 2 +- main_form.py | 11 +++++++---- modules/list_of_tab.py | 15 +++++++++++++++ 4 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 modules/list_of_tab.py diff --git a/UI_modules/custom_notebook.py b/UI_modules/custom_notebook.py index 8e26275..fe9aa41 100644 --- a/UI_modules/custom_notebook.py +++ b/UI_modules/custom_notebook.py @@ -1,5 +1,6 @@ import tkinter from tkinter import ttk +from modules.list_of_tab import list_of_tab class CustomNotebook(ttk.Notebook): @@ -10,7 +11,7 @@ class CustomNotebook(ttk.Notebook): def __init__(self, *args, **kwargs): if not self.__initialized: self.__initialize_custom_style() - self.__inititialized = True + self.__initialized = True kwargs["style"] = "CustomNotebook" ttk.Notebook.__init__(self, *args, **kwargs) @@ -37,7 +38,8 @@ def on_close_release(self, event): element = self.identify(event.x, event.y) index = self.index("@%d,%d" % (event.x, event.y)) - + print(self.tab(index, "text")) # получаем имя вкладки которую закрываем + # проверять по имени вкладки if "close" in element and self._active == index: self.forget(index) self.event_generate("<>") diff --git a/UI_modules/custom_tab.py b/UI_modules/custom_tab.py index 9755038..9bc737c 100644 --- a/UI_modules/custom_tab.py +++ b/UI_modules/custom_tab.py @@ -60,4 +60,4 @@ def __stop_watch_tail(self, event): def get_all_text(self): self.all_visible_text = self.txt.get(1.0, tkinter.END) - return self.all_visible_text \ No newline at end of file + return self.all_visible_text diff --git a/main_form.py b/main_form.py index 5c062c3..024806d 100644 --- a/main_form.py +++ b/main_form.py @@ -8,6 +8,7 @@ from UI_modules.custom_tab import Tab from UI_modules.modal_window import ModalWindow from modules.saver import Saver +from modules.list_of_tab import list_of_tab APP_WIDTH_WIN = 750 @@ -16,7 +17,7 @@ # список всех вкладок -list_of_tab = [] +list_of_tab = list_of_tab # диалоговое окно открытия файла, возвращает путь к файлу @@ -42,7 +43,7 @@ def save_all_file(tabs=list_of_tab): # обновление информации на всех вкладках def update_tabs(): while True: - for line in list_of_tab: + for line in list_of_tab.get_all_tab(): line.update_text() time.sleep(1) @@ -52,10 +53,12 @@ def add_tab(): file_path = path_to_file() if file_path: type_of_file = mimetypes.guess_type(file_path) + if type_of_file[0]: type_of_file = type_of_file[0].split('/')[0] + if type_of_file == 'text' or not type_of_file[0]: - list_of_tab.append(Tab(nb, file_path)) + list_of_tab.add_tab(Tab(nb, file_path)) else: file_name = file_path.split('/')[-1] modal_window = ModalWindow(file_name) @@ -69,7 +72,7 @@ def add_tab(): path_to_icon = '' else: app_width = APP_WIDTH_WIN - path_to_icon = 'icon.ico' + path_to_icon = 'icons\icon.ico' path_to_icon = os.path.join(os.getcwd(), path_to_icon) # здесь начинается описание UI diff --git a/modules/list_of_tab.py b/modules/list_of_tab.py new file mode 100644 index 0000000..ff6d96b --- /dev/null +++ b/modules/list_of_tab.py @@ -0,0 +1,15 @@ +class ListOfTab: + def __init__(self): + self.__list_of_tab = [] + + def add_tab(self, tab): + self.__list_of_tab.append(tab) + + def remove_tab(self, tab): + self.__list_of_tab.remove(tab) + + def get_all_tab(self): + return self.__list_of_tab + + +list_of_tab = ListOfTab() From 351286fc021d29fea8c72e6f579de75a44b6b1e0 Mon Sep 17 00:00:00 2001 From: Denis Date: Fri, 22 Dec 2017 01:16:31 +0300 Subject: [PATCH 21/25] Fix the save module. Now then tab is closed, it delete from list of tabs. --- UI_modules/custom_notebook.py | 9 +++++++-- UI_modules/custom_tab.py | 14 +++++++++++++- main_form.py | 4 ++-- modules/saver.py | 14 ++++++++------ 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/UI_modules/custom_notebook.py b/UI_modules/custom_notebook.py index fe9aa41..2e927ff 100644 --- a/UI_modules/custom_notebook.py +++ b/UI_modules/custom_notebook.py @@ -38,8 +38,8 @@ def on_close_release(self, event): element = self.identify(event.x, event.y) index = self.index("@%d,%d" % (event.x, event.y)) - print(self.tab(index, "text")) # получаем имя вкладки которую закрываем - # проверять по имени вкладки + tab_name_for_delete = self.tab(index, "text") # get name of closed tab + if "close" in element and self._active == index: self.forget(index) self.event_generate("<>") @@ -47,6 +47,11 @@ def on_close_release(self, event): self.state(["!pressed"]) self._active = None + for tab in list_of_tab.get_all_tab(): + if tab.tab_name == tab_name_for_delete: + list_of_tab.remove_tab(tab) + break + def __initialize_custom_style(self): style = ttk.Style() self.images = ( diff --git a/UI_modules/custom_tab.py b/UI_modules/custom_tab.py index 9bc737c..8a449f1 100644 --- a/UI_modules/custom_tab.py +++ b/UI_modules/custom_tab.py @@ -3,6 +3,7 @@ from tkinter import ttk import threading import time +from modules.list_of_tab import list_of_tab class Tab: @@ -12,8 +13,9 @@ def __init__(self, main_space, file_path=''): self.all_visible_text = '' self.document = Tail(file_path) # создаем на вкладке объект документа, который читаем self.page = ttk.Frame(main_space) # объект вкладка - self.tab_name = file_path.split('/')[-1] # имя вкладки, берем последнее значение после разделения по символу / + self.__tab_name_expect = file_path.split('/')[-1] # имя вкладки, берем последнее значение после разделения по символу / + self.tab_name = self.__set_tab_name(self.__tab_name_expect) self.scroll = tkinter.Scrollbar(self.page) # объект скролбарр на вкладку self.txt = tkinter.Text(self.page, font="TextFont", spacing3=2, yscrollcommand=self.scroll.set) # объект текстовое поле @@ -34,6 +36,16 @@ def __init__(self, main_space, file_path=''): daemon=True, name='__watch_tail') # поток для просмотра последней строки + def __set_tab_name(self, tab_name_expect): + self.__name, self.__file_fmt = tab_name_expect.split('.') + self.__all_tabs = list_of_tab.get_all_tab() + self.__count = 1 + for tab in self.__all_tabs: + if tab.tab_name == tab_name_expect: + tab_name_expect = '{0}({1}).{2}'.format(self.__name, self.__count, self.__file_fmt) + self.__count += 1 + return tab_name_expect + def update_text(self): """Эта функция должна была обновлять текст на вкладке""" self.txt.config(state='normal') diff --git a/main_form.py b/main_form.py index 024806d..766a612 100644 --- a/main_form.py +++ b/main_form.py @@ -29,13 +29,13 @@ def path_to_file(): return op -def save_file(tabs=list_of_tab): +def save_file(tabs=list_of_tab.get_all_tab()): tab_name = nb.tab(nb.select(), 'text') saver = Saver(tabs, tab_name) saver.save_one() -def save_all_file(tabs=list_of_tab): +def save_all_file(tabs=list_of_tab.get_all_tab()): saver = Saver(tabs) saver.save_all() diff --git a/modules/saver.py b/modules/saver.py index 94c566c..31b5368 100644 --- a/modules/saver.py +++ b/modules/saver.py @@ -1,7 +1,6 @@ import zipfile import os from tkinter.filedialog import asksaveasfilename -from os.path import basename from datetime import datetime @@ -17,15 +16,18 @@ def __init__(self, all_tabs, tab_name=''): self.path_to_save = '' def save_all(self): + # get current time current_moment = datetime.now().strftime('%Y%m%d_%H%M%S') + # set the save path self.path_to_save = asksaveasfilename(title='Save archive', initialfile='{}.zip'.format(current_moment), filetypes=(("ZIP File", "*.zip"), ("All files", "*.*"))) if self.path_to_save: - with zipfile.ZipFile('{}'.format(self.path_to_save), 'a', - compression=zipfile.ZIP_STORED, allowZip64=True) as my_zip: + with zipfile.ZipFile('{}'.format(self.path_to_save),'a', + compression=zipfile.ZIP_STORED, + allowZip64=True) as my_zip: for tab in self.all_tabs: self.current_tab_text = tab.get_all_text() - tmp_file = basename(tab.path_to_file) + tmp_file = tab.tab_name with open(tmp_file, 'w') as file: file.write(self.current_tab_text) my_zip.write(tmp_file) @@ -37,9 +39,9 @@ def save_one(self): for tab in self.all_tabs: if tab.tab_name == self.tab_name: self.current_tab_text = tab.get_all_text() - tmp_file = basename(tab.path_to_file) + tmp_file = tab.tab_name self.path_to_save = asksaveasfilename(title='Save file', - initialfile='{}'.format(self.tab_name), + initialfile='{}'.format(tmp_file), filetypes=(("Log File", "*.log"), ("Text File", "*.txt"), ("All files", "*.*"))) From 95c9fbdff7bd9adcaa1f0e4714774750c05d8556 Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 24 Dec 2017 23:24:31 +0300 Subject: [PATCH 22/25] Added random choice from file 'dict.txt'. --- fill_file_utilite/dict.txt | 14 ++++++++++++++ fill_file_utilite/fillFile.py | 12 ++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 fill_file_utilite/dict.txt diff --git a/fill_file_utilite/dict.txt b/fill_file_utilite/dict.txt new file mode 100644 index 0000000..fe12ef6 --- /dev/null +++ b/fill_file_utilite/dict.txt @@ -0,0 +1,14 @@ +error +Error +warn +Warning +INFO +info +Info +DEBUG +Debug +Left +Right +Up +AND +Down \ No newline at end of file diff --git a/fill_file_utilite/fillFile.py b/fill_file_utilite/fillFile.py index f9fb0b2..d9d163c 100644 --- a/fill_file_utilite/fillFile.py +++ b/fill_file_utilite/fillFile.py @@ -3,6 +3,7 @@ import msvcrt import threading import os +import random pressed_key = '' @@ -20,6 +21,9 @@ def press_key(): def fill_file(): k = 1 + words: list + with open('dict.txt', 'r') as dictionary: + words = dictionary.read().split('\n') for count in range(11): file_path = '{0}{1}{2}'.format(os.getcwd(), os.sep, 'test_{0}.log'.format(count)) if not os.path.exists(r'{0}'.format(file_path)): @@ -29,8 +33,12 @@ def fill_file(): sys.exit(0) else: with open('test_{0}.log'.format(count), 'a') as file: - file.writelines('New string Новая строка {} лога\n'.format(k)) - print('New string Новая строка {} лог\n'.format(k)) + file.writelines('New string {0} {1} Новая строка {0} {2}\n'.format(k, + random.choice(words), + random.choice(words))) + print('New string {0} {1} Новая строка {0} {2}\n'.format(k, + random.choice(words), + random.choice(words))) k += 1 time.sleep(1) else: From fef17e7fca3863343f1304e7fa97ca30bdb09a9b Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 24 Dec 2017 23:27:16 +0300 Subject: [PATCH 23/25] If the file was not changed , the programm does not read the file --- modules/loader.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/loader.py b/modules/loader.py index 99ae16f..3a843de 100644 --- a/modules/loader.py +++ b/modules/loader.py @@ -20,10 +20,13 @@ def __recognize_format(self, path_to_file): def get_lines(self): if not self.__fmt: self.__recognize_format(self.__path) - if self.__last_change <= self.__check_update(): + if self.__last_change < self.__check_update(): with open(r'{0}'.format(self.__path), 'r', encoding='{}'.format(self.__fmt), errors='replace') as file: file.seek(self.__tail) self.__log_content = file.read() self.__tail = file.tell() - return self.__log_content + return self.__log_content + else: + self.__log_content = '' + return self.__log_content From d923a4359f2ee832ba38ce89260f3e2c30a40075 Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 24 Dec 2017 23:42:01 +0300 Subject: [PATCH 24/25] Highlight the word 'error'. --- UI_modules/custom_tab.py | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/UI_modules/custom_tab.py b/UI_modules/custom_tab.py index 8a449f1..6e91eb5 100644 --- a/UI_modules/custom_tab.py +++ b/UI_modules/custom_tab.py @@ -10,21 +10,24 @@ class Tab: def __init__(self, main_space, file_path=''): self.path_to_file = file_path self.__end = 0 + self.search_index = '1.0' self.all_visible_text = '' self.document = Tail(file_path) # создаем на вкладке объект документа, который читаем self.page = ttk.Frame(main_space) # объект вкладка self.__tab_name_expect = file_path.split('/')[-1] # имя вкладки, берем последнее значение после разделения по символу / self.tab_name = self.__set_tab_name(self.__tab_name_expect) - self.scroll = tkinter.Scrollbar(self.page) # объект скролбарр на вкладку - self.txt = tkinter.Text(self.page, font="TextFont", - spacing3=2, yscrollcommand=self.scroll.set) # объект текстовое поле + self.txt = tkinter.Text(self.page, font="TextFont", spacing3=2) # объект текстовое поле + self.scroll = tkinter.Scrollbar(self.txt) # объект скролбарр на вкладку + self.txt.config(yscrollcommand=self.scroll.set) self.scroll.config(command=self.txt.yview) # прикрепляем скроллбар к текстовому полю - self.txt.pack(side='left', fill='both', expand=True) # задаем размещение текстового поле + self.txt.pack(side='top', fill='both', expand=True) # задаем размещение текстового поле self.scroll.pack(side='right', fill=tkinter.Y) # задаем размещение скроллбара + self.txt.tag_config("red", background="red", foreground="white") + main_space.add(self.page, text='{}'.format(self.tab_name)) # добавляем вкладку self.txt.bind('', self.__watch_tail) # при нажатии на кнопку END начинается просмотр последних данных @@ -32,9 +35,14 @@ def __init__(self, main_space, file_path=''): self.txt.insert(tkinter.END, self.document.get_lines()) # вставляем текст из нашего документа self.txt.config(state='disabled') # закрываем возможность редактировать + self.thread_highlight = threading.Thread(target=self.__highlight_word, + args=['error', self.search_index], + daemon=True, + name='__highlight_red') # поток для выделения текста self.thread_show_last_string = threading.Thread(target=self.__shows_the_last_string, daemon=True, name='__watch_tail') # поток для просмотра последней строки + self.thread_highlight.start() def __set_tab_name(self, tab_name_expect): self.__name, self.__file_fmt = tab_name_expect.split('.') @@ -70,6 +78,30 @@ def __stop_watch_tail(self, event): """останавливаем цикл, который постоянно мониторит последнюю строку""" self.__end = 0 + def __search_word(self, word, start_index): + """Find first position of the word, from start position""" + pos = self.txt.search(word, start_index, tkinter.END) + if pos: + string, sym = pos.split('.') + new_sym = str(int(sym) + len(word)) + next_start_index = '{0}.{1}'.format(string, new_sym) + self.search_index = next_start_index + return pos, next_start_index + else: + next_start_index = '' + return pos, next_start_index + + def __highlight_word(self, word, start_index): + next_index = start_index + while True: + first_sym, last_sym = self.__search_word(word, start_index=next_index) + if last_sym: + next_index = last_sym + self.txt.tag_add('red', first_sym, last_sym) + time.sleep(0.2) + else: + time.sleep(0.7) + def get_all_text(self): self.all_visible_text = self.txt.get(1.0, tkinter.END) return self.all_visible_text From fe08d796f170242cdb44a7a7b2902f0ecb0e83e5 Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 24 Dec 2017 23:46:12 +0300 Subject: [PATCH 25/25] Menu bar changed. --- main_form.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/main_form.py b/main_form.py index 766a612..a4661da 100644 --- a/main_form.py +++ b/main_form.py @@ -82,17 +82,19 @@ def add_tab(): start_pos_x = int(root.winfo_screenwidth() / 2) - int((app_width / 2)) start_pos_y = int(root.winfo_screenheight() / 2.5) - int((app_height / 2)) -menubar = tkinter.Menu(root) +menu_bar = tkinter.Menu(root, tearoff=False) save_button = tkinter.Menu(root) -root.config(menu=menubar) -menubar.add_command(label="Open..", command=add_tab) -save_menu = tkinter.Menu(menubar) +root.config(menu=menu_bar) -save_menu.add_command(label='Save active', command=save_file) -save_menu.add_command(label='Save all...', command=save_all_file) -save_menu.add_separator() -menubar.add_cascade(label='Save..', menu=save_menu) +submenu = tkinter.Menu(menu_bar, tearoff=False) +save_submenu = tkinter.Menu(submenu) + +menu_bar.add_cascade(label='File', menu=submenu) +submenu.add_command(label="Open file", command=add_tab) +submenu.add_cascade(label='Save..', menu=save_submenu) +save_submenu.add_command(label='Save active', command=save_file) +save_submenu.add_command(label='Save all...', command=save_all_file) # Defines and places the notebook widget nb = CustomNotebook(root)