241 lines
11 KiB
Python
241 lines
11 KiB
Python
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
|
|
|
|
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()
|
|
|
|
|
|
class FrameDevices(ScrollableFrame):
|
|
|
|
def __init__(self, master: ThemedTk, devices: list, **kwargs) -> None:
|
|
|
|
super().__init__(master, **kwargs)
|
|
|
|
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()
|
|
|
|
def render_devices(self):
|
|
|
|
i = 0
|
|
for device in self.devices:
|
|
|
|
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
|
|
|
|
if i+1 != len(self.devices):
|
|
divider = ttk.Separator(self, orient="horizontal")
|
|
divider.grid(column=0, row=i+1, pady=9)
|
|
i += 1
|
|
|
|
class FrameDevicesEmpty(ThemedFrame):
|
|
|
|
def __init__(self, master: ThemedTk, **kwargs) -> None:
|
|
|
|
super().__init__(master, **kwargs)
|
|
|
|
master.title("Devices - Stardew Sync")
|
|
|
|
# self["borderwidth"] = 1
|
|
# self["relief"] = "solid"
|
|
|
|
self.grid_columnconfigure(0, weight=1)
|
|
self.grid_rowconfigure(0, weight=2)
|
|
|
|
master.columnconfigure(1, weight=1)
|
|
|
|
self.label = ttk.Label(self, text="No devices found")
|
|
self.label.grid(column=0, row=0, padx=9, pady=9) |