feat: add license key configuration to settings and update UI with system icons and button bitmaps

This commit is contained in:
Martin Tranberg
2026-03-31 16:48:36 +02:00
parent fa6840de75
commit 784ca755d5

View File

@@ -29,7 +29,8 @@ def load_settings():
"temp_dir": "C:\\Temp_SP",
"language": "da", # da eller en
"favorites": [], # Liste over {id, name, type, drive_id, site_id, path}
"fav_visible": True
"fav_visible": True,
"license_key": ""
}
if not os.path.exists(SETTINGS_FILE):
with open(SETTINGS_FILE, 'w', encoding='utf-8') as f:
@@ -58,15 +59,15 @@ CURRENT_LANG = settings.get("language", "da")
STRINGS = {
"da": {
"title": "SharePoint Explorer",
"btn_back": "Tilbage",
"btn_home": "🏠 Hjem",
"btn_save_changes": "💾 Gem ændringer i SharePoint",
"btn_back": "Tilbage",
"btn_home": "Hjem",
"btn_save_changes": "Gem ændringer i SharePoint",
"btn_login": "Log ind",
"btn_logged_in": "Logget ind",
"btn_refresh": "🔄 Opdater",
"btn_upload_file": "📤 Upload Fil",
"btn_upload_folder": "📁 Upload Mappe",
"btn_new_folder": " Ny Mappe",
"btn_refresh": "Opdater",
"btn_upload_file": "Upload Fil",
"btn_upload_folder": "Upload Mappe",
"btn_new_folder": "Ny Mappe",
"col_name": "Navn",
"col_type": "Type",
"col_size": "Størrelse",
@@ -124,7 +125,7 @@ STRINGS = {
"msg_update_failed_code": "Upload fejlede: {code}",
"msg_unknown_error": "Ukendt fejl",
"type_unknown": "Ukendt",
"btn_settings": "⚙️ Indstillinger",
"btn_settings": "Indstillinger",
"settings_title": "Indstillinger",
"settings_auth_group": "Authentication / API",
"settings_client_id": "App (Client) ID:",
@@ -140,22 +141,25 @@ STRINGS = {
"msg_settings_saved": "Indstillingerne er gemt.",
"msg_restart_required": "Visse ændringer (f.eks. ID'er) træder først i kraft efter genstart.",
"status_login_needed": "Session udløbet. Log ind igen.",
"btn_add_fav": "Tilføj til favoritter",
"btn_remove_fav": "Fjern fra favoritter",
"label_favorites": "Favoritter",
"msg_fav_exists": "'{name}' er allerede i favoritter."
"btn_add_fav": "Tilføj til favoritter",
"btn_remove_fav": "Fjern fra favoritter",
"label_favorites": "Favoritter",
"msg_fav_exists": "'{name}' er allerede i favoritter.",
"settings_license_group": "Licens / Aktivering",
"settings_license_key": "Licensnøgle:",
"settings_license_status": "Status: Ikke aktiveret"
},
"en": {
"title": "SharePoint Explorer",
"btn_back": "Back",
"btn_home": "🏠 Home",
"btn_save_changes": "💾 Save changes to SharePoint",
"btn_back": "Back",
"btn_home": "Home",
"btn_save_changes": "Save changes to SharePoint",
"btn_login": "Login",
"btn_logged_in": "Logged in",
"btn_refresh": "🔄 Refresh",
"btn_upload_file": "📤 Upload File",
"btn_upload_folder": "📁 Upload Folder",
"btn_new_folder": " New Folder",
"btn_refresh": "Refresh",
"btn_upload_file": "Upload File",
"btn_upload_folder": "Upload Folder",
"btn_new_folder": "New Folder",
"col_name": "Name",
"col_type": "Type",
"col_size": "Size",
@@ -213,7 +217,7 @@ STRINGS = {
"msg_update_failed_code": "Upload failed: {code}",
"msg_unknown_error": "Unknown error",
"type_unknown": "Unknown",
"btn_settings": "⚙️ Settings",
"btn_settings": "Settings",
"settings_title": "Settings",
"settings_auth_group": "Authentication / API",
"settings_client_id": "App (Client) ID:",
@@ -229,10 +233,13 @@ STRINGS = {
"msg_settings_saved": "Settings saved.",
"msg_restart_required": "Some changes (e.g., IDs) only take effect after restart.",
"status_login_needed": "Session expired. Please login again.",
"btn_add_fav": "Add to favorites",
"btn_remove_fav": "Remove from favorites",
"label_favorites": "Favorites",
"msg_fav_exists": "'{name}' is already in favorites."
"btn_add_fav": "Add to favorites",
"btn_remove_fav": "Remove from favorites",
"label_favorites": "Favorites",
"msg_fav_exists": "'{name}' is already in favorites.",
"settings_license_group": "License / Activation",
"settings_license_key": "License Key:",
"settings_license_status": "Status: Not activated"
}
}
@@ -291,7 +298,7 @@ class SettingsDialog(wx.Dialog):
def __init__(self, parent, current_settings):
lang = current_settings.get("language", "da")
title = STRINGS[lang].get("settings_title", "Settings")
super().__init__(parent, title=title, size=(520, 620))
super().__init__(parent, title=title, size=(520, 720))
self.settings = current_settings.copy()
self.lang = lang
@@ -345,6 +352,20 @@ class SettingsDialog(wx.Dialog):
inner_vbox.Add(path_sizer, 0, wx.EXPAND | wx.ALL, 10)
# --- Group: License ---
lic_box = wx.StaticBox(panel, label=self.get_txt("settings_license_group"))
lic_sizer = wx.StaticBoxSizer(lic_box, wx.VERTICAL)
lic_sizer.Add(wx.StaticText(panel, label=self.get_txt("settings_license_key")), 0, wx.BOTTOM, 5)
self.license_ctrl = wx.TextCtrl(panel, value=self.settings.get("license_key", ""))
lic_sizer.Add(self.license_ctrl, 0, wx.EXPAND | wx.BOTTOM, 5)
status_txt = wx.StaticText(panel, label=self.get_txt("settings_license_status"))
status_txt.SetForegroundColour(wx.RED)
lic_sizer.Add(status_txt, 0, wx.TOP, 5)
inner_vbox.Add(lic_sizer, 0, wx.EXPAND | wx.ALL, 10)
# --- Group: Language ---
lang_box = wx.StaticBox(panel, label=self.get_txt("settings_lang_group"))
lang_sizer = wx.StaticBoxSizer(lang_box, wx.HORIZONTAL)
@@ -384,6 +405,7 @@ class SettingsDialog(wx.Dialog):
self.settings["tenant_id"] = self.tenant_id_ctrl.GetValue().strip()
self.settings["temp_dir"] = self.temp_dir_picker.GetPath()
self.settings["language"] = "da" if self.lang_choice.GetSelection() == 0 else "en"
self.settings["license_key"] = self.license_ctrl.GetValue().strip()
if not self.settings["client_id"] or not self.settings["tenant_id"]:
wx.MessageBox("Client ID og Tenant ID skal udfyldes.", "Fejl", wx.OK | wx.ICON_ERROR)
@@ -415,12 +437,13 @@ class SharePointApp(wx.Frame):
self.favorites = settings.get("favorites", [])
self.fav_visible = settings.get("fav_visible", True)
# System Ikoner (ArtProvider - mest basale for kompatibilitet)
# System Ikoner (Brug ART_CMN_DIALOG eller ART_TOOLBAR for mere farve på Windows)
self.image_list = wx.ImageList(16, 16)
self.idx_site = self.image_list.Add(wx.ArtProvider.GetBitmap(wx.ART_GO_HOME, wx.ART_OTHER, (16, 16))) # Site (Hus ikon)
self.idx_drive = self.image_list.Add(wx.ArtProvider.GetBitmap(wx.ART_HARDDISK, wx.ART_OTHER, (16, 16))) # Drive
self.idx_folder = self.image_list.Add(wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, (16, 16))) # Folder
self.idx_file = self.image_list.Add(wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, (16, 16))) # File
self.idx_site = self.image_list.Add(wx.ArtProvider.GetBitmap(wx.ART_GO_HOME, wx.ART_CMN_DIALOG, (16, 16))) # Site
self.idx_drive = self.image_list.Add(wx.ArtProvider.GetBitmap(wx.ART_HARDDISK, wx.ART_CMN_DIALOG, (16, 16))) # Drive
self.idx_folder = self.image_list.Add(wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_CMN_DIALOG, (16, 16))) # Folder
self.idx_file = self.image_list.Add(wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_CMN_DIALOG, (16, 16))) # File
self.idx_star = self.image_list.Add(wx.ArtProvider.GetBitmap(wx.ART_ADD_BOOKMARK, wx.ART_CMN_DIALOG, (16, 16))) # Favorit stjerne
# Threading/Sync til filredigering
@@ -469,55 +492,73 @@ class SharePointApp(wx.Frame):
nav_panel = wx.Panel(panel)
nav_hbox = wx.BoxSizer(wx.HORIZONTAL)
self.back_btn = wx.Button(nav_panel, label=self.get_txt("btn_back"), size=(100, 30))
self.back_btn = wx.Button(nav_panel, label=self.get_txt("btn_back"), size=(110, 30))
self.back_btn.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_GO_BACK, wx.ART_BUTTON, (16, 16)))
self.back_btn.SetBitmapMargins((12, 0))
self.back_btn.Disable()
self.back_btn.Bind(wx.EVT_BUTTON, self.go_back)
nav_hbox.Add(self.back_btn, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 10)
self.home_btn = wx.Button(nav_panel, label=self.get_txt("btn_home"), size=(100, 30))
self.home_btn = wx.Button(nav_panel, label=self.get_txt("btn_home"), size=(110, 30))
self.home_btn.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_GO_HOME, wx.ART_BUTTON, (16, 16)))
self.home_btn.SetBitmapMargins((12, 0))
self.home_btn.Disable()
self.home_btn.Bind(wx.EVT_BUTTON, self.load_sites)
nav_hbox.Add(self.home_btn, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
self.refresh_btn = wx.Button(nav_panel, label=self.get_txt("btn_refresh"), size=(100, 30))
self.refresh_btn = wx.Button(nav_panel, label=self.get_txt("btn_refresh"), size=(110, 30))
self.refresh_btn.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_REDO, wx.ART_BUTTON, (16, 16)))
self.refresh_btn.SetBitmapMargins((12, 0))
self.refresh_btn.Disable()
self.refresh_btn.Bind(wx.EVT_BUTTON, self.on_refresh)
nav_hbox.Add(self.refresh_btn, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
# NY KNAP: Gem ændringer (Vises kun ved redigering)
self.done_btn = wx.Button(nav_panel, label=self.get_txt("btn_save_changes"), size=(200, 30))
self.done_btn = wx.Button(nav_panel, label=self.get_txt("btn_save_changes"), size=(250, 30))
self.done_btn.SetBackgroundColour(wx.Colour(255, 69, 0)) # OrangeRed
self.done_btn.SetForegroundColour(wx.WHITE)
self.done_btn.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_BUTTON, (16, 16)))
self.done_btn.SetBitmapMargins((12, 0))
self.done_btn.Hide()
self.done_btn.Bind(wx.EVT_BUTTON, self.on_done_editing_clicked)
nav_hbox.Add(self.done_btn, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 10)
# NYE KNAPPER: Upload og Ny Mappe (Vises kun når man er inde i et drev/mappe)
self.upload_btn = wx.Button(nav_panel, label=self.get_txt("btn_upload_file"), size=(120, 30))
self.upload_btn = wx.Button(nav_panel, label=self.get_txt("btn_upload_file"), size=(130, 30))
self.upload_btn.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_BUTTON, (16, 16)))
self.upload_btn.SetBitmapMargins((12, 0))
self.upload_btn.Hide()
self.upload_btn.Bind(wx.EVT_BUTTON, self.on_upload_clicked)
nav_hbox.Add(self.upload_btn, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
self.upload_folder_btn = wx.Button(nav_panel, label=self.get_txt("btn_upload_folder"), size=(120, 30))
self.upload_folder_btn = wx.Button(nav_panel, label=self.get_txt("btn_upload_folder"), size=(130, 30))
self.upload_folder_btn.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_FOLDER_OPEN, wx.ART_BUTTON, (16, 16)))
self.upload_folder_btn.SetBitmapMargins((12, 0))
self.upload_folder_btn.Hide()
self.upload_folder_btn.Bind(wx.EVT_BUTTON, self.on_upload_folder_clicked)
nav_hbox.Add(self.upload_folder_btn, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
self.new_folder_btn = wx.Button(nav_panel, label=self.get_txt("btn_new_folder"), size=(100, 30))
self.new_folder_btn = wx.Button(nav_panel, label=self.get_txt("btn_new_folder"), size=(120, 30))
self.new_folder_btn.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_NEW_DIR, wx.ART_BUTTON, (16, 16)))
self.new_folder_btn.SetBitmapMargins((12, 0))
self.new_folder_btn.Hide()
self.new_folder_btn.Bind(wx.EVT_BUTTON, self.on_new_folder_clicked)
nav_hbox.Add(self.new_folder_btn, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
nav_hbox.AddStretchSpacer(1)
self.login_btn = wx.Button(nav_panel, label=self.get_txt("btn_login"), size=(120, 30))
self.login_btn = wx.Button(nav_panel, label=self.get_txt("btn_login"), size=(130, 30))
self.login_btn.SetBackgroundColour(wx.Colour(40, 167, 69)) # Grøn
self.login_btn.SetForegroundColour(wx.WHITE)
self.login_btn.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_GO_FORWARD, wx.ART_TOOLBAR, (16, 16)))
self.login_btn.SetBitmapMargins((12, 0))
self.login_btn.Bind(wx.EVT_BUTTON, self.login)
nav_hbox.Add(self.login_btn, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 10)
# INDSTILLINGER KNAP
self.settings_btn = wx.Button(nav_panel, label=self.get_txt("btn_settings"), size=(120, 30))
self.settings_btn = wx.Button(nav_panel, label=self.get_txt("btn_settings"), size=(130, 30))
self.settings_btn.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_REPORT_VIEW, wx.ART_TOOLBAR, (16, 16)))
self.settings_btn.SetBitmapMargins((12, 0))
self.settings_btn.Bind(wx.EVT_BUTTON, self.on_settings_clicked)
nav_hbox.Add(self.settings_btn, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 10)
@@ -558,6 +599,11 @@ class SharePointApp(wx.Frame):
self.fav_header.SetBackgroundColour(wx.Colour(240, 240, 240))
h_hbox = wx.BoxSizer(wx.HORIZONTAL)
# Star Icon
star_bmp = wx.ArtProvider.GetBitmap(wx.ART_ADD_BOOKMARK, wx.ART_MENU, (16, 16))
self.fav_icon = wx.StaticBitmap(self.fav_header, bitmap=star_bmp)
h_hbox.Add(self.fav_icon, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
self.fav_label = wx.StaticText(self.fav_header, label=self.get_txt("label_favorites"))
self.fav_label.SetFont(wx.Font(9, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
h_hbox.Add(self.fav_label, 1, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
@@ -630,33 +676,41 @@ class SharePointApp(wx.Frame):
if item['type'] in ["FOLDER", "DRIVE", "SITE"]:
fav_item = menu.Append(wx.ID_ANY, self.get_txt("btn_add_fav"))
fav_item.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_ADD_BOOKMARK, wx.ART_MENU, (16, 16)))
self.Bind(wx.EVT_MENU, lambda e, i=item: self.add_favorite(i), fav_item)
menu.AppendSeparator()
if item['type'] == "FILE":
edit_item = menu.Append(wx.ID_ANY, self.get_txt("msg_edit_file"))
edit_item.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_EDIT, wx.ART_MENU, (16, 16)))
self.Bind(wx.EVT_MENU, lambda e, i=item: self.open_file(i), edit_item)
if item['type'] in ["FILE", "FOLDER"]:
rename_item = menu.Append(wx.ID_ANY, f"{self.get_txt('msg_rename')} '{item['name']}'")
rename_item.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_REPORT_VIEW, wx.ART_MENU, (16, 16)))
self.Bind(wx.EVT_MENU, lambda e: self.on_rename_clicked(item), rename_item)
delete_item = menu.Append(wx.ID_ANY, f"{self.get_txt('msg_delete')} '{item['name']}'")
delete_item.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_DELETE, wx.ART_MENU, (16, 16)))
self.Bind(wx.EVT_MENU, lambda e: self.on_delete_items_clicked(selected_items), delete_item)
else:
# Flere emner valgt
delete_items = menu.Append(wx.ID_ANY, f"{self.get_txt('msg_delete')} {len(selected_indices)} " + ("emner" if self.lang == "da" else "items"))
delete_items.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_DELETE, wx.ART_MENU, (16, 16)))
self.Bind(wx.EVT_MENU, lambda e: self.on_delete_items_clicked(selected_items), delete_items)
else:
# Menu for selve mappen (hvis man trykker på det tomme felt)
if self.current_drive_id:
upload_item = menu.Append(wx.ID_ANY, self.get_txt("msg_upload_here"))
upload_item.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_MENU, (16, 16)))
self.Bind(wx.EVT_MENU, self.on_upload_clicked, upload_item)
upload_dir_item = menu.Append(wx.ID_ANY, self.get_txt("msg_upload_folder_here"))
upload_dir_item.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_FOLDER_OPEN, wx.ART_MENU, (16, 16)))
self.Bind(wx.EVT_MENU, self.on_upload_folder_clicked, upload_dir_item)
new_folder_item = menu.Append(wx.ID_ANY, self.get_txt("msg_new_folder_here"))
new_folder_item.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_NEW_DIR, wx.ART_MENU, (16, 16)))
self.Bind(wx.EVT_MENU, self.on_new_folder_clicked, new_folder_item)
# Tilføj altid opdater punkt til sidst
@@ -664,6 +718,7 @@ class SharePointApp(wx.Frame):
menu.AppendSeparator()
refresh_item = menu.Append(wx.ID_ANY, self.get_txt("btn_refresh"))
refresh_item.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_REDO, wx.ART_MENU, (16, 16)))
self.Bind(wx.EVT_MENU, self.on_refresh, refresh_item)
self.PopupMenu(menu)
@@ -679,10 +734,12 @@ class SharePointApp(wx.Frame):
menu = wx.Menu()
if data:
fav_item = menu.Append(wx.ID_ANY, self.get_txt("btn_add_fav"))
fav_item.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_ADD_BOOKMARK, wx.ART_MENU, (16, 16)))
self.Bind(wx.EVT_MENU, lambda e, d=data: self.add_favorite(d), fav_item)
menu.AppendSeparator()
refresh_item = menu.Append(wx.ID_ANY, self.get_txt("btn_refresh"))
refresh_item.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_REDO, wx.ART_MENU, (16, 16)))
self.Bind(wx.EVT_MENU, self.on_refresh, refresh_item)
self.PopupMenu(menu)
menu.Destroy()
@@ -720,9 +777,10 @@ class SharePointApp(wx.Frame):
def refresh_fav_list(self):
self.fav_list.DeleteAllItems()
for i, fav in enumerate(self.favorites):
img_idx = self.idx_folder
img_idx = self.idx_star
if fav['type'] == "DRIVE": img_idx = self.idx_drive
elif fav['type'] == "SITE": img_idx = self.idx_site
elif fav['type'] == "FOLDER": img_idx = self.idx_folder
self.fav_list.InsertItem(i, fav['name'], img_idx)
self.fav_list.SetItemData(i, i) # Store index
@@ -758,6 +816,7 @@ class SharePointApp(wx.Frame):
menu = wx.Menu()
remove_item = menu.Append(wx.ID_ANY, self.get_txt("btn_remove_fav"))
remove_item.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_DEL_BOOKMARK, wx.ART_MENU, (16, 16)))
self.Bind(wx.EVT_MENU, lambda e: self.remove_favorite(fav['id']), remove_item)
self.PopupMenu(menu)
menu.Destroy()