Improved enums and error handling

This commit is contained in:
Profitroll 2023-01-26 13:29:30 +01:00
parent bfcdcce11d
commit 062a38ceec
6 changed files with 82 additions and 29 deletions

View File

@ -1,5 +1,6 @@
from os import path from os import path
from tkinter import NSEW, NW, E, N, S, W, PhotoImage, messagebox, ttk from tkinter import NSEW, NW, E, N, S, W, PhotoImage, messagebox, ttk
from traceback import format_exc
import requests import requests
import sv_ttk import sv_ttk
@ -7,6 +8,7 @@ from ttkthemes import ThemedTk
from classes.custom.scrollable_frame import FIT_HEIGHT, FIT_WIDTH from classes.custom.scrollable_frame import FIT_HEIGHT, FIT_WIDTH
from classes.custom.themed_frame import ThemedFrame from classes.custom.themed_frame import ThemedFrame
from classes.enums import ConnectionState, Theme
from classes.frames.devices import FrameDevices, FrameDevicesEmpty from classes.frames.devices import FrameDevices, FrameDevicesEmpty
from classes.frames.errors import FrameErrorConnection, FrameErrorFirstStart, FrameErrorSavesFolder, FrameErrorUnconfigured from classes.frames.errors import FrameErrorConnection, FrameErrorFirstStart, FrameErrorSavesFolder, FrameErrorUnconfigured
from classes.frames.saves import FrameSaves, FrameSavesEmpty from classes.frames.saves import FrameSaves, FrameSavesEmpty
@ -14,6 +16,7 @@ from classes.frames.settings import FrameSettings
from classes.toplevel.welcome import ToplevelWelcome from classes.toplevel.welcome import ToplevelWelcome
from modules.theme_titlebar import theme_title_bar from modules.theme_titlebar import theme_title_bar
from modules.utils import configGet, get_string_mode, resize_window, set_icon, use_dark_mode from modules.utils import configGet, get_string_mode, resize_window, set_icon, use_dark_mode
from modules.logger import logger
class App(ThemedTk): class App(ThemedTk):
@ -33,7 +36,7 @@ class App(ThemedTk):
sv_ttk.init_theme(self) sv_ttk.init_theme(self)
if use_dark_mode(): if use_dark_mode():
theme_title_bar(self, mode="dark") theme_title_bar(self, mode=Theme.DARK)
self.update() self.update()
set_icon(self) set_icon(self)
@ -43,14 +46,11 @@ class App(ThemedTk):
self.draw_main() self.draw_main()
def verify_authorization(self): def verify_authorization(self) -> ConnectionState:
try: try:
if requests.get(configGet("address")+"/apikey", headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed")).status_code == 200: return ConnectionState.UNAUTHORIZED if requests.get(configGet("address")+"/apikey", headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed")).status_code == 403 else ConnectionState.OK
return True
else:
return False
except: except:
return False return ConnectionState.BAD
def verify_saves_dir(self): def verify_saves_dir(self):
@ -63,7 +63,14 @@ class App(ThemedTk):
def frame_saves(self): def frame_saves(self):
self.grid_rowconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(1, weight=1) self.grid_columnconfigure(1, weight=1)
try:
self.frame_saves_saves = requests.get(f'{configGet("address")}/saves?only_ids=True&sort={(configGet("prefer_saves").split())[1]}', headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed")) self.frame_saves_saves = requests.get(f'{configGet("address")}/saves?only_ids=True&sort={(configGet("prefer_saves").split())[1]}', headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed"))
except Exception as exp:
messagebox.showerror(title="Connection error", message=f"We could not reach the server to check for save entries\n\n{exp}")
logger.error(format_exc())
self.frame_saves_object = FrameErrorConnection(self)
self.frame_saves_object.grid(column=1, row=0, sticky=NSEW)
return
if self.frame_saves_saves.status_code == 200 and isinstance(self.frame_saves_saves.json(), list) is True and len(self.frame_saves_saves.json()) > 0: if self.frame_saves_saves.status_code == 200 and isinstance(self.frame_saves_saves.json(), list) is True and len(self.frame_saves_saves.json()) > 0:
self.frame_saves_object = FrameSaves(self, self.frame_saves_saves.json(), vscroll=True) self.frame_saves_object = FrameSaves(self, self.frame_saves_saves.json(), vscroll=True)
else: else:
@ -74,7 +81,14 @@ class App(ThemedTk):
def frame_devices(self): def frame_devices(self):
self.grid_rowconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(1, weight=1) self.grid_columnconfigure(1, weight=1)
try:
self.frame_devices_devices = requests.get(f'{configGet("address")}/devices', headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed")) self.frame_devices_devices = requests.get(f'{configGet("address")}/devices', headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed"))
except Exception as exp:
messagebox.showerror(title="Connection error", message=f"We could not reach the server to check the devices list\n\n{exp}")
logger.error(format_exc())
self.frame_devices_object = FrameErrorConnection(self)
self.frame_devices_object.grid(column=1, row=0, sticky=NSEW)
return
if self.frame_devices_devices.status_code == 200 and isinstance(self.frame_devices_devices.json(), list) is True and len(self.frame_devices_devices.json()) > 0: if self.frame_devices_devices.status_code == 200 and isinstance(self.frame_devices_devices.json(), list) is True and len(self.frame_devices_devices.json()) > 0:
self.frame_devices_object = FrameDevices(self, self.frame_devices_devices.json(), vscroll=True) self.frame_devices_object = FrameDevices(self, self.frame_devices_devices.json(), vscroll=True)
else: else:
@ -136,14 +150,19 @@ class App(ThemedTk):
# messagebox.showerror(title="Configuration error", message="Your client is not properly configured.") # messagebox.showerror(title="Configuration error", message="Your client is not properly configured.")
return return
if self.verify_authorization() is False: self.verified = self.verify_authorization()
if self.verified in [ConnectionState.BAD, ConnectionState.UNAUTHORIZED]:
self.item_saves.state(["disabled"]) self.item_saves.state(["disabled"])
self.item_devices.state(["disabled"]) self.item_devices.state(["disabled"])
self.grid_rowconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(1, weight=1) self.grid_columnconfigure(1, weight=1)
self.connection_error = FrameErrorConnection(self) self.connection_error = FrameErrorConnection(self)
self.connection_error.grid(column=1, row=0, rowspan=2, sticky=N+S+W+E) self.connection_error.grid(column=1, row=0, rowspan=2, sticky=N+S+W+E)
if self.verified == ConnectionState.UNAUTHORIZED:
messagebox.showerror(title="Authentication error", message="Your API key seems to be invalid.") messagebox.showerror(title="Authentication error", message="Your API key seems to be invalid.")
else:
messagebox.showerror(title="Connection error", message="Server is not reachable or your client configuration is incorrect. Please check your network connection and client configuration.")
return return
if self.verify_saves_dir() is False: if self.verify_saves_dir() is False:

24
classes/enums.py Normal file
View File

@ -0,0 +1,24 @@
from enum import Enum
class SavesPreference(Enum):
LATEST_UPLOAD = "latest upload"
LATEST_PROGRESS = "latest progress"
class SavesPreferenceButton(Enum):
LATEST_UPLOAD = "Latest upload "
LATEST_PROGRESS = "Latest progress "
class Theme(Enum):
AUTO = "auto"
LIGHT = "light"
DARK = "dark"
class ThemeButton(Enum):
AUTO = "Auto "
LIGHT = "Light "
DARK = "Dark "
class ConnectionState(Enum):
OK = "ok"
BAD = "bad"
UNAUTHORIZED = "unauthorized"

View File

@ -11,13 +11,13 @@ from modules.utils import configGet, get_string_mode
def try_connecting(master: Any): def try_connecting(master: Any):
try: try:
if requests.get(configGet("address")+"/apikey", headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed")).status_code != 200: if requests.get(configGet("address")+"/apikey", headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed")).status_code == 403:
messagebox.showerror(title="Authentication error", message="Your API key seems to be invalid.") messagebox.showerror(title="Authentication error", message="Your API key seems to be invalid.")
return return
# messagebox.showinfo(title="Connection succeeded", message="Server is reachable, apikey is valid, so your client is now ready to be used!") # messagebox.showinfo(title="Connection succeeded", message="Server is reachable, apikey is valid, so your client is now ready to be used!")
master.destroy_everything() master.destroy_everything()
except: except:
messagebox.showerror(title="Configuration error", message="Your client configuration is incorrect.") messagebox.showerror(title="Connection error", message="Server is not reachable or your client configuration is incorrect. Please check your network connection and client configuration.")
# master.destroy_everything() # master.destroy_everything()

View File

@ -4,6 +4,7 @@ from tkinter import N, NSEW, S, W, E, END, IntVar, StringVar, filedialog, messag
from ttkthemes import ThemedTk from ttkthemes import ThemedTk
from classes.custom.themed_frame import ThemedFrame from classes.custom.themed_frame import ThemedFrame
from classes.enums import SavesPreference, SavesPreferenceButton, Theme
from modules.theme_titlebar import theme_title_bar from modules.theme_titlebar import theme_title_bar
from modules.utils import configGet, configSet, get_string_mode, use_dark_mode from modules.utils import configGet, configSet, get_string_mode, use_dark_mode
@ -92,10 +93,10 @@ class FrameSettings(ThemedFrame):
self.saves_preference_label = ttk.Label(self, text="Saves preference:") self.saves_preference_label = ttk.Label(self, text="Saves preference:")
self.saves_preference_label.grid(column=0, row=4, sticky=W, padx=9, pady=9) self.saves_preference_label.grid(column=0, row=4, sticky=W, padx=9, pady=9)
self.default_preference = "Latest upload " if configGet("prefer_saves") == "latest upload" else "Latest progress " self.default_preference = SavesPreferenceButton.LATEST_UPLOAD.value if configGet("prefer_saves") == SavesPreference.LATEST_UPLOAD.value else SavesPreferenceButton.LATEST_PROGRESS.value
self.chosen_preference = StringVar() self.chosen_preference = StringVar()
self.preferences = ("Latest upload ", "Latest progress ") self.preferences = (SavesPreferenceButton.LATEST_UPLOAD.value, SavesPreferenceButton.LATEST_PROGRESS.value)
self.saves_preference_button = ttk.OptionMenu(self, self.chosen_preference, self.default_preference, *self.preferences, direction="below") self.saves_preference_button = ttk.OptionMenu(self, self.chosen_preference, self.default_preference, *self.preferences, direction="below")
self.saves_preference_button.grid(column=1, row=4, sticky=W, padx=9, pady=9) self.saves_preference_button.grid(column=1, row=4, sticky=W, padx=9, pady=9)
# ================ # ================
@ -127,10 +128,13 @@ class FrameSettings(ThemedFrame):
def change_theme(self, *args): def change_theme(self, *args):
if self.chosen_theme.get().strip().lower() == "auto": if self.chosen_theme.get().strip().lower() == Theme.AUTO.value:
self.chosen_theme_real = "dark" if use_dark_mode(no_config=True) is True else "light" self.chosen_theme_real = Theme.DARK if use_dark_mode(no_config=True) is True else Theme.LIGHT
else: else:
self.chosen_theme_real = self.chosen_theme.get().strip().lower() if self.chosen_theme.get().strip().lower() == Theme.LIGHT.value:
self.chosen_theme_real = Theme.LIGHT
else:
self.chosen_theme_real = Theme.DARK
theme_title_bar(self.master, self.chosen_theme_real) theme_title_bar(self.master, self.chosen_theme_real)
def select_location(self, entry: ttk.Entry): def select_location(self, entry: ttk.Entry):

View File

@ -9,6 +9,7 @@ from classes.custom.image_label import ImageLabel
from classes.custom.themed_frame import ThemedFrame from classes.custom.themed_frame import ThemedFrame
from classes.custom.themed_toplevel import ThemedToplevel from classes.custom.themed_toplevel import ThemedToplevel
from classes.enums import Theme
from modules.logger import logger from modules.logger import logger
from modules.theme_titlebar import theme_title_bar from modules.theme_titlebar import theme_title_bar
from modules.utils import configGet, configSet, resize_window, set_icon, use_dark_mode from modules.utils import configGet, configSet, resize_window, set_icon, use_dark_mode
@ -31,7 +32,7 @@ class ToplevelWelcome(ThemedToplevel):
sv_ttk.init_theme(self) sv_ttk.init_theme(self)
if use_dark_mode(): if use_dark_mode():
theme_title_bar(self, mode="dark") theme_title_bar(self, mode=Theme.DARK)
self.update() self.update()
set_icon(self) set_icon(self)
@ -287,20 +288,23 @@ class ToplevelWelcome(ThemedToplevel):
def change_theme(self, *args): def change_theme(self, *args):
if self.stage_option_menu_var.get().strip().lower() == "auto": if self.stage_option_menu_var.get().strip().lower() == Theme.AUTO.value:
self.stage_option_menu_var_real = "dark" if use_dark_mode(no_config=True) is True else "light" self.stage_option_menu_var_real = Theme.DARK if use_dark_mode(no_config=True) is True else Theme.LIGHT
else: else:
self.stage_option_menu_var_real = self.stage_option_menu_var.get().strip().lower() if self.stage_option_menu_var.get().strip().lower() == Theme.LIGHT.value:
self.stage_option_menu_var_real = Theme.LIGHT
else:
self.stage_option_menu_var_real = Theme.DARK
theme_title_bar(self, self.stage_option_menu_var_real) theme_title_bar(self, self.stage_option_menu_var_real)
theme_title_bar(self.master, self.stage_option_menu_var_real) theme_title_bar(self.master, self.stage_option_menu_var_real)
def stage_theme_validate(self): def stage_theme_validate(self):
if self.stage_option_menu_var.get().strip().lower() == "auto": if self.stage_option_menu_var.get().strip().lower() == Theme.AUTO.value:
configSet(["dark_mode_auto"], True) configSet(["dark_mode_auto"], True)
else: else:
configSet(["dark_mode_auto"], False) configSet(["dark_mode_auto"], False)
if self.stage_option_menu_var.get().strip().lower() == "dark": if self.stage_option_menu_var.get().strip().lower() == Theme.DARK.value:
configSet(["dark_mode"], True) configSet(["dark_mode"], True)
else: else:
configSet(["dark_mode"], False) configSet(["dark_mode"], False)

View File

@ -3,25 +3,27 @@ import sys
import sv_ttk import sv_ttk
from distutils.version import StrictVersion as Version from distutils.version import StrictVersion as Version
from os import system from os import system
from tkinter import Tcl, Toplevel from tkinter import Misc, Tcl, Toplevel
from typing import Literal, Union from typing import Literal, Union
from ttkthemes import ThemedTk from ttkthemes import ThemedTk
from classes.enums import Theme
if sys.platform.startswith("win"): if sys.platform.startswith("win"):
from ctypes import byref, c_int, sizeof, windll from ctypes import byref, c_int, sizeof, windll
def theme_title_bar(window: Union[ThemedTk, Toplevel], mode: Literal["dark", "light"]) -> None: def theme_title_bar(window: Union[ThemedTk, Toplevel, Misc], mode: Literal[Theme.DARK, Theme.LIGHT]) -> None:
""" """
MORE INFO: MORE INFO:
https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
""" """
if mode == "dark": if mode.value == "dark":
value = 1 value = 1
#window.configure(background="#1c1c1c") #window.configure(background="#1c1c1c")
elif mode == "light": elif mode.value == "light":
value = 0 value = 0
#window.configure(background="#ffffff") #window.configure(background="#ffffff")
else: else:
@ -29,7 +31,7 @@ def theme_title_bar(window: Union[ThemedTk, Toplevel], mode: Literal["dark", "li
try: try:
sv_ttk.set_theme(mode) sv_ttk.set_theme(mode.value)
window.update() window.update()