2023-01-22 01:35:32 +02:00
from os import path
2023-01-23 13:22:54 +02:00
from tkinter import NSEW , NW , E , N , S , W , PhotoImage , messagebox , ttk
2023-01-26 14:29:30 +02:00
from traceback import format_exc
2023-01-22 01:35:32 +02:00
2023-01-22 01:22:08 +02:00
import requests
import sv_ttk
from ttkthemes import ThemedTk
2023-01-22 01:35:32 +02:00
2023-01-23 01:13:30 +02:00
from classes . custom . scrollable_frame import FIT_HEIGHT , FIT_WIDTH
from classes . custom . themed_frame import ThemedFrame
2023-01-26 14:29:30 +02:00
from classes . enums import ConnectionState , Theme
2023-01-23 01:13:30 +02:00
from classes . frames . devices import FrameDevices , FrameDevicesEmpty
2023-01-24 16:27:07 +02:00
from classes . frames . errors import FrameErrorConnection , FrameErrorFirstStart , FrameErrorSavesFolder , FrameErrorUnconfigured
2023-01-25 17:23:18 +02:00
from classes . frames . saves import FrameSaves , FrameSavesEmpty
2023-01-22 18:53:55 +02:00
from classes . frames . settings import FrameSettings
2023-01-22 21:06:55 +02:00
from classes . toplevel . welcome import ToplevelWelcome
2023-01-22 01:35:32 +02:00
from modules . theme_titlebar import theme_title_bar
2023-01-23 17:38:47 +02:00
from modules . utils import configGet , get_string_mode , resize_window , set_icon , use_dark_mode
2023-01-26 14:29:30 +02:00
from modules . logger import logger
2023-01-22 01:35:32 +02:00
2023-01-22 01:22:08 +02:00
class App ( ThemedTk ) :
def __init__ ( self ) :
super ( ) . __init__ ( )
2023-01-23 01:13:30 +02:00
self . __version__ = " 0.1.0 "
2023-01-23 17:38:47 +02:00
resize_window ( self , 610 , 400 )
2023-01-26 12:10:25 +02:00
self . resizable ( True , True )
2023-01-25 17:23:18 +02:00
self . minsize ( 610 , 200 )
2023-01-22 01:22:08 +02:00
self . title ( " Stardew Sync " )
2023-01-22 18:53:55 +02:00
2023-01-22 01:22:08 +02:00
sv_ttk . init_theme ( self )
if use_dark_mode ( ) :
2023-01-26 14:29:30 +02:00
theme_title_bar ( self , mode = Theme . DARK )
2023-01-22 18:53:55 +02:00
self . update ( )
2023-01-22 01:22:08 +02:00
2023-01-23 13:22:54 +02:00
set_icon ( self )
2023-01-22 01:22:08 +02:00
2023-01-22 18:53:55 +02:00
self . focus_set ( )
2023-01-22 01:22:08 +02:00
2023-01-22 18:53:55 +02:00
self . draw_main ( )
2023-01-22 01:22:08 +02:00
2023-01-26 14:29:30 +02:00
def verify_authorization ( self ) - > ConnectionState :
2023-01-22 01:22:08 +02:00
try :
2023-01-26 14:29:30 +02:00
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
2023-01-22 18:53:55 +02:00
except :
2023-01-26 14:29:30 +02:00
return ConnectionState . BAD
2023-01-22 01:22:08 +02:00
2023-01-22 18:53:55 +02:00
def verify_saves_dir ( self ) :
2023-01-22 01:22:08 +02:00
2023-01-22 18:53:55 +02:00
if configGet ( " saves_location " ) is None or path . exists ( configGet ( " saves_location " ) ) is False :
return False
else :
return True
2023-01-22 01:22:08 +02:00
def frame_saves ( self ) :
2023-01-23 01:13:30 +02:00
self . grid_rowconfigure ( 0 , weight = 1 )
self . grid_columnconfigure ( 1 , weight = 1 )
2023-01-26 14:29:30 +02:00
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 " ) )
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
2023-01-25 17:23:18 +02:00
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 )
else :
2023-01-27 13:18:10 +02:00
self . frame_saves_object = FrameSaves ( self , [ ] , vscroll = True )
2023-01-23 01:13:30 +02:00
self . frame_saves_object . grid ( column = 1 , row = 0 , sticky = NSEW )
2023-01-22 01:22:08 +02:00
return
def frame_devices ( self ) :
2023-01-23 01:13:30 +02:00
self . grid_rowconfigure ( 0 , weight = 1 )
self . grid_columnconfigure ( 1 , weight = 1 )
2023-01-26 14:29:30 +02:00
try :
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
2023-01-23 01:13:30 +02:00
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 )
else :
self . frame_devices_object = FrameDevicesEmpty ( self )
self . frame_devices_object . grid ( column = 1 , row = 0 , sticky = NSEW )
2023-01-22 01:22:08 +02:00
return
def frame_settings ( self ) :
2023-01-23 01:13:30 +02:00
self . grid_rowconfigure ( 0 , weight = 1 )
self . grid_columnconfigure ( 1 , weight = 1 )
2023-01-22 01:22:08 +02:00
self . frame_settings_object = FrameSettings ( self )
self . frame_settings_object . grid ( column = 1 , row = 0 , sticky = N + S + W + E )
return
def draw_main ( self ) :
2023-01-22 18:53:55 +02:00
sv_ttk . set_theme ( get_string_mode ( ) )
2023-01-22 01:22:08 +02:00
2023-01-22 18:53:55 +02:00
# self.grid_rowconfigure(1, weight=2)
# self.grid_rowconfigure(0, weight=2)
# self.grid_columnconfigure(1, weight=1)
# self.setup_label = ttk.Label(self, text="Your client seems to be unconfigured")
# self.setup_label.grid(column=1, row=0, padx=9, pady=9, sticky=S)
# self.setup_button = ttk.Button(self, text="Set up", style="Accent.TButton", width=10, command=self.open_window_config)
# self.setup_button.grid(column=1, row=1, padx=9, pady=9, sticky=N)
# return
2023-01-22 21:06:55 +02:00
if configGet ( " first_run " ) is True :
self . welcome_window = ToplevelWelcome ( self )
self . welcome_window . grab_set ( )
2023-01-22 01:22:08 +02:00
2023-01-22 18:53:55 +02:00
self . frame_sidebar = ThemedFrame ( self )
self . frame_sidebar . grid ( column = 0 , row = 0 , columnspan = 1 , sticky = N + S + W + E )
2023-01-22 01:22:08 +02:00
self . item_saves = ttk . Button ( self . frame_sidebar , text = " Saves " , width = 10 , command = self . frame_saves )
self . item_saves . grid ( column = 0 , row = 0 , sticky = W , padx = 9 , pady = 9 )
self . item_devices = ttk . Button ( self . frame_sidebar , text = " Devices " , width = 10 , command = self . frame_devices )
self . item_devices . grid ( column = 0 , row = 1 , sticky = W , padx = 9 , pady = 3 )
self . item_settings = ttk . Button ( self . frame_sidebar , text = " Settings " , width = 10 , command = self . frame_settings )
self . item_settings . grid ( column = 0 , row = 2 , sticky = W + S , padx = 9 , pady = 9 )
2023-01-22 18:53:55 +02:00
2023-01-24 16:27:07 +02:00
if configGet ( " first_run " ) is True :
self . grid_rowconfigure ( 0 , weight = 1 )
self . grid_columnconfigure ( 1 , weight = 1 )
self . connection_error = FrameErrorFirstStart ( self )
self . connection_error . grid ( column = 1 , row = 0 , rowspan = 2 , sticky = N + S + W + E )
return
2023-01-22 18:53:55 +02:00
if configGet ( " address " ) in [ " " , None ] or configGet ( " apikey " ) in [ " " , None ] :
self . item_saves . state ( [ " disabled " ] )
self . item_devices . state ( [ " disabled " ] )
2023-01-23 01:13:30 +02:00
self . grid_rowconfigure ( 0 , weight = 1 )
self . grid_columnconfigure ( 1 , weight = 1 )
2023-01-22 18:53:55 +02:00
self . connection_error = FrameErrorUnconfigured ( self )
self . connection_error . grid ( column = 1 , row = 0 , rowspan = 2 , sticky = N + S + W + E )
# messagebox.showerror(title="Configuration error", message="Your client is not properly configured.")
return
2023-01-26 14:29:30 +02:00
self . verified = self . verify_authorization ( )
if self . verified in [ ConnectionState . BAD , ConnectionState . UNAUTHORIZED ] :
2023-01-22 18:53:55 +02:00
self . item_saves . state ( [ " disabled " ] )
self . item_devices . state ( [ " disabled " ] )
2023-01-23 01:13:30 +02:00
self . grid_rowconfigure ( 0 , weight = 1 )
self . grid_columnconfigure ( 1 , weight = 1 )
2023-01-22 18:53:55 +02:00
self . connection_error = FrameErrorConnection ( self )
self . connection_error . grid ( column = 1 , row = 0 , rowspan = 2 , sticky = N + S + W + E )
2023-01-26 14:29:30 +02:00
if self . verified == ConnectionState . UNAUTHORIZED :
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. " )
2023-01-22 18:53:55 +02:00
return
2023-01-22 01:22:08 +02:00
2023-01-22 18:53:55 +02:00
if self . verify_saves_dir ( ) is False :
self . item_saves . state ( [ " disabled " ] )
2023-01-23 01:13:30 +02:00
self . grid_rowconfigure ( 0 , weight = 1 )
self . grid_columnconfigure ( 1 , weight = 1 )
2023-01-22 18:53:55 +02:00
self . connection_error = FrameErrorSavesFolder ( self )
self . connection_error . grid ( column = 1 , row = 0 , rowspan = 2 , sticky = N + S + W + E )
messagebox . showerror ( title = " Configuration error " , message = " Saves folder seems to be invalid. " )
return
2023-01-22 01:22:08 +02:00
self . frame_saves ( )
2023-01-22 18:53:55 +02:00
def destroy_everything ( self , draw = True ) :
2023-01-22 01:22:08 +02:00
for widget in self . winfo_children ( ) :
widget . destroy ( )
2023-01-22 18:53:55 +02:00
if draw is True :
self . draw_main ( )
# def open_window_config(self):
# window = WindowConfig(self)
# window.grab_set()
# self.setup_button.destroy()
# self.setup_label.destroy()
# self.grid_rowconfigure(1, weight=2)
# self.grid_rowconfigure(0, weight=2)
# self.grid_columnconfigure(1, weight=1)
# ttk.Label(self, text="Client configured, try to connect").grid(column=1, row=0, padx=9, pady=9, sticky=S)
# ttk.Button(self, text="Connect", style="Accent.TButton", width=10, command=self.try_connecting).grid(column=1, row=1, padx=9, pady=9, sticky=N)