feat: add file and folder download functionality to context menu
This commit is contained in:
@@ -87,6 +87,9 @@ STRINGS = {
|
|||||||
"msg_rename_prompt": "Indtast det nye navn for '{name}':",
|
"msg_rename_prompt": "Indtast det nye navn for '{name}':",
|
||||||
"msg_rename_title": "Omdøb emne",
|
"msg_rename_title": "Omdøb emne",
|
||||||
"msg_open_browser": "Åbn i browser",
|
"msg_open_browser": "Åbn i browser",
|
||||||
|
"msg_download": "Download",
|
||||||
|
"msg_downloading_to": "Downloader '{name}' til '{path}'...",
|
||||||
|
"msg_download_done": "'{name}' downloadet færdig.",
|
||||||
"msg_upload_here": "Upload fil her",
|
"msg_upload_here": "Upload fil her",
|
||||||
"msg_upload_folder_here": "Upload mappe her",
|
"msg_upload_folder_here": "Upload mappe her",
|
||||||
"msg_new_folder_here": "Opret ny mappe her",
|
"msg_new_folder_here": "Opret ny mappe her",
|
||||||
@@ -153,6 +156,9 @@ STRINGS = {
|
|||||||
"msg_rename_prompt": "Enter new name for '{name}':",
|
"msg_rename_prompt": "Enter new name for '{name}':",
|
||||||
"msg_rename_title": "Rename item",
|
"msg_rename_title": "Rename item",
|
||||||
"msg_open_browser": "Open in browser",
|
"msg_open_browser": "Open in browser",
|
||||||
|
"msg_download": "Download",
|
||||||
|
"msg_downloading_to": "Downloading '{name}' to '{path}'...",
|
||||||
|
"msg_download_done": "'{name}' download finished.",
|
||||||
"msg_upload_here": "Upload file here",
|
"msg_upload_here": "Upload file here",
|
||||||
"msg_upload_folder_here": "Upload folder here",
|
"msg_upload_folder_here": "Upload folder here",
|
||||||
"msg_new_folder_here": "Create new folder here",
|
"msg_new_folder_here": "Create new folder here",
|
||||||
@@ -412,6 +418,10 @@ class SharePointApp(wx.Frame):
|
|||||||
if item.get("web_url"):
|
if item.get("web_url"):
|
||||||
browser_item = menu.Append(wx.ID_ANY, self.get_txt("msg_open_browser"))
|
browser_item = menu.Append(wx.ID_ANY, self.get_txt("msg_open_browser"))
|
||||||
self.Bind(wx.EVT_MENU, lambda e: webbrowser.open(item["web_url"]), browser_item)
|
self.Bind(wx.EVT_MENU, lambda e: webbrowser.open(item["web_url"]), browser_item)
|
||||||
|
|
||||||
|
download_item = menu.Append(wx.ID_ANY, self.get_txt("msg_download"))
|
||||||
|
self.Bind(wx.EVT_MENU, lambda e: self.on_download_clicked(item), download_item)
|
||||||
|
|
||||||
menu.AppendSeparator()
|
menu.AppendSeparator()
|
||||||
|
|
||||||
if item['type'] == "FILE":
|
if item['type'] == "FILE":
|
||||||
@@ -587,6 +597,60 @@ class SharePointApp(wx.Frame):
|
|||||||
self.set_status(self.get_txt("msg_error"))
|
self.set_status(self.get_txt("msg_error"))
|
||||||
wx.CallAfter(wx.MessageBox, f"Rename failed: {res.status_code}", self.get_txt("msg_error"), wx.OK | wx.ICON_ERROR)
|
wx.CallAfter(wx.MessageBox, f"Rename failed: {res.status_code}", self.get_txt("msg_error"), wx.OK | wx.ICON_ERROR)
|
||||||
|
|
||||||
|
def on_download_clicked(self, item):
|
||||||
|
if not self.ensure_valid_token(): return
|
||||||
|
|
||||||
|
if item['type'] == "FILE":
|
||||||
|
with wx.FileDialog(self, self.get_txt("msg_select_file"), defaultFile=item['name'], style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as fd:
|
||||||
|
if fd.ShowModal() == wx.ID_OK:
|
||||||
|
path = fd.GetPath()
|
||||||
|
threading.Thread(target=self._download_file_bg_task, args=(item, path), daemon=True).start()
|
||||||
|
else:
|
||||||
|
# Mappe eller Drev
|
||||||
|
with wx.DirDialog(self, self.get_txt("msg_select_folder"), style=wx.DD_DEFAULT_STYLE | wx.DD_DIR_MUST_EXIST) as dd:
|
||||||
|
if dd.ShowModal() == wx.ID_OK:
|
||||||
|
parent_path = dd.GetPath()
|
||||||
|
dest_path = os.path.join(parent_path, item['name'])
|
||||||
|
threading.Thread(target=self._download_folder_bg_task, args=(item, dest_path), daemon=True).start()
|
||||||
|
|
||||||
|
def _download_file_bg_task(self, item, dest_path):
|
||||||
|
if not self.ensure_valid_token(): return
|
||||||
|
self.set_status(self.get_txt("msg_downloading_to", name=item['name'], path=dest_path))
|
||||||
|
if self._download_file_sync_call(item['drive_id'], item['id'], dest_path):
|
||||||
|
self.set_status(self.get_txt("msg_download_done", name=item['name']))
|
||||||
|
else:
|
||||||
|
self.set_status(self.get_txt("msg_error"))
|
||||||
|
|
||||||
|
def _download_file_sync_call(self, drive_id, item_id, dest_path):
|
||||||
|
url = f"https://graph.microsoft.com/v1.0/drives/{drive_id}/items/{item_id}/content"
|
||||||
|
res = requests.get(url, headers=self.headers)
|
||||||
|
if res.status_code == 200:
|
||||||
|
with open(dest_path, 'wb') as f:
|
||||||
|
f.write(res.content)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _download_folder_bg_task(self, item, dest_path):
|
||||||
|
if not self.ensure_valid_token(): return
|
||||||
|
self.set_status(self.get_txt("msg_downloading_to", name=item['name'], path=dest_path))
|
||||||
|
self._download_folder_recursive_sync(item['drive_id'], item['id'], dest_path)
|
||||||
|
self.set_status(self.get_txt("msg_download_done", name=item['name']))
|
||||||
|
|
||||||
|
def _download_folder_recursive_sync(self, drive_id, folder_id, local_dir):
|
||||||
|
if not os.path.exists(local_dir):
|
||||||
|
os.makedirs(local_dir)
|
||||||
|
|
||||||
|
url = f"https://graph.microsoft.com/v1.0/drives/{drive_id}/items/{folder_id}/children"
|
||||||
|
res = requests.get(url, headers=self.headers)
|
||||||
|
if res.status_code == 200:
|
||||||
|
items = res.json().get('value', [])
|
||||||
|
for item in items:
|
||||||
|
item_path = os.path.join(local_dir, item['name'])
|
||||||
|
if 'folder' in item:
|
||||||
|
self._download_folder_recursive_sync(drive_id, item['id'], item_path)
|
||||||
|
else:
|
||||||
|
self._download_file_sync_call(drive_id, item['id'], item_path)
|
||||||
|
|
||||||
def set_status(self, text):
|
def set_status(self, text):
|
||||||
wx.CallAfter(self.status_bar.SetStatusText, text)
|
wx.CallAfter(self.status_bar.SetStatusText, text)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user