Skip to content

Commit

Permalink
Close "Received Files" modal if an error occurs
Browse files Browse the repository at this point in the history
For #13
  • Loading branch information
peterstory committed Jul 23, 2024
1 parent ce72bec commit f9c0604
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 96 deletions.
99 changes: 99 additions & 0 deletions src/pydiode/gui/common.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,107 @@
import os
from pathlib import Path
import signal
import subprocess
import sys
from tkinter import Toplevel, ttk
from tkinter.messagebox import showerror

# Check subprocesses every SLEEP milliseconds
SLEEP = 250


class SavedWindow:
# A modal window shown after files were received
top = None

# Whether to show the window. Configured as a BooleanVar in gui_main().
should_show = None

@classmethod
def on_ok(cls, event=None):
if cls.top:
cls.top.destroy()

@classmethod
def on_show_files(cls, target_dir):
# Based on: https://stackoverflow.com/a/17317468/3043071
if sys.platform == "win32":
os.startfile(target_dir)
else:
opener = "open" if sys.platform == "darwin" else "xdg-open"
subprocess.run([opener, target_dir])
cls.top.destroy()

@classmethod
def show_window(cls, root, target_dir):
# Only create a window if:
# - The user didn't permanently dismiss the window and
# - The window hasn't yet been created, or it was destroyed
if cls.should_show.get() and (
not cls.top or not cls.top.winfo_exists()
):
cls.top = Toplevel(root)
cls.top.grid_rowconfigure(0, weight=1)
cls.top.grid_columnconfigure(0, weight=1)
cls.top.title("Received Files")

ttk.Label(
cls.top, text=f"Saved files to: {Path(target_dir).name}"
).grid(column=0, row=0, columnspan=3, pady=(15, 0))

ttk.Checkbutton(
cls.top,
text="Do not show again",
variable=cls.should_show,
onvalue=False,
offvalue=True,
).grid(column=0, row=1, padx=10, pady=10)

show_files_button = ttk.Button(
cls.top,
text="Show Files",
command=lambda: cls.on_show_files(target_dir),
)
show_files_button.grid(column=1, row=1, pady=10)

ok_button = ttk.Button(
cls.top, text="OK", default="active", command=cls.on_ok
)
ok_button.grid(column=2, row=1, padx=10, pady=10)

# Dismiss if escape or return are pressed
cls.top.bind("<Escape>", cls.on_ok)
cls.top.bind("<Return>", cls.on_ok)

# Use modal style on macOS
if sys.platform == "darwin":
cls.top.tk.call(
"::tk::unsupported::MacWindowStyle",
"style",
cls.top._w,
"modal",
)

# Set the modal's minimum size, and center it over the main window.
# If the size exceeds these dimensions, the modal won't be
# perfectly centered.
width = 400
height = 100
cls.top.minsize(width=width, height=height)
x = root.winfo_x() + (root.winfo_width() // 2) - (width // 2)
y = root.winfo_y() + (root.winfo_height() // 2) - (height // 4)
cls.top.geometry(f"+{x}+{y}")

# Prevent resizing
cls.top.resizable(False, False)

# Stay on top of the main window
cls.top.transient(root)

# Take focus
cls.top.grab_set()


class ProcessPipeline:

def __init__(self):
Expand Down Expand Up @@ -190,6 +286,9 @@ def check_subprocesses(
# If any subprocesses exited irregularly, describe the issue
error_msgs = pipeline.get_process_errors()
if error_msgs:
# Dismiss the "Received Files" window, if it's open
SavedWindow.on_ok()
# Show the error message
showerror(title="Error", message=error_msgs)
# Clear the pipeline, so it doesn't grow as more subprocesses are
# started
Expand Down
102 changes: 6 additions & 96 deletions src/pydiode/gui/receive.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import os
from pathlib import Path
import subprocess
import sys
from tkinter import Toplevel, ttk
from tkinter.filedialog import askdirectory
from tkinter.messagebox import showinfo

from pydiode.gui.common import check_subprocesses, ProcessPipeline, SLEEP
from pydiode.gui.common import (
check_subprocesses,
ProcessPipeline,
SavedWindow,
SLEEP,
)

# Information about our subprocesses
RECEIVE_PIPELINE = ProcessPipeline()
Expand Down Expand Up @@ -68,97 +69,6 @@ def receive_or_cancel(
)


class SavedWindow:
# A modal window shown after files were received
top = None

# Whether to show the window. Configured as a BooleanVar in gui_main().
should_show = None

@classmethod
def on_ok(cls, event=None):
cls.top.destroy()

@classmethod
def on_show_files(cls, target_dir):
# Based on: https://stackoverflow.com/a/17317468/3043071
if sys.platform == "win32":
os.startfile(target_dir)
else:
opener = "open" if sys.platform == "darwin" else "xdg-open"
subprocess.run([opener, target_dir])
cls.top.destroy()

@classmethod
def show_window(cls, root, target_dir):
# Only create a window if:
# - The user didn't permanently dismiss the window and
# - The window hasn't yet been created, or it was destroyed
if cls.should_show.get() and (
not cls.top or not cls.top.winfo_exists()
):
cls.top = Toplevel(root)
cls.top.grid_rowconfigure(0, weight=1)
cls.top.grid_columnconfigure(0, weight=1)
cls.top.title("Received Files")

ttk.Label(
cls.top, text=f"Saved files to: {Path(target_dir).name}"
).grid(column=0, row=0, columnspan=3, pady=(15, 0))

ttk.Checkbutton(
cls.top,
text="Do not show again",
variable=cls.should_show,
onvalue=False,
offvalue=True,
).grid(column=0, row=1, padx=10, pady=10)

show_files_button = ttk.Button(
cls.top,
text="Show Files",
command=lambda: cls.on_show_files(target_dir),
)
show_files_button.grid(column=1, row=1, pady=10)

ok_button = ttk.Button(
cls.top, text="OK", default="active", command=cls.on_ok
)
ok_button.grid(column=2, row=1, padx=10, pady=10)

# Dismiss if escape or return are pressed
cls.top.bind("<Escape>", cls.on_ok)
cls.top.bind("<Return>", cls.on_ok)

# Use modal style on macOS
if sys.platform == "darwin":
cls.top.tk.call(
"::tk::unsupported::MacWindowStyle",
"style",
cls.top._w,
"modal",
)

# Set the modal's minimum size, and center it over the main window.
# If the size exceeds these dimensions, the modal won't be
# perfectly centered.
width = 400
height = 100
cls.top.minsize(width=width, height=height)
x = root.winfo_x() + (root.winfo_width() // 2) - (width // 2)
y = root.winfo_y() + (root.winfo_height() // 2) - (height // 4)
cls.top.geometry(f"+{x}+{y}")

# Prevent resizing
cls.top.resizable(False, False)

# Stay on top of the main window
cls.top.transient(root)

# Take focus
cls.top.grab_set()


def receive_files(
root,
target_dir,
Expand Down

0 comments on commit f9c0604

Please sign in to comment.