From: Christian Heller Date: Thu, 14 Nov 2024 14:28:37 +0000 (+0100) Subject: Browser: Split prompt into two ellipsized subprompts. X-Git-Url: https://plomlompom.com/repos/%7B%7B%20web_path%20%7D%7D/decks/index.html?a=commitdiff_plain;h=7ec4364e29de96d917f3d4f7825822b6959ff5e0;p=stable_plom Browser: Split prompt into two ellipsized subprompts. --- diff --git a/browser.py b/browser.py index 89eabad..f6ff73d 100755 --- a/browser.py +++ b/browser.py @@ -25,7 +25,6 @@ from stable.gen_params import (GenParams, GEN_PARAMS_FLOAT, # noqa: E402 GEN_PARAMS_INT, GEN_PARAMS_STR, # noqa: E402 GEN_PARAMS) # noqa: E402 -PromptsDiff = dict[str, str] BasicItemsAttrs = dict[str, set[str]] AttrVals: TypeAlias = list[str] AttrValsByVisibility: TypeAlias = dict[str, AttrVals] @@ -388,6 +387,8 @@ class ImgItem(GalleryItem): def __init__(self, path: str, name: str, cache: Cache) -> None: super().__init__(path, name) + self.subprompt1: str = '' + self.subprompt2: str = '' mtime = getmtime(self.full_path) dt = datetime.fromtimestamp(mtime, tz=timezone.utc) iso8601_str: str = dt.isoformat(timespec='microseconds') @@ -746,7 +747,6 @@ class Gallery: self.items_attrs: ItemsAttrs = {} self.selected_idx = 0 self.slots: list[GallerySlot] = [] - self._prompts_diff: PromptsDiff = {} self._grid = Gtk.Grid() self._force_width, self._force_height = 0, 0 @@ -814,63 +814,65 @@ class Gallery: else: self.request_update(build_grid=True) - def _prep_items_attrs(self, - entries: list[GalleryItem] - ) -> tuple[BasicItemsAttrs, PromptsDiff]: - - def diff_prompts(basic_items_attrs: BasicItemsAttrs) -> PromptsDiff: - if 'prompt' not in basic_items_attrs: - return {} - prompts_diff: PromptsDiff = {} - prompts = list(basic_items_attrs['prompt']) - - def find_longest_equal(prompts, j, matcher): - longest_total, temp_longest = '', '' - while j < len(prompts[0]): - if 'end' == matcher: - temp_longest = prompts[0][-j] + temp_longest - else: - temp_longest += prompts[0][j] - if len(temp_longest) > len(longest_total): - found_in_all = True - for prompt in prompts[1:]: - if ('start' == matcher - and not prompt.startswith(temp_longest)) or\ - ('end' == matcher - and not prompt.endswith(temp_longest)) or\ - ('in' == matcher - and temp_longest not in prompt): - found_in_all = False - break - if not found_in_all: - break - longest_total = temp_longest - j += 1 - return longest_total - - prefix = find_longest_equal(prompts, 0, 'start') - suffix = find_longest_equal(prompts, 1, matcher='end') - cores = [p[len(prefix):] for p in prompts] - if suffix: - for i, p in enumerate(cores): - cores[i] = p[:-len(suffix)] - longest_total = '' - for i in range(len(cores[0])): - temp_longest = find_longest_equal(cores, j=i, matcher='in') + @staticmethod + def _diff_prompts(prompts: list[str]) -> dict[str, tuple[str, str]]: + if not prompts: + return {} + + def find_longest_equal(prompts, j, matcher): + longest_total, temp_longest = '', '' + while j < len(prompts[0]): + if 'end' == matcher: + temp_longest = prompts[0][-j] + temp_longest + else: + temp_longest += prompts[0][j] if len(temp_longest) > len(longest_total): + found_in_all = True + for prompt in prompts[1:]: + if ('start' == matcher + and not prompt.startswith(temp_longest)) or\ + ('end' == matcher + and not prompt.endswith(temp_longest)) or\ + ('in' == matcher + and temp_longest not in prompt): + found_in_all = False + break + if not found_in_all: + break longest_total = temp_longest - middle = longest_total - for i, p in enumerate(prompts): - remains = p[len(prefix):] - idx_middle = remains.index(middle) - second = remains[:idx_middle] - remains = remains[idx_middle + len(middle):] - first = remains[:-len(suffix)] if suffix else remains - pre_ell = '…' if prefix else '' - post_ell = '…' if suffix else '' - prompts_diff[p] = f'{pre_ell}{first}…{second}{post_ell}' - return prompts_diff - + j += 1 + return longest_total + + prefix = find_longest_equal(prompts, 0, 'start') + suffix = find_longest_equal(prompts, 1, matcher='end') + cores = [p[len(prefix):] for p in prompts] + if suffix: + for i, p in enumerate(cores): + cores[i] = p[:-len(suffix)] + longest_total = '' + for i in range(len(cores[0])): + temp_longest = find_longest_equal(cores, j=i, matcher='in') + if len(temp_longest) > len(longest_total): + longest_total = temp_longest + middle = longest_total + prompts_diff = {} + for i, p in enumerate(prompts): + remains = p[len(prefix):] if prefix else p + idx_middle = remains.index(middle) + first = remains[:idx_middle] if idx_middle else '' + remains = remains[idx_middle + len(middle):] + second = remains[:-len(suffix)] if suffix else remains + if first: + first = f'…{first}' if prefix else first + first = f'{first}…' if suffix or middle else first + if second: + second = f'…{second}' if prefix or middle else second + second = f'{second}…' if suffix else second + prompts_diff[p] = (first if first else '…', + second if second else '…') + return prompts_diff + + def _prep_items_attrs(self, entries: list[GalleryItem]) -> BasicItemsAttrs: basic_items_attrs = {} for attr_name in (s.name for s in self._sort_order): vals: set[str] = set() @@ -880,8 +882,7 @@ class Gallery: if val is not None: vals.add(val) basic_items_attrs[attr_name] = vals - prompts_diff = diff_prompts(basic_items_attrs) - return basic_items_attrs, prompts_diff + return basic_items_attrs def _load_directory(self) -> None: """(Re-)build .dir_entries from ._img_dir_path, ._basic_items_attrs.""" @@ -928,8 +929,19 @@ class Gallery: read_directory(path) read_directory(self._img_dir_path, make_parent=True) - self._basic_items_attrs, self._prompts_diff = self._prep_items_attrs( - self.dir_entries) + prompts_set: set[str] = set() + for entry in [e for e in self.dir_entries + if isinstance(e, ImgItem) and hasattr(e, 'prompt')]: + prompts_set.add(entry.prompt) + prompts_diff = self._diff_prompts(list(prompts_set)) + for entry in [e for e in self.dir_entries if isinstance(e, ImgItem)]: + entry.subprompt1 = prompts_diff[entry.prompt][0] + entry.subprompt2 = prompts_diff[entry.prompt][1] + if self._sort_order.by_name('prompt'): + self._sort_order.remove('prompt') + self._sort_order._list.append(SorterAndFilterer('subprompt1')) + self._sort_order._list.append(SorterAndFilterer('subprompt2')) + self._basic_items_attrs = self._prep_items_attrs(self.dir_entries) ignorable_attrs = [] for attr_name, attr_vals in self._basic_items_attrs.items(): if len(attr_vals) < 2: @@ -989,7 +1001,7 @@ class Gallery: items_attrs_tmp_1 = separate_items_attrs(self._basic_items_attrs) filtered = filter_entries(items_attrs_tmp_1) - reduced_basic_items_attrs = self._prep_items_attrs(filtered)[0] + reduced_basic_items_attrs = self._prep_items_attrs(filtered) items_attrs_tmp_2 = separate_items_attrs(reduced_basic_items_attrs) for attr_name in (s.name for s in self._sort_order): final_values: AttrValsByVisibility = {'incl': [], 'semi': []} @@ -1040,11 +1052,7 @@ class Gallery: attr_name, attr_values = remaining[0] if 1 == len(remaining): for i, attr in enumerate(ancestors): - parent_attr_name, parent_attr_value = attr - if 'prompt' == parent_attr_name: - parent_attr_value = self\ - ._prompts_diff[parent_attr_value] - txt = f'{parent_attr_name}: {parent_attr_value}' + txt = f'{attr[0]}: {attr[1]}' vlabel = VerticalLabel(txt, self._slots_geometry) self._grid.attach(vlabel, i, i_row_ref[0], 1, 1) row: list[Optional[GalleryItem]] @@ -1088,8 +1096,6 @@ class Gallery: self._col_headers_grid.attach(Gtk.Box(), 0, 0, 1, 1) top_attr_name: str = sort_attrs[-1][0] for i, val in enumerate(sort_attrs[-1][1]): - if 'prompt' == top_attr_name: - val = self._prompts_diff[val] label = Gtk.Label(label=f'{top_attr_name}: {val}', xalign=0, ellipsize=Pango.EllipsizeMode.MIDDLE)