WIP: Saves windows
This commit is contained in:
parent
3666db25c6
commit
b1aeb06a09
@ -9,7 +9,7 @@ from classes.custom.scrollable_frame import FIT_HEIGHT, FIT_WIDTH
|
||||
from classes.custom.themed_frame import ThemedFrame
|
||||
from classes.frames.devices import FrameDevices, FrameDevicesEmpty
|
||||
from classes.frames.errors import FrameErrorConnection, FrameErrorFirstStart, FrameErrorSavesFolder, FrameErrorUnconfigured
|
||||
from classes.frames.saves import FrameSaves
|
||||
from classes.frames.saves import FrameSaves, FrameSavesEmpty
|
||||
from classes.frames.settings import FrameSettings
|
||||
from classes.toplevel.welcome import ToplevelWelcome
|
||||
from modules.theme_titlebar import theme_title_bar
|
||||
@ -25,11 +25,11 @@ class App(ThemedTk):
|
||||
self.__version__ = "0.1.0"
|
||||
|
||||
resize_window(self, 610, 400)
|
||||
self.resizable(False, True)
|
||||
self.minsize(610, 200)
|
||||
|
||||
self.title("Stardew Sync")
|
||||
|
||||
self.resizable(False, True)
|
||||
|
||||
sv_ttk.init_theme(self)
|
||||
|
||||
if use_dark_mode():
|
||||
@ -63,7 +63,11 @@ class App(ThemedTk):
|
||||
def frame_saves(self):
|
||||
self.grid_rowconfigure(0, weight=1)
|
||||
self.grid_columnconfigure(1, weight=1)
|
||||
self.frame_saves_object = FrameSaves(self)
|
||||
self.frame_saves_saves = requests.get(f'{configGet("address")}/saves?only_ids=True', headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed"))
|
||||
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:
|
||||
self.frame_saves_object = FrameSavesEmpty(self)
|
||||
self.frame_saves_object.grid(column=1, row=0, sticky=NSEW)
|
||||
return
|
||||
|
||||
@ -73,12 +77,8 @@ class App(ThemedTk):
|
||||
self.frame_devices_devices = requests.get(f'{configGet("address")}/devices', headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed"))
|
||||
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.resize(FIT_HEIGHT)
|
||||
else:
|
||||
self.frame_devices_object = FrameDevicesEmpty(self)
|
||||
#self.frame_devices_object = FrameDevices(self, hscroll=False, vscroll=True)
|
||||
#self.frame_devices_object.resize(FIT_WIDTH)
|
||||
#self.frame_devices_object.resize(FIT_HEIGHT)
|
||||
self.frame_devices_object.grid(column=1, row=0, sticky=NSEW)
|
||||
return
|
||||
|
||||
|
148
classes/frames/device.py
Normal file
148
classes/frames/device.py
Normal file
@ -0,0 +1,148 @@
|
||||
import platform
|
||||
from datetime import datetime
|
||||
from functools import partial
|
||||
from tkinter import LEFT, NSEW, E, Misc, W, messagebox, ttk
|
||||
from tkinter.messagebox import askyesno
|
||||
from urllib.parse import quote, urlencode
|
||||
|
||||
import requests
|
||||
|
||||
from classes.custom.themed_frame import ThemedFrame
|
||||
from modules.logger import logger
|
||||
from modules.utils import configGet, configSet
|
||||
|
||||
|
||||
class FrameDevice(ThemedFrame):
|
||||
|
||||
def __init__(self, master: Misc, device_dict: str, **kwargs) -> None:
|
||||
|
||||
super().__init__(master, style="Card.TFrame", **kwargs)
|
||||
|
||||
self.grid_columnconfigure(0, weight=1)
|
||||
self.grid_columnconfigure(1, weight=3)
|
||||
self.grid_columnconfigure(2, weight=3)
|
||||
|
||||
self.name = device_dict["name"]
|
||||
|
||||
self.title = ttk.Label(self, text=self.name, font=("SunValleyBodyStrongFont", 12, "bold"), justify=LEFT, width=46)
|
||||
self.title.grid(column=0, row=0, padx=9, pady=9, sticky=W)
|
||||
|
||||
last_upload = "N/A" if device_dict["last_save"] == 0 else datetime.utcfromtimestamp(device_dict["last_save"]).strftime("%d.%m.%Y %H:%M")
|
||||
self.description = ttk.Label(self, text=f'OS: {device_dict["os"]}\nClient: {device_dict["client"]}\nLast upload: {last_upload}', width=46)
|
||||
self.description.grid(column=0, row=1, padx=9, pady=9, sticky=W)
|
||||
|
||||
self.buttons = ThemedFrame(self)
|
||||
self.buttons.grid(column=0, columnspan=2, row=2, sticky=NSEW, padx=9, pady=9)
|
||||
self.buttons.grid_columnconfigure(0, weight=1)
|
||||
|
||||
self.button_device_rename_action = partial(self.rename)
|
||||
self.button_device_rename = ttk.Button(self.buttons, text="Rename", width=11, command=self.button_device_rename_action)
|
||||
self.button_device_rename.grid(column=0, row=0, padx=9, sticky=E)
|
||||
|
||||
self.button_device_delete_action = partial(self.delete)
|
||||
self.button_device_delete = ttk.Button(self.buttons, text="Delete", style="Accent.TButton", width=11, command=self.button_device_delete_action)
|
||||
self.button_device_delete.grid(column=1, row=0, sticky=W)
|
||||
|
||||
if self.name == configGet("name"):
|
||||
self.button_device_delete.state(["disabled"])
|
||||
|
||||
def rename(self):
|
||||
|
||||
self.rename_entry = ttk.Entry(self, font=("SunValleyBodyFont", 12), justify=LEFT, width=27)
|
||||
self.rename_entry.insert(0, self.name)
|
||||
self.rename_entry.grid(column=0, row=0, padx=9, pady=9, sticky=W)
|
||||
|
||||
button_device_cancel_action = partial(self.rename_cancel)
|
||||
button_device_cancel = ttk.Button(self.buttons, text="Cancel", width=11, command=button_device_cancel_action)
|
||||
button_device_cancel.grid(column=0, row=0, padx=9, sticky=E)
|
||||
|
||||
button_device_save_action = partial(self.rename_verify)
|
||||
button_device_save = ttk.Button(self.buttons, text="Save", style="Accent.TButton", width=11, command=button_device_save_action)
|
||||
button_device_save.grid(column=1, row=0, sticky=W)
|
||||
|
||||
def rename_verify(self):
|
||||
|
||||
self.name_before = configGet("name")
|
||||
|
||||
if (self.rename_entry.get().strip() == "") or ("?" in self.rename_entry.get().strip()) or ("/" in self.rename_entry.get().strip()):
|
||||
logger.error(f"Name {self.rename_entry.get().strip()} is not a valid name")
|
||||
messagebox.showerror(title="Name error", message="Provided device name is not valid. Please provide a valid one.")
|
||||
return
|
||||
|
||||
try:
|
||||
quote(self.rename_entry.get().strip())
|
||||
except:
|
||||
logger.error(f"Name {self.rename_entry.get().strip()} is not a valid name")
|
||||
messagebox.showerror(title="Name error", message="Provided device name is not valid. Please provide a valid one.")
|
||||
return
|
||||
|
||||
existing_device_before = requests.get(f'{configGet("address")}/devices/{self.name}', headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed"))
|
||||
if existing_device_before.status_code == 200:
|
||||
response = requests.patch(f'{configGet("address")}/devices/{self.name}?{urlencode({"new_name": self.rename_entry.get().strip(), "os": platform.system()+" "+platform.release(), "client": f"SyncTk {self.master.master.master.master.__version__}"})}', headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed"))
|
||||
if response.status_code != 204:
|
||||
logger.error(f"Name {self.rename_entry.get().strip()} could not be set because server returned {response.status_code}")
|
||||
messagebox.showerror(title="Name error", message=f"Provided device name is not valid.\n\nServer response: {response.json()}")
|
||||
return
|
||||
else:
|
||||
logger.error(f"Tried to rename {self.name} into {self.rename_entry.get().strip()} but server returned {existing_device_before.status_code}")
|
||||
messagebox.showerror(title="Rename error", message="It seems like this device no longer exists.")
|
||||
return
|
||||
|
||||
self.name = self.rename_entry.get().strip()
|
||||
|
||||
for widget in self.winfo_children():
|
||||
if isinstance(widget, ttk.Entry):
|
||||
widget.destroy()
|
||||
|
||||
device_title = ttk.Label(self, text=self.name, font=("SunValleyBodyStrongFont", 12, "bold"), justify=LEFT, width=46)
|
||||
device_title.grid(column=0, row=0, padx=9, pady=9, sticky=W)
|
||||
|
||||
button_device_rename_action = partial(self.rename)
|
||||
button_device_rename = ttk.Button(self.buttons, text="Rename", width=11, command=button_device_rename_action)
|
||||
button_device_rename.grid(column=0, row=0, padx=9, sticky=E)
|
||||
|
||||
button_device_delete_action = partial(self.delete)
|
||||
button_device_delete = ttk.Button(self.buttons, text="Delete", style="Accent.TButton", width=11, command=button_device_delete_action)
|
||||
button_device_delete.grid(column=1, row=0, sticky=W)
|
||||
|
||||
if self.name_before == configGet("name"):
|
||||
configSet(["name"], self.name)
|
||||
|
||||
if self.name == configGet("name"):
|
||||
button_device_delete.state(["disabled"])
|
||||
|
||||
def rename_cancel(self):
|
||||
|
||||
for widget in self.winfo_children():
|
||||
if isinstance(widget, ttk.Entry):
|
||||
widget.destroy()
|
||||
|
||||
device_title = ttk.Label(self, text=self.name, font=("SunValleyBodyStrongFont", 12, "bold"), justify=LEFT, width=46)
|
||||
device_title.grid(column=0, row=0, padx=9, pady=9, sticky=W)
|
||||
|
||||
button_device_rename_action = partial(self.rename)
|
||||
button_device_rename = ttk.Button(self.buttons, text="Rename", width=11, command=button_device_rename_action)
|
||||
button_device_rename.grid(column=0, row=0, padx=9, sticky=E)
|
||||
|
||||
button_device_delete_action = partial(self.delete)
|
||||
button_device_delete = ttk.Button(self.buttons, text="Delete", style="Accent.TButton", width=11, command=button_device_delete_action)
|
||||
button_device_delete.grid(column=1, row=0, sticky=W)
|
||||
|
||||
if self.name == configGet("name"):
|
||||
button_device_delete.state(["disabled"])
|
||||
|
||||
def delete(self):
|
||||
|
||||
decision = askyesno(title="Device removal", message=f"You are about to remove the device '{self.name}' and this will also remove all the save files uploaded by this device. Are you sure you want to continue?")
|
||||
|
||||
if decision is False:
|
||||
return
|
||||
|
||||
requests.delete(f'{configGet("address")}/devices/{self.name}', headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed"))
|
||||
|
||||
for k in range(len(self.master.devices)):
|
||||
if self.master.devices[k]["name"] == self.name:
|
||||
del self.master.devices[k]
|
||||
break
|
||||
|
||||
self.destroy()
|
@ -1,159 +1,10 @@
|
||||
from datetime import datetime
|
||||
from functools import partial
|
||||
import platform
|
||||
from tkinter import LEFT, NSEW, E, W, Misc, StringVar, ttk
|
||||
from tkinter import messagebox
|
||||
from tkinter.messagebox import askyesno, showinfo
|
||||
from tkinter.simpledialog import askstring
|
||||
from urllib.parse import quote, urlencode
|
||||
from tkinter import NSEW, ttk
|
||||
|
||||
import requests
|
||||
from ttkthemes import ThemedTk
|
||||
|
||||
from classes.custom.scrollable_frame import ScrollableFrame
|
||||
from classes.custom.themed_frame import ThemedFrame
|
||||
from modules.utils import configGet, configSet
|
||||
from modules.logger import logger
|
||||
|
||||
|
||||
class FrameDevice(ThemedFrame):
|
||||
|
||||
def __init__(self, master: Misc, device_dict: str, **kwargs) -> None:
|
||||
|
||||
super().__init__(master, style="Card.TFrame", **kwargs)
|
||||
|
||||
self["borderwidth"] = 1
|
||||
self["relief"] = "solid"
|
||||
|
||||
self.grid_columnconfigure(0, weight=1)
|
||||
self.grid_columnconfigure(1, weight=3)
|
||||
self.grid_columnconfigure(2, weight=3)
|
||||
|
||||
self.name = device_dict["name"]
|
||||
|
||||
self.title = ttk.Label(self, text=self.name, font=("SunValleyBodyFont", 12), justify=LEFT, width=46)
|
||||
self.title.grid(column=0, row=0, padx=9, pady=9, sticky=W)
|
||||
|
||||
last_upload = "N/A" if device_dict["last_save"] == 0 else datetime.utcfromtimestamp(device_dict["last_save"]).strftime("%d.%m.%Y %H:%M")
|
||||
self.description = ttk.Label(self, text=f'OS: {device_dict["os"]}\nClient: {device_dict["client"]}\nLast upload: {last_upload}', width=46)
|
||||
self.description.grid(column=0, row=1, padx=9, pady=9, sticky=W)
|
||||
|
||||
self.buttons = ThemedFrame(self)
|
||||
self.buttons.grid(column=0, columnspan=2, row=2, sticky=NSEW, padx=9, pady=9)
|
||||
self.buttons.grid_columnconfigure(0, weight=1)
|
||||
|
||||
self.button_device_rename_action = partial(self.rename)
|
||||
self.button_device_rename = ttk.Button(self.buttons, text="Rename", width=11, command=self.button_device_rename_action)
|
||||
self.button_device_rename.grid(column=0, row=0, padx=9, sticky=E)
|
||||
|
||||
self.button_device_delete_action = partial(self.delete)
|
||||
self.button_device_delete = ttk.Button(self.buttons, text="Delete", style="Accent.TButton", width=11, command=self.button_device_delete_action)
|
||||
self.button_device_delete.grid(column=1, row=0, sticky=W)
|
||||
|
||||
if self.name == configGet("name"):
|
||||
# button_device_rename.state(["disabled"])
|
||||
self.button_device_delete.state(["disabled"])
|
||||
|
||||
def rename(self):
|
||||
|
||||
self.rename_entry = ttk.Entry(self, font=("SunValleyBodyFont", 12), justify=LEFT, width=27)
|
||||
self.rename_entry.insert(0, self.name)
|
||||
self.rename_entry.grid(column=0, row=0, padx=9, pady=9, sticky=W)
|
||||
|
||||
button_device_cancel_action = partial(self.rename_cancel)
|
||||
button_device_cancel = ttk.Button(self.buttons, text="Cancel", width=11, command=button_device_cancel_action)
|
||||
button_device_cancel.grid(column=0, row=0, padx=9, sticky=E)
|
||||
|
||||
button_device_save_action = partial(self.rename_verify)
|
||||
button_device_save = ttk.Button(self.buttons, text="Save", style="Accent.TButton", width=11, command=button_device_save_action)
|
||||
button_device_save.grid(column=1, row=0, sticky=W)
|
||||
|
||||
def rename_verify(self):
|
||||
|
||||
self.name_before = configGet("name")
|
||||
|
||||
if (self.rename_entry.get().strip() == "") or ("?" in self.rename_entry.get().strip()) or ("/" in self.rename_entry.get().strip()):
|
||||
logger.error(f"Name {self.rename_entry.get().strip()} is not a valid name")
|
||||
messagebox.showerror(title="Name error", message="Provided device name is not valid. Please provide a valid one.")
|
||||
return
|
||||
|
||||
try:
|
||||
quote(self.rename_entry.get().strip())
|
||||
except:
|
||||
logger.error(f"Name {self.rename_entry.get().strip()} is not a valid name")
|
||||
messagebox.showerror(title="Name error", message="Provided device name is not valid. Please provide a valid one.")
|
||||
return
|
||||
|
||||
existing_device_before = requests.get(f'{configGet("address")}/devices/{self.name}', headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed"))
|
||||
if existing_device_before.status_code == 200:
|
||||
response = requests.patch(f'{configGet("address")}/devices/{self.name}?{urlencode({"new_name": self.rename_entry.get().strip(), "os": platform.system()+" "+platform.release(), "client": f"SyncTk {self.master.master.master.master.__version__}"})}', headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed"))
|
||||
if response.status_code != 204:
|
||||
logger.error(f"Name {self.rename_entry.get().strip()} could not be set because server returned {response.status_code}")
|
||||
messagebox.showerror(title="Name error", message=f"Provided device name is not valid.\n\nServer response: {response.json()}")
|
||||
return
|
||||
else:
|
||||
logger.error(f"Tried to rename {self.name} into {self.rename_entry.get().strip()} but server returned {existing_device_before.status_code}")
|
||||
messagebox.showerror(title="Rename error", message="It seems like this device no longer exists.")
|
||||
return
|
||||
|
||||
self.name = self.rename_entry.get().strip()
|
||||
|
||||
for widget in self.winfo_children():
|
||||
if isinstance(widget, ttk.Entry):
|
||||
widget.destroy()
|
||||
|
||||
device_title = ttk.Label(self, text=self.name, font=("SunValleyBodyFont", 12), justify=LEFT, width=46)
|
||||
device_title.grid(column=0, row=0, padx=9, pady=9, sticky=W)
|
||||
|
||||
button_device_rename_action = partial(self.rename)
|
||||
button_device_rename = ttk.Button(self.buttons, text="Rename", width=11, command=button_device_rename_action)
|
||||
button_device_rename.grid(column=0, row=0, padx=9, sticky=E)
|
||||
|
||||
button_device_delete_action = partial(self.delete)
|
||||
button_device_delete = ttk.Button(self.buttons, text="Delete", style="Accent.TButton", width=11, command=button_device_delete_action)
|
||||
button_device_delete.grid(column=1, row=0, sticky=W)
|
||||
|
||||
if self.name_before == configGet("name"):
|
||||
configSet(["name"], self.name)
|
||||
|
||||
if self.name == configGet("name"):
|
||||
button_device_delete.state(["disabled"])
|
||||
|
||||
def rename_cancel(self):
|
||||
|
||||
for widget in self.winfo_children():
|
||||
if isinstance(widget, ttk.Entry):
|
||||
widget.destroy()
|
||||
|
||||
device_title = ttk.Label(self, text=self.name, font=("SunValleyBodyFont", 12), justify=LEFT, width=46)
|
||||
device_title.grid(column=0, row=0, padx=9, pady=9, sticky=W)
|
||||
|
||||
button_device_rename_action = partial(self.rename)
|
||||
button_device_rename = ttk.Button(self.buttons, text="Rename", width=11, command=button_device_rename_action)
|
||||
button_device_rename.grid(column=0, row=0, padx=9, sticky=E)
|
||||
|
||||
button_device_delete_action = partial(self.delete)
|
||||
button_device_delete = ttk.Button(self.buttons, text="Delete", style="Accent.TButton", width=11, command=button_device_delete_action)
|
||||
button_device_delete.grid(column=1, row=0, sticky=W)
|
||||
|
||||
if self.name == configGet("name"):
|
||||
button_device_delete.state(["disabled"])
|
||||
|
||||
def delete(self):
|
||||
|
||||
decision = askyesno(title="Device removal", message=f"You are about to remove the device '{self.name}' and this will also remove all the save files uploaded by this device. Are you sure you want to continue?")
|
||||
|
||||
if decision is False:
|
||||
return
|
||||
|
||||
requests.delete(f'{configGet("address")}/devices/{self.name}', headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed"))
|
||||
|
||||
for k in range(len(self.master.devices)):
|
||||
if self.master.devices[k]["name"] == self.name:
|
||||
del self.master.devices[k]
|
||||
break
|
||||
|
||||
self.destroy()
|
||||
from classes.frames.device import FrameDevice
|
||||
|
||||
|
||||
class FrameDevices(ScrollableFrame):
|
||||
@ -164,14 +15,8 @@ class FrameDevices(ScrollableFrame):
|
||||
|
||||
master.title("Devices - Stardew Sync")
|
||||
|
||||
# self["borderwidth"] = 1
|
||||
# self["relief"] = "solid"
|
||||
|
||||
self.devices = devices
|
||||
|
||||
# self.grid_columnconfigure(0, weight=1)
|
||||
# self.grid_rowconfigure(0, weight=2)
|
||||
|
||||
master.columnconfigure(1, weight=1)
|
||||
|
||||
self.render_devices()
|
||||
@ -183,36 +28,6 @@ class FrameDevices(ScrollableFrame):
|
||||
|
||||
device_frame = FrameDevice(self, device_dict=device)
|
||||
device_frame.grid(column=0, row=i, pady=9, padx=9, sticky=NSEW)
|
||||
|
||||
# self.device_frame["borderwidth"] = 1
|
||||
# self.device_frame["relief"] = "solid"
|
||||
|
||||
# device_frame.grid_columnconfigure(0, weight=1)
|
||||
# device_frame.grid_columnconfigure(1, weight=3)
|
||||
# device_frame.grid_columnconfigure(2, weight=3)
|
||||
|
||||
# device_title = ttk.Label(device_frame, text=device["name"], font=("SunValleyBodyFont", 12), justify=LEFT, width=46)
|
||||
# device_title.grid(column=0, row=0, padx=9, pady=9, sticky=W)
|
||||
|
||||
# last_upload = "N/A" if device["last_save"] == 0 else datetime.utcfromtimestamp(device["last_save"]).strftime("%d.%m.%Y %H:%M")
|
||||
# device_description = ttk.Label(device_frame, text=f'OS: {device["os"]}\nClient: {device["client"]}\nLast upload: {last_upload}', width=46)
|
||||
# device_description.grid(column=0, row=1, padx=9, pady=9, sticky=W)
|
||||
|
||||
# buttons_frame = ThemedFrame(device_frame)
|
||||
# buttons_frame.grid(column=0, columnspan=2, row=2, sticky=NSEW, padx=9, pady=9)
|
||||
# buttons_frame.grid_columnconfigure(0, weight=1)
|
||||
|
||||
# button_device_rename_action = partial(self.device_rename, device_frame, buttons_frame, device["name"])
|
||||
# button_device_rename = ttk.Button(buttons_frame, text="Rename", width=11, command=button_device_rename_action)
|
||||
# button_device_rename.grid(column=0, row=0, padx=9, sticky=E)
|
||||
|
||||
# button_device_delete_action = partial(self.device_delete, device["name"])
|
||||
# button_device_delete = ttk.Button(buttons_frame, text="Delete", style="Accent.TButton", width=11, command=button_device_delete_action)
|
||||
# button_device_delete.grid(column=1, row=0, sticky=W)
|
||||
|
||||
# if device["name"] == configGet("name"):
|
||||
# # button_device_rename.state(["disabled"])
|
||||
# button_device_delete.state(["disabled"])
|
||||
|
||||
i += 1
|
||||
|
||||
@ -229,9 +44,6 @@ class FrameDevicesEmpty(ThemedFrame):
|
||||
|
||||
master.title("Devices - Stardew Sync")
|
||||
|
||||
# self["borderwidth"] = 1
|
||||
# self["relief"] = "solid"
|
||||
|
||||
self.grid_columnconfigure(0, weight=1)
|
||||
self.grid_rowconfigure(0, weight=2)
|
||||
|
||||
|
37
classes/frames/save.py
Normal file
37
classes/frames/save.py
Normal file
@ -0,0 +1,37 @@
|
||||
from datetime import datetime, timezone
|
||||
from tkinter import LEFT, NSEW, Misc, S, W, ttk
|
||||
|
||||
from classes.custom.themed_frame import ThemedFrame
|
||||
|
||||
|
||||
class FrameSave(ThemedFrame):
|
||||
|
||||
def __init__(self, master: Misc, save_dict: str, **kwargs) -> None:
|
||||
|
||||
super().__init__(master, style="Card.TFrame", **kwargs)
|
||||
|
||||
self.grid_columnconfigure(0, weight=1)
|
||||
self.grid_columnconfigure(1, weight=3)
|
||||
self.grid_columnconfigure(2, weight=3)
|
||||
|
||||
self.title = ttk.Label(self, text=save_dict["data"]["farmer"], font=("SunValleyBodyStrongFont", 12, "bold"), justify=LEFT, width=46)
|
||||
self.title.grid(column=0, row=0, padx=9, pady=9, sticky=W)
|
||||
|
||||
self.description = ttk.Label(self, text=f'Money: {save_dict["data"]["money"]}\nGame version: {save_dict["data"]["game_version"]}\nID: {save_dict["id"]}', width=46)
|
||||
self.description.grid(column=0, row=1, padx=9, pady=9, sticky=W)
|
||||
|
||||
self.buttons = ThemedFrame(self)
|
||||
self.buttons.grid(column=0, columnspan=2, row=2, sticky=NSEW, padx=9, pady=9)
|
||||
self.buttons.grid_columnconfigure(0, weight=1)
|
||||
|
||||
upload_date = datetime.utcfromtimestamp(save_dict["date"]).replace(tzinfo=timezone.utc).astimezone(tz=None)
|
||||
self.last_upload = ttk.Label(self.buttons, text=f'{upload_date.strftime("%A, %d %b %Y")}\nUploaded at {upload_date.strftime("%H:%M")} by {save_dict["device"]}', font=("SunValleyBodyFont", 8), justify=LEFT, width=46)
|
||||
self.last_upload.grid(column=0, row=0, sticky=W+S)
|
||||
|
||||
# self.button_device_rename_action = partial(self.rename)
|
||||
# self.button_device_rename = ttk.Button(self.buttons, text="Rename", width=11, command=self.button_device_rename_action)
|
||||
# self.button_device_rename.grid(column=0, row=0, padx=9, sticky=E)
|
||||
|
||||
#self.button_device_delete_action = partial(self.delete)
|
||||
self.button_device_delete = ttk.Button(self.buttons, text="Synchronize", style="Accent.TButton", width=11) #, command=self.button_device_delete_action)
|
||||
self.button_device_delete.grid(column=1, row=0, sticky=W)
|
@ -1,11 +1,81 @@
|
||||
from tkinter import EW, NS, ttk
|
||||
from os import path, walk
|
||||
from tkinter import NSEW, ttk
|
||||
import xmltodict
|
||||
|
||||
from ttkthemes import ThemedTk
|
||||
|
||||
from classes.custom.scrollable_frame import ScrollableFrame
|
||||
from classes.custom.themed_frame import ThemedFrame
|
||||
from classes.frames.save import FrameSave
|
||||
from modules.utils import configGet
|
||||
|
||||
|
||||
class FrameSaves(ThemedFrame):
|
||||
class FrameSaves(ScrollableFrame):
|
||||
|
||||
def __init__(self, master: ThemedTk, saves: list, **kwargs) -> None:
|
||||
|
||||
super().__init__(master, **kwargs)
|
||||
|
||||
master.title("Saves - Stardew Sync")
|
||||
|
||||
self.saves = saves
|
||||
self.saves_local = []
|
||||
|
||||
for subdir, dirs, files in walk(configGet("saves_location")):
|
||||
try:
|
||||
for dir in dirs:
|
||||
with open(path.join(dir, "SaveGameInfo"), "r", encoding="utf-8") as file:
|
||||
save_dict = xmltodict.parse(file.read())
|
||||
self.saves_local.append(
|
||||
{
|
||||
"id": int(save_dict["SaveGame"]["uniqueIDForThisGame"]),
|
||||
"user": None,
|
||||
"device": configGet("name"),
|
||||
"date": None,
|
||||
"data": {
|
||||
"farmer": save_dict["Farmer"]["name"],
|
||||
"money": int(save_dict["Farmer"]["money"]),
|
||||
"played": int(save_dict["Farmer"]["millisecondsPlayed"]),
|
||||
"save_time": int(save_dict["Farmer"]["saveTime"]),
|
||||
"year": int(save_dict["Farmer"]["yearForSaveGame"]),
|
||||
"season": int(save_dict["Farmer"]["seasonForSaveGame"]),
|
||||
"day": int(save_dict["Farmer"]["dayOfMonthForSaveGame"]),
|
||||
"game_version": save_dict["Farmer"]["gameVersion"]
|
||||
},
|
||||
"file": {
|
||||
"name": None,
|
||||
"uuid": None,
|
||||
"path": None
|
||||
}
|
||||
}
|
||||
)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Merge local and remote saves.
|
||||
# Maybe add something that indicates availability of an
|
||||
# remote update to pull or local new version to push.
|
||||
|
||||
master.columnconfigure(1, weight=1)
|
||||
|
||||
self.render_saves()
|
||||
|
||||
def render_saves(self):
|
||||
|
||||
i = 0
|
||||
for save in self.saves:
|
||||
|
||||
save_frame = FrameSave(self, save_dict=save)
|
||||
save_frame.grid(column=0, row=i, pady=9, padx=9, sticky=NSEW)
|
||||
|
||||
i += 1
|
||||
|
||||
if i+1 != len(self.saves):
|
||||
divider = ttk.Separator(self, orient="horizontal")
|
||||
divider.grid(column=0, row=i+1, pady=9)
|
||||
i += 1
|
||||
|
||||
class FrameSavesEmpty(ThemedFrame):
|
||||
|
||||
def __init__(self, master: ThemedTk, **kwargs) -> None:
|
||||
|
||||
@ -13,13 +83,10 @@ class FrameSaves(ThemedFrame):
|
||||
|
||||
master.title("Saves - Stardew Sync")
|
||||
|
||||
self["borderwidth"] = 2
|
||||
self["relief"] = "solid"
|
||||
self.grid_columnconfigure(0, weight=1)
|
||||
self.grid_rowconfigure(0, weight=2)
|
||||
|
||||
self.inside_frame = ThemedFrame(self)
|
||||
master.columnconfigure(1, weight=1)
|
||||
|
||||
for btn in range(0, 10):
|
||||
ttk.Button(self.inside_frame, text="SAVES "+str(btn)).grid(column=0, row=btn, padx=9, pady=9, sticky=EW)
|
||||
|
||||
self.scrollbar = ttk.Scrollbar(self.inside_frame, orient="vertical")
|
||||
self.scrollbar.grid(column=1, row=0, sticky=NS)
|
||||
self.label = ttk.Label(self, text="No saves found")
|
||||
self.label.grid(column=0, row=0, padx=9, pady=9)
|
3
main.py
3
main.py
@ -1,3 +1,4 @@
|
||||
import locale
|
||||
from os import path
|
||||
from classes.app import App
|
||||
from modules.utils import jsonSave
|
||||
@ -16,6 +17,8 @@ if not path.exists("config.json"):
|
||||
},
|
||||
"config.json"
|
||||
)
|
||||
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
darkdetect~=0.8.0
|
||||
xmltodict~=0.13.0
|
||||
ttkthemes~=3.2.2
|
||||
requests~=2.28.2
|
||||
sv_ttk~=2.4
|
Loading…
Reference in New Issue
Block a user