SyncTk/classes/frames/devices.py

241 lines
11 KiB
Python
Raw Normal View History

2023-01-23 01:13:30 +02:00
from datetime import datetime
from functools import partial
2023-01-25 15:01:13 +02:00
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
2023-01-22 18:53:55 +02:00
2023-01-23 01:13:30 +02:00
import requests
2023-01-22 18:53:55 +02:00
from ttkthemes import ThemedTk
2023-01-23 01:13:30 +02:00
from classes.custom.scrollable_frame import ScrollableFrame
2023-01-22 18:53:55 +02:00
from classes.custom.themed_frame import ThemedFrame
2023-01-25 15:01:13 +02:00
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()
2023-01-22 18:53:55 +02:00
2023-01-23 01:13:30 +02:00
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:
2023-01-25 15:01:13 +02:00
device_frame = FrameDevice(self, device_dict=device)
2023-01-23 01:13:30 +02:00
device_frame.grid(column=0, row=i, pady=9, padx=9, sticky=NSEW)
# self.device_frame["borderwidth"] = 1
# self.device_frame["relief"] = "solid"
2023-01-25 15:01:13 +02:00
# device_frame.grid_columnconfigure(0, weight=1)
# device_frame.grid_columnconfigure(1, weight=3)
# device_frame.grid_columnconfigure(2, weight=3)
2023-01-23 01:13:30 +02:00
2023-01-25 15:01:13 +02:00
# 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)
2023-01-23 01:13:30 +02:00
2023-01-25 15:01:13 +02:00
# 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)
2023-01-23 01:13:30 +02:00
2023-01-25 15:01:13 +02:00
# 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)
2023-01-23 01:13:30 +02:00
2023-01-25 15:01:13 +02:00
# 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)
2023-01-23 01:13:30 +02:00
2023-01-25 15:01:13 +02:00
# 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)
2023-01-23 01:13:30 +02:00
2023-01-25 15:01:13 +02:00
# if device["name"] == configGet("name"):
# # button_device_rename.state(["disabled"])
# button_device_delete.state(["disabled"])
2023-01-23 01:13:30 +02:00
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):
2023-01-22 18:53:55 +02:00
def __init__(self, master: ThemedTk, **kwargs) -> None:
super().__init__(master, **kwargs)
master.title("Devices - Stardew Sync")
2023-01-23 01:13:30 +02:00
# self["borderwidth"] = 1
# self["relief"] = "solid"
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=2)
2023-01-22 18:53:55 +02:00
2023-01-23 01:13:30 +02:00
master.columnconfigure(1, weight=1)
2023-01-22 18:53:55 +02:00
2023-01-23 01:13:30 +02:00
self.label = ttk.Label(self, text="No devices found")
self.label.grid(column=0, row=0, padx=9, pady=9)