-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
tips.py
238 lines (191 loc) · 10.4 KB
/
tips.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
"""
The Startup Tips (Tips for the Day) module for Temp_Cleaner GUI v6.8 or above.
Copyright (C) Insertx2k Dev (Mr.X) or Ziad Ahmed - 2021 - 2023
Licensed under the same license as Temp_Cleaner GUI (which is GPL 2+)
This module contains Windows and other necessary functions to implement the startup tips function in Temp_Cleaner GUI's window.
**SHOULD NOT BE REDISTRIBUTED OUTSIDE OF TEMP_CLEANER GUI**
"""
from tkinter import *
from tkinter import ttk, messagebox
import configparser
from customtkinter import *
from translations import *
import sys
import os
try:
from tkinterweb import HtmlFrame
except Exception as errorImportingTkWebLib:
print(f"[ERROR]: Couldn't import Tkinterweb\n{errorImportingTkWebLib}")
messagebox.showerror("Unhandled runtime exception", f"Couldn't load TkWeb library necessary for displaying tips to the user\nError details are:\n{errorImportingTkWebLib}\n\nPressing OK will make the program continue to function despite this error.")
pass
import random
# initializing a variable containing the path where program executable is stored.
application_path = ''
# a quick check whether if program is a compiled bundle by pyinstaller or a simple python file.
if getattr(sys, 'frozen', False):
# pyinstaller creates a sys attribute frozen=True during startup of pyinstaller bootloader to indicate
# that pyinstaller has compiled (frozen) this program, then it creates a sys constant _MEIPASS containing the path
# where the executable is found.
application_path = sys._MEIPASS
else: # if program is running as a python script via python terminal
application_path = os.path.dirname(os.path.abspath(__file__))
print(f"[DEBUG]: Tips module located at: {application_path}")
try:
# opening a configparser session for reading from the file 'Config.ini'
GetConfig = configparser.ConfigParser()
GetConfig.read(f"{application_path}\\Config.ini")
# ------------------------
except Exception as errorReadingConfigFile:
messagebox.showerror("Runtime error", f"It seems like one of the necessary files to make Temp_Cleaner GUI work are missing, double check that the file 'Config.ini' exists in the directory where this program exists and try again\n\nError details for technical support:\n{errorReadingConfigFile}")
raise SystemExit(255)
# attempts to get the current language for the ui mode of the updater program.
def getCurrentLanguage(currentLanguageStr=GetConfig["ProgConfig"]["languagesetting"]):
"""
Gets the current language from the config file 'Config.ini'
Should return `en` class if the current language is set to en, and so on.
"""
try:
if str(currentLanguageStr) == "en":
return en
elif str(currentLanguageStr) == "ar":
return ar
else:
return en
except Exception as exception_reading_config_file:
messagebox.showerror("An ERROR has occured",f"Couldn't read from 'Config.ini'\nException details:\n{exception_reading_config_file}\nPress OK to close this program")
return None
class TipsWindow(Toplevel):
def __init__(self):
super().__init__()
self.title(getCurrentLanguage().tips)
self._window_width = 450
self._window_height = 250
self.geometry(f'{self._window_width}x{self._window_height}')
self.minsize(self._window_width, self._window_height)
self.resizable(True, True)
self.wm_resizable(True, True)
deactivate_automatic_dpi_awareness() # fixes for HiDPi displays
# making window always on top.
self.attributes('-topmost',True)
# trying to load the style.json file to apply customtkinter styles.
try:
set_default_color_theme(f"{application_path}\\style.json")
except Exception as style_json_file_loader_tryone_error:
print(f"[ERROR]: couldn't read from file 'style.json' in the current directory due to the error:\n{style_json_file_loader_tryone_error}")
self.destroy()
return # error 299 is for error loading style.json file from current and previous directories.
# ---------------------------
def getCurrentAppearanceMode():
"""
Gets the current appearance mode to apply to the background of the widgets.
Returns a tuple containing the values of text color and background color for widgets.
Order goes like that:
```py
(background_color, text_color)
```
"""
global GetConfig
try:
if str(GetConfig["ProgConfig"]['appearancemode']) == "1": # 1 is for light mode
return (None, 'black')
elif str(GetConfig["ProgConfig"]['appearancemode']) == "2": # 2 is for dark mode
return ('#333', "white")
else:
return (None, "black")
except Exception as exception_reading_appearance_mode:
messagebox.showerror("An ERROR has occured", f"{exception_reading_appearance_mode}")
return False
return False
try:
self.iconbitmap(f"{application_path}\\icon0.ico")
except Exception as errorLoadingIconBitmap:
messagebox.showerror("ERROR in Mainloop thread", f"Couldn't load the iconbitmap for this window due to the exception:\n{errorLoadingIconBitmap}\nPress OK to acknowledge this event and continue running the program.")
pass
def quitBtnFunc():
"""
The function for the 'Quit' button in the Tips window
"""
try:
self.destroy()
except Exception as exceptionDestroyingMainProcess:
print(f"[ERROR]: Background Error: Self is already destroyed\nMore details:\n{exceptionDestroyingMainProcess}")
return None
try:
if str(GetConfig["ProgConfig"]["languagesetting"]) == "en":
print("[DEBUG]: Language for tips is English")
tips_folder_path = f"{application_path}\\tips\\en"
elif str(GetConfig["ProgConfig"]["languagesetting"]) == "ar":
print("[DEBUG]: Language for Tips is Arabic")
tips_folder_path = f"{application_path}\\tips\\ar"
else:
print(f'[DEBUG]: Language defined in {str(GetConfig["ProgConfig"]["languagesetting"])} has no tips available')
messagebox.showerror(getCurrentLanguage().cant_retrieve_config_fromfile_msgbox_title, getCurrentLanguage().error_unsupported_lang_in_tips)
self.destroy()
except Exception as errorReadingFolder:
messagebox.showerror(getCurrentLanguage().cant_retrieve_config_fromfile_msgbox_title, f"{getCurrentLanguage().tips_folder_missing}\n{errorReadingFolder}")
self.destroy()
def tipsLinkClicked(link):
"""
A function to make links in the tips window work.
Parameters: link -> the target url of the link the user presses
"""
try:
self.tipswebview.load_url(f"file:///{tips_folder_path}\\{str(link).replace('file:///', '')}")
except:
pass
return None
def openRandomTip():
"""
Loads a random tip file from the folder 'tips' in the program's directory.
returns False if failed to read from folder, otherwise returns None
"""
try:
if str(GetConfig["ProgConfig"]["languagesetting"]) == "en":
print("[DEBUG]: Language for tips is English")
tips_files = os.listdir(tips_folder_path)
elif str(GetConfig["ProgConfig"]["languagesetting"]) == "ar":
print("[DEBUG]: Language for Tips is Arabic")
tips_files = os.listdir(tips_folder_path)
else:
print(f'[DEBUG]: Language defined in {str(GetConfig["ProgConfig"]["languagesetting"])} has no tips available')
messagebox.showerror(getCurrentLanguage().cant_retrieve_config_fromfile_msgbox_title, getCurrentLanguage().error_unsupported_lang_in_tips)
self.destroy()
return False
except Exception as errorReadingFolder:
messagebox.showerror(getCurrentLanguage().cant_retrieve_config_fromfile_msgbox_title, f"{getCurrentLanguage().tips_folder_missing}\n{errorReadingFolder}")
self.destroy()
return False
tipfile_chosen = random.choice(tips_files)
try:
self.tipswebview.load_url(f"file:///{tips_folder_path}\\{tipfile_chosen}")
except:
self.destroy()
return None
# frame for web view widget.
self.viewframe = Frame(self, bg=getCurrentAppearanceMode()[0])
self.viewframe.pack(fill=BOTH, expand=True)
self.viewframe.pack_propagate(False)
# webview widget declaration.
try:
self.tipswebview = HtmlFrame(self.viewframe)
self.tipswebview.pack(fill=BOTH, expand=True)
self.tipswebview.on_link_click(tipsLinkClicked)
except Exception as errorDeclaringWebViewWidget:
messagebox.showerror("Runtime Error", f"Couldn't display the webview widget that displays tips for you because of the error:\n{errorDeclaringWebViewWidget}\n\nPressing OK will close the tips window")
self.destroy()
try:
openRandomTip()
except:
self.destroy()
# close button and it's frame
self.closebtnframe = Frame(self,bg=getCurrentAppearanceMode()[0], height=30)
self.closebtnframe.pack(fill=X, expand=False)
self.closebtnframe.pack_propagate(False)
self.close_btn = CTkButton(self.closebtnframe, text=getCurrentLanguage().quit_settings_btn, command=quitBtnFunc)
self.close_btn.pack(expand=True, fill=BOTH, side=LEFT)
self.next_btn = CTkButton(self.closebtnframe, text=getCurrentLanguage().tips_next, command=openRandomTip)
self.next_btn.pack(expand=True, fill=BOTH, side=RIGHT)
if __name__ == '__main__':
process = TipsWindow()
process.mainloop()
raise SystemExit(0)