Use ListModel for faster directory traversal

This commit is contained in:
Jan Hamal Dvořák 2025-03-09 13:25:14 +01:00
parent c54f183b0a
commit 2fb5265463
2 changed files with 55 additions and 16 deletions

View file

@ -7,20 +7,20 @@ from typing import Any, cast
import gi
from .file_model import FileItem, FileType
from .file_model import FileItem, FileListModel, FileType
gi.require_version("Gdk", "4.0")
gi.require_version("Gtk", "4.0")
gi.require_version("Gst", "1.0")
gi.require_version("Pango", "1.0")
from gi.repository import Gdk, Gio, Gst, Gtk, Pango # NOQA: E402
from gi.repository import Gdk, Gst, Gtk, Pango # NOQA: E402
class MainWindow(Gtk.ApplicationWindow):
file_info_label: Gtk.Label
stack: Gtk.Stack
list_view: Gtk.ListView
list_store: Gio.ListStore
list_model: FileListModel
selection_model: Gtk.SingleSelection
video_widget: Gtk.Picture
pipeline: Gst.Pipeline
@ -137,10 +137,10 @@ class MainWindow(Gtk.ApplicationWindow):
main_box.append(grid)
# Create list store and view
self.list_store = Gio.ListStore(item_type=FileItem)
# Create list model and view
self.list_model = FileListModel()
self.list_view = Gtk.ListView()
self.selection_model = Gtk.SingleSelection.new(self.list_store)
self.selection_model = Gtk.SingleSelection.new(self.list_model)
self.selection_model.connect("selection-changed", self._on_selection_changed)
self.list_view.set_model(self.selection_model)
self.list_view.set_vexpand(True)
@ -285,8 +285,8 @@ class MainWindow(Gtk.ApplicationWindow):
self._populate_file_list()
# Find and select the directory we came from
for i in range(self.list_store.get_n_items()):
item = self.list_store.get_item(i)
for i in range(self.list_model.get_n_items()):
item = self.list_model.get_item(i)
if not item:
continue
@ -392,7 +392,7 @@ class MainWindow(Gtk.ApplicationWindow):
file_item.save_attribute("position", duration)
# Force the list to update the changed item
self.list_store.items_changed(self.selection_model.get_selected(), 1, 1)
self.list_model.items_changed(self.selection_model.get_selected(), 1, 1)
def _on_menu_key_pressed(
self,
@ -551,11 +551,7 @@ class MainWindow(Gtk.ApplicationWindow):
# Sort directories first, then files, both alphabetically
items.sort(key=lambda x: (x.file_type != FileType.DIRECTORY, x.name.lower()))
while self.list_store.get_n_items():
self.list_store.remove(0)
for item in items:
self.list_store.append(item)
self.list_model.set_items(items)
if items:
self.file_info_label.set_text(items[0].name)

View file

@ -3,12 +3,12 @@ from __future__ import annotations
import os
from enum import Enum, auto
from pathlib import Path
from typing import overload
from typing import Optional, overload
import gi
gi.require_version("GObject", "2.0")
from gi.repository import GObject # NOQA: E402
from gi.repository import Gio, GObject # NOQA: E402
class FileType(Enum):
@ -54,3 +54,46 @@ class FileItem(GObject.Object):
pass
self.notify("attrs-changed")
class FileListModel(GObject.Object, Gio.ListModel):
"""A ListModel implementation for FileItems"""
__gtype_name__ = "FileListModel"
items: list[FileItem]
def __init__(self):
super().__init__()
self.items = []
def do_get_item_type(self) -> GObject.GType:
return GObject.type_from_name("FileItem")
def do_get_n_items(self) -> int:
return len(self.items)
def do_get_item(self, position: int) -> Optional[FileItem]:
if 0 <= position < len(self.items):
return self.items[position]
return None
def remove_all(self) -> None:
removed = len(self.items)
self.items = []
self.items_changed(0, removed, 0)
def set_items(self, items: list[FileItem]):
removed = len(self.items)
self.items = list(items)
self.items_changed(0, removed, len(self.items))
def append(self, item: FileItem) -> None:
pos = len(self.items)
self.items.append(item)
self.items_changed(pos, 0, 1)
def remove(self, position: int) -> None:
if 0 <= position < len(self.items):
self.items.pop(position)
self.items_changed(position, 1, 0)