From d3a7ce69e97922c5d46704a4902b8a506211933b Mon Sep 17 00:00:00 2001 From: Martin Tranberg Date: Mon, 30 Mar 2026 19:49:16 +0200 Subject: [PATCH] feat: implement UI locking and prevent application exit during active file editing sessions --- sharepoint_browser.py | 81 ++++++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 21 deletions(-) diff --git a/sharepoint_browser.py b/sharepoint_browser.py index e144b4a..c219aad 100644 --- a/sharepoint_browser.py +++ b/sharepoint_browser.py @@ -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()