feat: implement UI locking and prevent application exit during active file editing sessions

This commit is contained in:
Martin Tranberg
2026-03-30 19:49:16 +02:00
parent 2b82a7aa5c
commit d3a7ce69e9

View File

@@ -62,6 +62,7 @@ class SharePointApp(wx.Frame):
self.tree_item_data = {} # Mappenoder -> {type, id, name, drive_id, path}
self.tree_root = None
self.is_navigating_back = False
self.is_editing = False # Låse-state ved filredigering
# System Ikoner (ArtProvider - mest basale for kompatibilitet)
self.image_list = wx.ImageList(16, 16)
@@ -76,6 +77,7 @@ class SharePointApp(wx.Frame):
self.InitUI()
self.Centre()
self.Show()
self.Bind(wx.EVT_CLOSE, self.on_close_window)
def InitUI(self):
panel = wx.Panel(self)
@@ -195,6 +197,29 @@ class SharePointApp(wx.Frame):
self.edit_wait_event.set()
self.info_bar.Dismiss()
def on_close_window(self, event):
if self.is_editing:
self.show_info("Du er i gang med at redigere en fil. Luk din editor og gem ændringerne før du lukker programmet.", wx.ICON_WARNING, auto_hide=False)
return
event.Skip()
def lock_ui(self, lock=True):
def _do():
self.tree_ctrl.Enable(not lock)
self.list_ctrl.Enable(not lock)
self.back_btn.Enable(not lock if len(self.history) > 1 else False)
self.home_btn.Enable(not lock)
self.login_btn.Enable(not lock)
wx.CallAfter(_do)
def _refresh_current_view(self):
sel = self.tree_ctrl.GetSelection()
if sel.IsOk():
data = self.tree_item_data.get(sel)
if data:
# Kør i nuværende baggrundstråd hvis muligt, ellers ny
self._fetch_list_contents_bg(data)
def clear_main(self):
self.list_ctrl.DeleteAllItems()
self.current_items = []
@@ -382,6 +407,7 @@ class SharePointApp(wx.Frame):
self.tree_ctrl.SelectItem(target_node)
def on_tree_selected(self, event):
if self.is_editing: return
item = event.GetItem()
data = self.tree_item_data.get(item)
if not data:
@@ -462,8 +488,9 @@ class SharePointApp(wx.Frame):
self.current_folder_id = parent_data['id']
def on_item_activated(self, event):
idx = event.GetIndex()
item = self.current_items[idx]
if self.is_editing: return
item_idx = event.GetIndex()
item = self.current_items[item_idx]
if item['type'] in ["SITE", "DRIVE", "FOLDER"]:
self._sync_tree_selection(item['id'])
@@ -489,6 +516,7 @@ class SharePointApp(wx.Frame):
child, cookie = self.tree_ctrl.GetNextChild(selected, cookie)
def go_back(self, event=None):
if self.is_editing: return
if len(self.history) > 1:
self.history.pop() # Remove current
prev_item = self.history[-1] # Peak at previous
@@ -497,28 +525,33 @@ class SharePointApp(wx.Frame):
self.is_navigating_back = False
def process_file(self, item_id, file_name):
base_url = f"https://graph.microsoft.com/v1.0/drives/{self.current_drive_id}/items/{item_id}"
self.is_editing = True
self.lock_ui(True)
try:
# 1. Checkout
self.set_status(f"Tjekker '{file_name}' ud...")
checkout_res = requests.post(f"{base_url}/checkout", headers=self.headers)
# 1. Lokation info
site_id = self.current_site_id
drive_id = self.current_drive_id
base_url = f"https://graph.microsoft.com/v1.0/sites/{site_id}/drives/{drive_id}/items/{item_id}"
# Unik undermappe baseret på ID, men brug originalt filnavn indeni
item_hash = hashlib.md5(item_id.encode()).hexdigest()[:8]
working_dir = os.path.join(TEMP_DIR, item_hash)
if not os.path.exists(working_dir):
os.makedirs(working_dir)
local_path = os.path.join(working_dir, file_name)
# 2. Download
self.set_status(f"Downloader '{file_name}'...")
self.set_status(f"Henter '{file_name}'...")
res = requests.get(f"{base_url}/content", headers=self.headers)
if res.status_code != 200:
raise Exception(f"Download fejlede: {res.status_code}")
short_hash = hashlib.md5(item_id.encode()).hexdigest()[:8]
file_dir = os.path.join(TEMP_DIR, short_hash)
if not os.path.exists(file_dir):
os.makedirs(file_dir)
local_path = os.path.join(file_dir, file_name)
raise Exception(f"Kunne ikke hente fil: {res.status_code}")
with open(local_path, 'wb') as f:
f.write(res.content)
# Checkout
requests.post(f"{base_url}/checkout", headers=self.headers)
# 3. Åbn & Overvåg
self.set_status(f"Åbner '{file_name}'...")
@@ -548,8 +581,6 @@ class SharePointApp(wx.Frame):
self.edit_wait_event.clear()
wx.CallAfter(self.done_btn.Show)
wx.CallAfter(self.Layout)
self.show_info(f"Vi kan ikke se om du har gemt '{file_name}'. Klik på den orange knap øverst når du er færdig.", wx.ICON_WARNING, auto_hide=False)
# Vent på event (fra done_btn knap)
self.edit_wait_event.wait()
wx.CallAfter(self.done_btn.Hide)
wx.CallAfter(self.Layout)
@@ -565,15 +596,23 @@ class SharePointApp(wx.Frame):
self.set_status(f"Tjekker '{file_name}' ind...")
requests.post(f"{base_url}/checkin", headers=self.headers, json={"comment": "Opdateret via SP Explorer"})
os.remove(local_path)
# Oprydning: Slet fil og derefter mappe
try:
os.remove(local_path)
os.rmdir(working_dir)
except:
pass
self.set_status(f"Succes! '{file_name}' er opdateret.")
self.show_info(f"Filen '{file_name}' er gemt og tjekket ind korrekt.", wx.ICON_INFORMATION)
self._refresh_current_view()
except Exception as e:
self.set_status(f"Fejl: {str(e)}")
self.show_info(f"Der skete en fejl: {e}", wx.ICON_ERROR)
finally:
self.is_editing = False
self.lock_ui(False)
if __name__ == "__main__":
app = wx.App()