feat: implement natural sorting and column-based list view sorting with visual indicators
This commit is contained in:
@@ -9,6 +9,7 @@ import msal
|
||||
import wx
|
||||
import wx.lib.newevent
|
||||
import webbrowser
|
||||
import re
|
||||
|
||||
# --- STIHÅNDTERING (Til EXE-brug) ---
|
||||
if getattr(sys, 'frozen', False):
|
||||
@@ -246,6 +247,10 @@ STRINGS = {
|
||||
if not os.path.exists(TEMP_DIR):
|
||||
os.makedirs(TEMP_DIR)
|
||||
|
||||
def natural_sort_key(s):
|
||||
return [int(text) if text.isdigit() else text.lower()
|
||||
for text in re.split('([0-9]+)', str(s))]
|
||||
|
||||
class UploadDropTarget(wx.FileDropTarget):
|
||||
def __init__(self, window, app):
|
||||
wx.FileDropTarget.__init__(self)
|
||||
@@ -436,14 +441,25 @@ class SharePointApp(wx.Frame):
|
||||
self.active_edits = {} # item_id -> { "name": name, "event": Event, "waiting": bool }
|
||||
self.favorites = settings.get("favorites", [])
|
||||
self.fav_visible = settings.get("fav_visible", True)
|
||||
self.sort_col = 0 # Default Name
|
||||
self.sort_asc = True
|
||||
|
||||
# System Ikoner (Brug ART_CMN_DIALOG eller ART_TOOLBAR for mere farve på Windows)
|
||||
# System Ikoner
|
||||
self.image_list = wx.ImageList(16, 16)
|
||||
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
|
||||
|
||||
def add_icon(art_id, client=wx.ART_CMN_DIALOG):
|
||||
bmp = wx.ArtProvider.GetBitmap(art_id, client, (16, 16))
|
||||
if not bmp.IsOk():
|
||||
bmp = wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, client, (16, 16)) # Fallback
|
||||
return self.image_list.Add(bmp)
|
||||
|
||||
self.idx_site = add_icon(wx.ART_GO_HOME)
|
||||
self.idx_drive = add_icon(wx.ART_HARDDISK)
|
||||
self.idx_folder = add_icon(wx.ART_FOLDER)
|
||||
self.idx_file = add_icon(wx.ART_NORMAL_FILE)
|
||||
self.idx_star = add_icon(wx.ART_ADD_BOOKMARK)
|
||||
self.idx_up = add_icon(wx.ART_GO_UP, wx.ART_TOOLBAR)
|
||||
self.idx_down = add_icon(wx.ART_GO_DOWN, wx.ART_TOOLBAR)
|
||||
|
||||
# Threading/Sync til filredigering
|
||||
|
||||
@@ -638,6 +654,7 @@ class SharePointApp(wx.Frame):
|
||||
self.list_ctrl.InsertColumn(3, self.get_txt("col_modified"), width=180)
|
||||
|
||||
self.list_ctrl.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.on_item_activated)
|
||||
self.list_ctrl.Bind(wx.EVT_LIST_COL_CLICK, self.on_column_click)
|
||||
self.list_ctrl.Bind(wx.EVT_CONTEXT_MENU, self.on_right_click)
|
||||
|
||||
# AKTIVER DRAG & DROP
|
||||
@@ -1483,25 +1500,73 @@ class SharePointApp(wx.Frame):
|
||||
|
||||
wx.CallAfter(self._populate_list_ctrl, items_data, data)
|
||||
|
||||
def on_column_click(self, event):
|
||||
col = event.GetColumn()
|
||||
if col == self.sort_col:
|
||||
self.sort_asc = not self.sort_asc
|
||||
else:
|
||||
self.sort_col = col
|
||||
self.sort_asc = True
|
||||
|
||||
self.apply_sorting()
|
||||
|
||||
def apply_sorting(self):
|
||||
if not self.current_items: return
|
||||
|
||||
# Priority: SITE < DRIVE < FOLDER < FILE
|
||||
type_prio = {"SITE": 0, "DRIVE": 1, "FOLDER": 2, "FILE": 3}
|
||||
|
||||
def sort_logic(item):
|
||||
# Altid grupper efter type først (mapper øverst)
|
||||
p = type_prio.get(item['type'], 9)
|
||||
|
||||
val = ""
|
||||
if self.sort_col == 0: # Name
|
||||
val = natural_sort_key(item['name'])
|
||||
elif self.sort_col == 1: # Type
|
||||
val = item['type']
|
||||
elif self.sort_col == 2: # Size
|
||||
val = item['size'] if item['size'] is not None else -1
|
||||
elif self.sort_col == 3: # Modified
|
||||
val = item['modified']
|
||||
|
||||
return (p, val)
|
||||
|
||||
self.current_items.sort(key=sort_logic, reverse=not self.sort_asc)
|
||||
self._update_list_view_only()
|
||||
|
||||
def _update_list_view_only(self):
|
||||
self.list_ctrl.DeleteAllItems()
|
||||
for i, item in enumerate(self.current_items):
|
||||
img_idx = self.idx_file
|
||||
if item['type'] == "FOLDER": img_idx = self.idx_folder
|
||||
elif item['type'] == "DRIVE": img_idx = self.idx_drive
|
||||
elif item['type'] == "SITE": img_idx = self.idx_site
|
||||
|
||||
self.list_ctrl.InsertItem(i, item['name'], img_idx)
|
||||
type_str = self.get_txt("type_folder") if item['type'] == "FOLDER" else self.get_txt("type_file") if item['type'] == "FILE" else self.get_txt("type_drive")
|
||||
self.list_ctrl.SetItem(i, 1, type_str)
|
||||
size_str = format_size(item['size']) if item['size'] is not None else ""
|
||||
self.list_ctrl.SetItem(i, 2, size_str)
|
||||
self.list_ctrl.SetItem(i, 3, item['modified'])
|
||||
|
||||
# Opdater kolonne ikoner
|
||||
for col in range(4):
|
||||
info = self.list_ctrl.GetColumn(col)
|
||||
if col == self.sort_col:
|
||||
info.SetImage(self.idx_up if self.sort_asc else self.idx_down)
|
||||
else:
|
||||
info.SetImage(-1)
|
||||
self.list_ctrl.SetColumn(col, info)
|
||||
|
||||
def _populate_list_ctrl(self, items_data, parent_data):
|
||||
if not self: return
|
||||
try:
|
||||
self.list_ctrl.DeleteAllItems()
|
||||
self.current_items = []
|
||||
for i, item in enumerate(items_data):
|
||||
img_idx = self.idx_file
|
||||
if item['type'] == "FOLDER": img_idx = self.idx_folder
|
||||
elif item['type'] == "DRIVE": img_idx = self.idx_drive
|
||||
elif item['type'] == "SITE": img_idx = self.idx_site
|
||||
|
||||
self.list_ctrl.InsertItem(i, item['name'], img_idx)
|
||||
type_str = self.get_txt("type_folder") if item['type'] == "FOLDER" else self.get_txt("type_file") if item['type'] == "FILE" else self.get_txt("type_drive")
|
||||
self.list_ctrl.SetItem(i, 1, type_str)
|
||||
size_str = format_size(item['size']) if item['size'] is not None else ""
|
||||
self.list_ctrl.SetItem(i, 2, size_str)
|
||||
self.list_ctrl.SetItem(i, 3, item['modified'])
|
||||
self.current_items.append(item)
|
||||
|
||||
self.current_items = items_data
|
||||
|
||||
# Anvend sortering før visning
|
||||
self.apply_sorting()
|
||||
|
||||
self.set_status(self.get_txt("status_ready"))
|
||||
|
||||
if parent_data['type'] == "SITE":
|
||||
|
||||
Reference in New Issue
Block a user