fix: improve sort algo

This commit is contained in:
aclist 2026-02-16 01:57:51 +09:00
parent 45700e7a4a
commit c479051c2f
9 changed files with 36 additions and 174 deletions

View File

@ -3,14 +3,13 @@ import logging
import shutil import shutil
import threading import threading
import traceback import traceback
from typing import Optional
from warnings import deprecated
from concurrent.futures import wait, as_completed from concurrent.futures import wait, as_completed
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from functools import wraps from functools import wraps
from pathlib import Path from pathlib import Path
from typing import Any, Callable, TYPE_CHECKING from typing import Any, Callable, Optional, TYPE_CHECKING
from warnings import deprecated
import dzgui.api.pefile as PeFile import dzgui.api.pefile as PeFile
import dzgui.api.servers as Servers import dzgui.api.servers as Servers
@ -46,14 +45,14 @@ from dzgui.config.userprefs import UserPrefs
from dzgui.controllers.emitter import Emitter from dzgui.controllers.emitter import Emitter
from dzgui.model.misc_model import ModelManager from dzgui.model.misc_model import ModelManager
from dzgui.util import strings from dzgui.util import strings
from dzgui.util.diag import write_diagnostic
from dzgui.util._json import read_json, write_json from dzgui.util._json import read_json, write_json
from dzgui.util.diag import write_diagnostic
from dzgui.util.format import format_mods, format_player_count
from dzgui.util.localize import number from dzgui.util.localize import number
from dzgui.util.open_links import open_workshop_page, open_user_workshop from dzgui.util.open_links import open_workshop_page, open_user_workshop
from dzgui.util.format import format_mods, format_player_count
from dzgui.util.redact import redact_log from dzgui.util.redact import redact_log
from dzgui.views.dialogs.generic import ExceptionDialog, WaitDialog
from dzgui.views.dialogs.filepicker import FilePicker from dzgui.views.dialogs.filepicker import FilePicker
from dzgui.views.dialogs.generic import ExceptionDialog, WaitDialog
import gi import gi
@ -63,8 +62,8 @@ from gi.repository import Gtk, Gdk, GLib, GObject # noqa E402
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.model.map_model import MapManager
from dzgui.const.enum import ServerTab from dzgui.const.enum import ServerTab
from dzgui.model.map_model import MapManager
from dzgui.util.dist import Haversine from dzgui.util.dist import Haversine
from dzgui.views.base import Notebook, Grid, OuterWindow from dzgui.views.base import Notebook, Grid, OuterWindow
from dzgui.views.components.buttonbox import ContextualButton from dzgui.views.components.buttonbox import ContextualButton
@ -511,7 +510,7 @@ class Controller(GObject.GObject):
def get_mod_store(self) -> Gtk.ListStore: def get_mod_store(self) -> Gtk.ListStore:
return self.mediator.modtreeview.get_model() return self.mediator.modtreeview.get_model()
def format_mod_statusbar(self) -> None: def format_mod_statusbar(self) -> str:
total_mods, total_size = self.calc_mod_size() total_mods, total_size = self.calc_mod_size()
msg = format_mods(total_size, total_mods) msg = format_mods(total_size, total_mods)
return msg return msg
@ -534,7 +533,8 @@ class Controller(GObject.GObject):
try: try:
self.update_config(Preferences.FAV_LBL, name) self.update_config(Preferences.FAV_LBL, name)
self.update_config(Preferences.FAV_SRV, record) self.update_config(Preferences.FAV_SRV, record)
except Exception: except Exception as e:
logger.critical(e)
# TODO: add a failure dialog here # TODO: add a failure dialog here
return return
@ -642,9 +642,6 @@ class Controller(GObject.GObject):
self.mediator.modtreeview.set_cursor(0) self.mediator.modtreeview.set_cursor(0)
def dump_test_2(self) -> None: def dump_test_2(self) -> None:
import time
time.sleep(1)
data = ( data = (
[ [
"BAR", "BAR",
@ -660,146 +657,6 @@ class Controller(GObject.GObject):
"a", "a",
False, False,
], ],
[
"BAR",
"chernarusplus",
"a",
"a",
1,
1,
1,
"172.111.51.156:2302",
1,
1,
"a",
False,
],
[
"BAR",
"chernarusplus",
"a",
"a",
1,
1,
1,
"185.207.214.16:2302",
1,
1,
"a",
False,
],
[
"BAR",
"chernarusplus",
"a",
"a",
1,
1,
1,
"185.207.214.16:2302",
1,
1,
"a",
False,
],
[
"BAR",
"chernarusplus",
"a",
"a",
1,
1,
1,
"185.207.214.16:2302",
0,
0,
"a",
False,
],
[
"BAR",
"chernarusplus",
"a",
"a",
1,
1,
1,
"185.207.214.16:2302",
0,
0,
"a",
False,
],
[
"BAR",
"chernarusplus",
"a",
"a",
1,
1,
1,
"185.207.214.16:2302",
0,
0,
"a",
False,
],
[
"BAR",
"chernarusplus",
"a",
"a",
1,
1,
1,
"185.207.214.16:2302",
0,
0,
"a",
False,
],
[
"BAR",
"chernarusplus",
"a",
"a",
1,
1,
1,
"185.207.214.16:2302",
0,
0,
"a",
False,
],
[
"BAR",
"chernarusplus",
"a",
"a",
1,
1,
1,
"185.207.214.16:2302",
0,
0,
"a",
False,
],
[
"BAR",
"chernarusplus",
"a",
"a",
1,
1,
1,
"185.207.214.16:2302",
0,
0,
"a",
False,
],
) )
self.push_data_success(data, FilterMode.INITIAL) self.push_data_success(data, FilterMode.INITIAL)
@ -812,6 +669,11 @@ class Controller(GObject.GObject):
treeview.set_loaded(True) treeview.set_loaded(True)
treeview.set_model(self.to_insert) treeview.set_model(self.to_insert)
# TODO: this will allow history and saved tab to emit signals to statusbar
# CHORE: test if treeview's sort method inserts row at the correct index
# inserting a row serializes file on disk, updates control model for that tab, and
# reapplies filters to ephemeral model; since filters are applied, in-situ insertion might not be necessary
self.to_insert.connect("row-inserted", lambda: print("row inserted into model"))
map_man = treeview.get_map_man() map_man = treeview.get_map_man()
# TODO: signals or other approach to deferring map # TODO: signals or other approach to deferring map
@ -862,8 +724,6 @@ class Controller(GObject.GObject):
treeview = self.get_active_treeview() treeview = self.get_active_treeview()
manager = treeview.get_filter_man() manager = treeview.get_filter_man()
self.to_insert = None
if data is None: if data is None:
self.to_insert = None self.to_insert = None
else: else:
@ -991,7 +851,7 @@ class Controller(GObject.GObject):
# TODO: call filter_man methods directly # TODO: call filter_man methods directly
def refilter_model(self, mode: FilterMode, label: Optional[str] = None) -> None: def refilter_model(self, mode: FilterMode, label: Optional[str] = None) -> None:
tv = self.get_active_treeview() tv = self.get_active_treeview()
#tv.freeze_child_notify() # tv.freeze_child_notify()
filter_man = tv.get_filter_man() filter_man = tv.get_filter_man()
if filter_man.get_control() is None: if filter_man.get_control() is None:
return return
@ -1013,7 +873,7 @@ class Controller(GObject.GObject):
# TODO: clear ephemeral model if necessary # TODO: clear ephemeral model if necessary
# manager = treeview.get_filter_man() # manager = treeview.get_filter_man()
# manager.clear_model() # manager.clear_model()
#treeview.fancy_col.set_cell_data_func(treeview.fancy_rend, None) # treeview.fancy_col.set_cell_data_func(treeview.fancy_rend, None)
self.first_iteration = True self.first_iteration = True
self.pending_jobs = jobs self.pending_jobs = jobs

View File

@ -1,5 +1,6 @@
import datetime import datetime
import re import re
from dataclasses import dataclass from dataclasses import dataclass
from typing import Optional, TYPE_CHECKING from typing import Optional, TYPE_CHECKING
from warnings import deprecated from warnings import deprecated
@ -115,6 +116,7 @@ class FilteredModelManager:
case FilterMode.TOGGLE_ON: case FilterMode.TOGGLE_ON:
rows = self.filter_toggle_on(filters, *args) rows = self.filter_toggle_on(filters, *args)
# TODO: unimplemented
# if mode is not FilterMode.INITIAL: # if mode is not FilterMode.INITIAL:
# for row in rows: # for row in rows:
# if row[7] in self.ping_cache: # if row[7] in self.ping_cache:
@ -127,10 +129,6 @@ class FilteredModelManager:
for row in rows: for row in rows:
clone.append(row) clone.append(row)
# else:
# print("nothing to filter, sending none")
# clone = None
self.set_cache(filters, clone, rows) self.set_cache(filters, clone, rows)
self.set_model(clone) self.set_model(clone)
return clone return clone
@ -206,13 +204,12 @@ class FilteredModelManager:
case strings.filter_full: case strings.filter_full:
rows = [row for row in rows if row[4] != row[5]] rows = [row for row in rows if row[4] != row[5]]
case strings.filter_duplicate: case strings.filter_duplicate:
seen = [] seen = set()
final = [] final = []
for row in rows: for row in rows:
if row[0] in seen: if row[0] not in seen:
continue seen.add(row[0])
seen.append(row[0]) final.append(row)
final.append(row)
rows = final rows = final
case strings.filter_day: case strings.filter_day:
reg = r"([0][0-9]|[1][0-6])" reg = r"([0][0-9]|[1][0-6])"

View File

@ -16,7 +16,7 @@ class MapManager:
self.prior_map: str self.prior_map: str
self.selected_map = all_maps self.selected_map = all_maps
# TODO: namespace # TODO: namespace under strings.filters
self.default_filters = { self.default_filters = {
strings.filter_1pp: True, strings.filter_1pp: True,
strings.filter_day: True, strings.filter_day: True,

View File

@ -48,7 +48,7 @@ class ModelManager:
self.map_store = ListStore(str) self.map_store = ListStore(str)
self.help_store = self.new_model_from_class(MenuCols) self.help_store = self.new_model_from_class(MenuCols)
self.log_store = self.new_model_from_class(LogCols) self.log_store = self.new_model_from_class(LogCols)
# FIXME: needs to be generated on demand # FIXME: needs to be generated on demand for servers
self.modlist_store = self.new_model_from_class(ServerModCols) self.modlist_store = self.new_model_from_class(ServerModCols)
for row in HELP_MENU_ROWS: for row in HELP_MENU_ROWS:

View File

@ -274,6 +274,7 @@ class Notebook(ScrollableMixin, Gtk.Notebook): # type: ignore
if widget is None: if widget is None:
return return
# FIXME: deprecated
widget.grab_content_area() widget.grab_content_area()
def get_page(self) -> Gtk.Widget | None: def get_page(self) -> Gtk.Widget | None:

View File

@ -3,11 +3,15 @@ from typing import Literal
from dzgui.const.enum import NotebookPage from dzgui.const.enum import NotebookPage
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk # noqa from gi.repository import Gtk, Gdk # noqa
class HelpMenuMixin: class HelpMenuMixin:
def _on_esc_keypress(self, widget: Gtk.Widget, event: Gdk.EventKey) -> Literal[True]: def _on_esc_keypress(
self, widget: Gtk.Widget, event: Gdk.EventKey
) -> Literal[True]:
if event.keyval == Gdk.KEY_Escape: if event.keyval == Gdk.KEY_Escape:
self.controller.open_page(NotebookPage.HELP) self.controller.open_page(NotebookPage.HELP) # type: ignore
return True return True

View File

@ -13,7 +13,7 @@ if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
class Log(CursorMixin, HelpMenuMixin, Gtk.ScrolledWindow): class Log(CursorMixin, HelpMenuMixin, Gtk.ScrolledWindow): # type: ignore
def __init__(self, controller: "Controller") -> None: def __init__(self, controller: "Controller") -> None:
super().__init__() super().__init__()
self.treeview = LogTreeView(controller) self.treeview = LogTreeView(controller)
@ -26,6 +26,6 @@ class Log(CursorMixin, HelpMenuMixin, Gtk.ScrolledWindow):
def get_treeview(self) -> LogTreeView: def get_treeview(self) -> LogTreeView:
return self.treeview return self.treeview
def grab_content_area(self) -> None: def grab_content_area(self) -> None:
self.treeview.grab_focus() self.treeview.grab_focus()

View File

@ -60,8 +60,8 @@ class Options(Gtk.Box):
css.add_class(label, "page-heading") css.add_class(label, "page-heading")
self.add(label) self.add(label)
self.steam_entry = None self.steam_entry: Gtk.Entry = None
self.bm_entry = None self.bm_entry: Gtk.Entry = None
self.steam = WebButton(label=strings.options.steam_web) self.steam = WebButton(label=strings.options.steam_web)
self.steam.connect("clicked", self._on_link_button_clicked, STEAM_API_SETUP) self.steam.connect("clicked", self._on_link_button_clicked, STEAM_API_SETUP)

View File

@ -84,7 +84,7 @@ class ServerNotebook(Gtk.ScrolledWindow):
def grab_content_area(self) -> None: def grab_content_area(self) -> None:
self.get_active_treeview().grab_focus() self.get_active_treeview().grab_focus()
def get_current_tab_text(self) -> None: def get_current_tab_text(self) -> str:
ind = self.notebook.get_current_page() ind = self.notebook.get_current_page()
child = self.notebook.get_nth_page(ind) child = self.notebook.get_nth_page(ind)
return self.notebook.get_tab_label_text(child) return self.notebook.get_tab_label_text(child)