diff --git a/hyperplane/editable_row.py b/hyperplane/editable_row.py index bc499f9..7640e6b 100644 --- a/hyperplane/editable_row.py +++ b/hyperplane/editable_row.py @@ -74,7 +74,7 @@ def start_edit(self) -> None: self.check_revealer.set_reveal_child(True) def end_edit(self) -> None: - """Saves the edits and updates self accordingly.""" + """Saves the edits and updates the row accordingly.""" self.check_revealer.set_reveal_child(False) GLib.timeout_add( self.check_revealer.get_transition_duration(), @@ -136,7 +136,7 @@ def set_active(self) -> None: @GObject.Property(type=str) def identifier(self) -> str: - """The identifier for self used in dconf.""" + """The identifier for the row used in dconf.""" return self._identifier @identifier.setter diff --git a/hyperplane/gtk/path-entry.blp b/hyperplane/gtk/path-entry.blp new file mode 100644 index 0000000..230fef2 --- /dev/null +++ b/hyperplane/gtk/path-entry.blp @@ -0,0 +1,12 @@ +using Gtk 4.0; + +template $HypPathEntry : Entry { + hexpand: true; + + ShortcutController { + Shortcut { + trigger: "Escape"; + action: "action(win.hide-path-entry)"; + } + } +} \ No newline at end of file diff --git a/hyperplane/gtk/style.css b/hyperplane/gtk/style.css index e8d7d89..4c8b738 100644 --- a/hyperplane/gtk/style.css +++ b/hyperplane/gtk/style.css @@ -66,6 +66,10 @@ and that looks ugly. filter: contrast(50%) brightness(130%); } +.sidebar-drop-target { + border-bottom: @accent_bg_color 3px solid; +} + .sidebar-check-button > check { color: @sidebar_fg_color; background-color: @sidebar_shade_color; diff --git a/hyperplane/gtk/window.blp b/hyperplane/gtk/window.blp index 20609a3..fbe7fd8 100644 --- a/hyperplane/gtk/window.blp +++ b/hyperplane/gtk/window.blp @@ -226,16 +226,7 @@ template $HypWindow : Adw.ApplicationWindow { } Adw.Clamp path_entry_clamp { - Entry path_entry { - hexpand: true; - - ShortcutController { - Shortcut { - trigger: "Escape"; - action: "action(win.hide-path-entry)"; - } - } - } + $HypPathEntry path_entry {} } Adw.Clamp search_entry_clamp { diff --git a/hyperplane/hyperplane.gresource.xml.in b/hyperplane/hyperplane.gresource.xml.in index c556ce5..ba19750 100644 --- a/hyperplane/hyperplane.gresource.xml.in +++ b/hyperplane/hyperplane.gresource.xml.in @@ -5,6 +5,7 @@ gtk/item.ui gtk/items-page.ui gtk/path-bar.ui + gtk/path-entry.ui gtk/path-segment.ui gtk/preferences.ui gtk/volumes-box.ui diff --git a/hyperplane/item_sorter.py b/hyperplane/item_sorter.py index 9af6da4..e9a931c 100644 --- a/hyperplane/item_sorter.py +++ b/hyperplane/item_sorter.py @@ -99,9 +99,5 @@ def do_compare( def __ordering_from_cmpfunc(self, cmpfunc_result: int) -> Gtk.Ordering: """Converts the result of a `GCompareFunc` like `strcmp()` to a `GtkOrdering` value.""" - # HACK: https://gitlab.gnome.org/GNOME/gtk/-/issues/6298 - if cmpfunc_result > 0: - return Gtk.Ordering.LARGER - if cmpfunc_result < 0: - return Gtk.Ordering.SMALLER - return Gtk.Ordering.EQUAL + # https://gitlab.gnome.org/GNOME/gtk/-/issues/6298 + return Gtk.Ordering((cmpfunc_result > 0) - (cmpfunc_result < 0)) diff --git a/hyperplane/items_page.py b/hyperplane/items_page.py index 8564e48..f3e8ce9 100644 --- a/hyperplane/items_page.py +++ b/hyperplane/items_page.py @@ -446,7 +446,7 @@ def __right_click(self, _gesture, _n, x, y) -> None: GLib.timeout_add(10, self.__popup_menu) def __drop_file( - self, _drop_target: Gtk.DropTarget, file_list: GObject.Value, _x, _y + self, _drop_target: Gtk.DropTarget, file_list: Gdk.FileList, _x, _y ) -> None: # TODO: This is copy-paste from __paste() for src in file_list: @@ -516,7 +516,7 @@ def __drop_texture( output.write_bytes(texture_bytes) def __drop_text( - self, _drop_target: Gtk.DropTarget, text: GObject.Value, _x, _y + self, _drop_target: Gtk.DropTarget, text: str, _x, _y ) -> None: # TODO: Again again, copy-paste from __paste() if not text: # If text is an empty string @@ -895,7 +895,6 @@ def delete(): case 0: return case 1: - # TODO: Blocking I/O for this? Really? msg = _("Are you sure you want to permanently delete {}?").format( f'"{get_gfile_display_name(gfiles[0])}"' ) diff --git a/hyperplane/meson.build b/hyperplane/meson.build index 96fbc39..bdd8561 100644 --- a/hyperplane/meson.build +++ b/hyperplane/meson.build @@ -6,6 +6,7 @@ blueprints = custom_target('blueprints', 'gtk/item.blp', 'gtk/items-page.blp', 'gtk/path-bar.blp', + 'gtk/path-entry.blp', 'gtk/path-segment.blp', 'gtk/preferences.blp', 'gtk/volumes-box.blp', @@ -54,6 +55,7 @@ hyperplane_sources = [ 'main.py', 'navigation_bin.py', 'path_bar.py', + 'path_entry.py', 'path_segment.py', 'postmaster_general.py', 'preferences.py', diff --git a/hyperplane/path_bar.py b/hyperplane/path_bar.py index c210caf..bb6cc5b 100644 --- a/hyperplane/path_bar.py +++ b/hyperplane/path_bar.py @@ -18,9 +18,12 @@ # SPDX-License-Identifier: GPL-3.0-or-later """The path bar in a HypWindow.""" -from typing import Optional +from os import sep +from pathlib import Path +from typing import Iterable, Optional +from urllib.parse import unquote, urlparse -from gi.repository import GLib, Gtk +from gi.repository import Gio, GLib, Gtk from hyperplane import shared from hyperplane.path_segment import HypPathSegment @@ -57,15 +60,15 @@ def remove(self, n: int) -> None: child, ) - if not (sep := self.separators[child]): + if not (separator := self.separators[child]): return - sep.set_reveal_child(False) + separator.set_reveal_child(False) GLib.timeout_add( - sep.get_transition_duration(), + separator.get_transition_duration(), self.__remove_child, self.segments_box, - sep, + separator, ) self.separators.pop(child) @@ -97,13 +100,13 @@ def append( sep_label = Gtk.Label.new("+" if self.tags else "/") sep_label.add_css_class("heading" if self.tags else "dim-label") - sep = Gtk.Revealer( + separator = Gtk.Revealer( child=sep_label, transition_type=Gtk.RevealerTransitionType.SLIDE_RIGHT ) - self.segments_box.append(sep) - sep.set_reveal_child(True) + self.segments_box.append(separator) + separator.set_reveal_child(True) else: - sep = None + separator = None segment = HypPathSegment(label, icon_name, uri, tag) self.segments_box.append(segment) @@ -111,7 +114,7 @@ def append( segment.set_transition_type(Gtk.RevealerTransitionType.SLIDE_RIGHT) segment.set_reveal_child(True) - self.separators[segment] = sep + self.separators[segment] = separator self.segments.append(segment) last_segment = self.segments[-1] @@ -140,6 +143,109 @@ def purge(self) -> None: self.segments = [] self.separators = {} + def update(self, gfile: Optional[Gio.File], tags: Optional[Iterable[str]]) -> None: + """Updates the bar according to a new `gfile` or new `tags`.""" + if gfile: + if self.tags: + self.purge() + + self.tags = False + + uri = gfile.get_uri() + parse = urlparse(uri) + segments = [] + + # Do these automatically is shceme != "file" + if parse.scheme != "file": + scheme_uri = f"{parse.scheme}://" + try: + file_info = Gio.File.new_for_uri(scheme_uri).query_info( + ",".join( + ( + Gio.FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON, + Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, + ) + ), + Gio.FileQueryInfoFlags.NONE, + ) + except GLib.Error: + pass + else: + display_name = file_info.get_display_name() + symbolic = file_info.get_symbolic_icon() + + segments.insert( + 0, + ( + display_name, + symbolic.get_names()[0] if symbolic else None, + scheme_uri, + None, + ), + ) + + parts = unquote(parse.path).split(sep) + + for index, part in enumerate(parts): + if not part: + continue + + segments.append((part, "", f"file://{sep.join(parts[:index+1])}", None)) + + if (path := gfile.get_path()) and ( + (path := Path(path)) == shared.home_path + or path.is_relative_to(shared.home_path) + ): + segments = segments[len(shared.home_path.parts) - 1 :] + segments.insert( + 0, + (_("Home"), "user-home-symbolic", shared.home_path.as_uri(), None), + ) + elif parse.scheme == "file": + # Not relative to home, so add a root segment + segments.insert( + 0, + ( + "", + "drive-harddisk-symbolic", + # Fall back to sep if the GFile doesn't have a path + Path(path.anchor if path else sep).as_uri(), + None, + ), + ) + + elif tags: + if not self.tags: + self.purge() + + self.tags = True + + segments = tuple((tag, "", None, tag) for tag in tags) + + if (old_len := len(self.segments)) > (new_len := len(segments)): + self.remove(old_len - new_len) + + append = False + for index, new_segment in enumerate(segments): + try: + old_segment = self.segments[index] + except IndexError: + old_segment = None + + if ( + not append + and old_segment + and new_segment[2] == old_segment.uri + and new_segment[3] == old_segment.tag + ): + continue + + if not append: + self.remove(len(self.segments) - index) + append = True + + self.append(*new_segment) + def __remove_child(self, parent: Gtk.Box, child: Gtk.Widget) -> None: # This is so GTK doesn't freak out when the child isn't in the parent anymore if child.get_parent == parent: diff --git a/hyperplane/path_entry.py b/hyperplane/path_entry.py new file mode 100644 index 0000000..f31bba5 --- /dev/null +++ b/hyperplane/path_entry.py @@ -0,0 +1,78 @@ +# path_entry.py +# +# Copyright 2023 kramo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# SPDX-License-Identifier: GPL-3.0-or-later + +"""An entry for navigating to paths or tags.""" +from typing import Any + +from gi.repository import Gio, GObject, Gtk + +from hyperplane import shared + + +@Gtk.Template(resource_path=shared.PREFIX + "/gtk/path-entry.ui") +class HypPathEntry(Gtk.Entry): + """An entry for navigating to paths or tags.""" + + __gtype_name__ = "HypPathEntry" + + def __init__(self, **kwargs) -> None: + super().__init__(**kwargs) + self.connect("activate", self.__activate) + + def __activate(self, entry, *_args: Any) -> None: + text = entry.get_text().strip() + + if text.startswith("//"): + tags = list( + tag + for tag in shared.tags + if tag in text.lstrip("/").rstrip("/").split("//") + ) + + if not tags: + self.get_root().send_toast(_("No such tags")) + return + + self.emit("hide-entry") + self.get_root().new_page(tags=tags) + return + + if "://" in text: + gfile = Gio.File.new_for_uri(text) + else: + gfile = Gio.File.new_for_path(text) + + if ( + not gfile.query_file_type(Gio.FileQueryInfoFlags.NONE) + == Gio.FileType.DIRECTORY + ): + self.get_root().send_toast(_("Unable to find path")) + return + + self.emit("hide-entry") + + self.get_root().new_page(gfile) + + @GObject.Signal(name="hide-entry") + def hide(self) -> None: + """ + Emitted to indicate that the entry is done and should be hidden. + + Containers of this widget should connect to it and react accordingly. + """ diff --git a/hyperplane/postmaster_general.py b/hyperplane/postmaster_general.py index fd777ec..aac245b 100644 --- a/hyperplane/postmaster_general.py +++ b/hyperplane/postmaster_general.py @@ -46,7 +46,7 @@ def tags_changed(self, change: Gtk.FilterChange) -> None: All objects that keep an internal list of tags should connect to it and update their list accordingly. - `change` represents whether tags were added, removed or just reordered. + `change` indicates whether tags were added, removed or just reordered. This is only relevant for item filters. """ diff --git a/hyperplane/tag_row.py b/hyperplane/tag_row.py index b1cae31..9350f77 100644 --- a/hyperplane/tag_row.py +++ b/hyperplane/tag_row.py @@ -18,12 +18,11 @@ # SPDX-License-Identifier: GPL-3.0-or-later """A row in the sidebar representing a tag.""" -from typing import Any - from gi.repository import Gdk, Gtk from hyperplane import shared from hyperplane.editable_row import HypEditableRow +from hyperplane.utils.tags import update_tags class HypTagRow(HypEditableRow): @@ -49,6 +48,48 @@ def __init__(self, tag: str, icon_name: str, **kwargs) -> None: ) self.add_controller(middle_click) + # Drag and drop + drag_source = Gtk.DragSource.new() + drag_source.connect("prepare", self.__drag_prepare) + drag_source.connect("drag-begin", self.__drag_begin) + drag_source.set_actions(Gdk.DragAction.MOVE) + self.box.add_controller(drag_source) + + drop_target = Gtk.DropTarget.new(str, Gdk.DragAction.MOVE) + drop_target.connect("enter", self.__drop_enter) + drop_target.connect("leave", self.__drop_leave) + drop_target.connect("drop", self.__drop) + self.add_controller(drop_target) + + def __drag_prepare(self, _src: Gtk.DragSource, _x: float, _y: float) -> None: + return Gdk.ContentProvider.new_for_value(self.tag) + + def __drag_begin(self, src: Gtk.DragSource, _drag: Gdk.Drag) -> None: + src.set_icon(Gtk.WidgetPaintable.new(self), 0, 0) + + def __drop_enter(self, _target: Gtk.DropTarget, _x: float, _y: float) -> None: + self.add_css_class("sidebar-drop-target") + + return Gdk.DragAction.MOVE + + def __drop_leave(self, _target: Gtk.DropTarget) -> None: + self.remove_css_class("sidebar-drop-target") + + def __drop( + self, _target: Gtk.DropTarget, string: str, _x: float, _y: float + ) -> None: + if not string in shared.tags: + return + + self_index = shared.tags.index(self.tag) + str_index = shared.tags.index(string) + + shared.tags.insert( + self_index + int(self_index < str_index), shared.tags.pop(str_index) + ) + + update_tags() + def __right_click( self, _gesture: Gtk.GestureClick, _n: int, x: float, y: float ) -> None: diff --git a/hyperplane/utils/tags.py b/hyperplane/utils/tags.py index a66e6fa..5adef35 100644 --- a/hyperplane/utils/tags.py +++ b/hyperplane/utils/tags.py @@ -26,11 +26,19 @@ from hyperplane import shared -def __update_tags() -> None: +def update_tags(change: Gtk.FilterChange = Gtk.FilterChange.DIFFERENT) -> None: + """ + Writes the list of tags from `shared.tags` to disk and notifies widgets. + + `change` indicates whether tags were + added (more strict), removed (less strict) or just reordered (different). + """ (shared.home_path / ".hyperplane").write_text( "\n".join(shared.tags), encoding="utf-8" ) + shared.postmaster.emit("tags-changed", change) + def path_represents_tags(path: PathLike | str) -> bool: """Checks whether a given `path` represents tags or not.""" @@ -53,9 +61,7 @@ def add_tags(*tags: str) -> None: """ for tag in tags: shared.tags.append(tag) - __update_tags() - - shared.postmaster.emit("tags-changed", Gtk.FilterChange.MORE_STRICT) + update_tags(Gtk.FilterChange.MORE_STRICT) def remove_tags(*tags: str) -> None: @@ -63,9 +69,7 @@ def remove_tags(*tags: str) -> None: for tag in tags: if tag in shared.tags: shared.tags.remove(tag) - __update_tags() - - shared.postmaster.emit("tags-changed", Gtk.FilterChange.LESS_STRICT) + update_tags(Gtk.FilterChange.LESS_STRICT) def move_tag(tag: str, up: bool) -> None: @@ -83,9 +87,7 @@ def move_tag(tag: str, up: bool) -> None: shared.tags[index - 1], shared.tags[index], ) - __update_tags() - - shared.postmaster.emit("tags-changed", Gtk.FilterChange.DIFFERENT) + update_tags() return # Moving down @@ -100,6 +102,4 @@ def move_tag(tag: str, up: bool) -> None: shared.tags[index], ) - __update_tags() - - shared.postmaster.emit("tags-changed", Gtk.FilterChange.DIFFERENT) + update_tags() diff --git a/hyperplane/window.py b/hyperplane/window.py index 85cdc21..81d538a 100644 --- a/hyperplane/window.py +++ b/hyperplane/window.py @@ -20,10 +20,8 @@ """The main application window.""" from itertools import chain from os import sep -from pathlib import Path from time import time from typing import Any, Callable, Iterable, Optional, Self -from urllib.parse import unquote, urlparse from gi.repository import Adw, Gdk, Gio, GLib, Gtk @@ -32,6 +30,7 @@ from hyperplane.items_page import HypItemsPage from hyperplane.navigation_bin import HypNavigationBin from hyperplane.path_bar import HypPathBar +from hyperplane.path_entry import HypPathEntry from hyperplane.properties import HypPropertiesWindow from hyperplane.tag_row import HypTagRow from hyperplane.utils.create_message_dialog import create_message_dialog @@ -51,11 +50,14 @@ class HypWindow(Adw.ApplicationWindow): __gtype_name__ = "HypWindow" + # Main view tab_overview: Adw.TabOverview = Gtk.Template.Child() toast_overlay: Adw.ToastOverlay = Gtk.Template.Child() overlay_split_view: Adw.OverlaySplitView = Gtk.Template.Child() tab_view: Adw.TabView = Gtk.Template.Child() toolbar_view: Adw.ToolbarView = Gtk.Template.Child() + + # Sidebar sidebar: Gtk.ListBox = Gtk.Template.Child() sidebar_action_bar: Gtk.ActionBar = Gtk.Template.Child() home_row: Gtk.Box = Gtk.Template.Child() @@ -65,15 +67,17 @@ class HypWindow(Adw.ApplicationWindow): trash_row: HypEditableRow = Gtk.Template.Child() volumes_box: HypVolumesBox = Gtk.Template.Child() + # Header bar title_stack: Gtk.Stack = Gtk.Template.Child() path_bar_clamp: Adw.Clamp = Gtk.Template.Child() path_bar: HypPathBar = Gtk.Template.Child() path_entry_clamp: Adw.Clamp = Gtk.Template.Child() - path_entry: Gtk.Entry = Gtk.Template.Child() + path_entry: HypPathEntry = Gtk.Template.Child() search_entry_clamp: Adw.Clamp = Gtk.Template.Child() search_entry: Gtk.SearchEntry = Gtk.Template.Child() search_button: Gtk.ToggleButton = Gtk.Template.Child() + # Rename popover rename_popover: Gtk.Popover = Gtk.Template.Child() rename_label: Gtk.Label = Gtk.Template.Child() rename_entry: Adw.EntryRow = Gtk.Template.Child() @@ -81,11 +85,12 @@ class HypWindow(Adw.ApplicationWindow): rename_revealer_label: Gtk.Label = Gtk.Template.Child() rename_button: Gtk.Button = Gtk.Template.Child() + # Right-click menus right_click_menu: Gtk.PopoverMenu = Gtk.Template.Child() tag_right_click_menu: Gtk.PopoverMenu = Gtk.Template.Child() file_right_click_menu: Gtk.PopoverMenu = Gtk.Template.Child() - path_bar_connection: int + path_entry_connection: int sidebar_tag_rows: set right_clicked_tag: str @@ -122,10 +127,12 @@ def __init__(self, **kwargs) -> None: # Create actions navigation_view = HypNavigationBin(initial_gfile=shared.home) + self.tab_view.append(navigation_view).set_title( - title := self.get_visible_page().get_title() + title := (page := self.get_visible_page()).get_title() ) - self.__update_path_bar() + + self.path_bar.update(page.gfile, page.tags) self.set_title(title) self.create_action( @@ -196,13 +203,14 @@ def __init__(self, **kwargs) -> None: self.tab_view.connect("create-window", self.__create_window) self.tab_overview.connect("create-tab", self.__create_tab) - self.path_entry.connect("activate", self.__path_entry_activated) self.search_entry.connect("search-started", self.__show_search_entry) self.search_entry.connect("search-changed", self.__search_changed) self.search_entry.connect("stop-search", self.__hide_search_entry) self.search_entry.connect("activate", self.__search_activate) self.search_button.connect("clicked", self.__toggle_search_entry) + self.path_entry.connect("hide-entry", self.__hide_path_entry) + shared.postmaster.connect("tags-changed", self.__update_tags) shared.postmaster.connect("sidebar-edited", self.__sidebar_edited) shared.postmaster.connect( @@ -496,110 +504,6 @@ def __navigation_changed(self, view: Adw.NavigationView, *_args: Any) -> None: self.__nav_stack_changed() - def __update_path_bar(self) -> None: - page = self.get_visible_page() - - if page.gfile: - if self.path_bar.tags: - self.path_bar.purge() - - self.path_bar.tags = False - - uri = page.gfile.get_uri() - parse = urlparse(uri) - segments = [] - - # Do these automatically is shceme != "file" - if parse.scheme != "file": - scheme_uri = f"{parse.scheme}://" - try: - file_info = Gio.File.new_for_uri(scheme_uri).query_info( - ",".join( - ( - Gio.FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON, - Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, - ) - ), - Gio.FileQueryInfoFlags.NONE, - ) - except GLib.Error: - pass - else: - display_name = file_info.get_display_name() - symbolic = file_info.get_symbolic_icon() - - segments.insert( - 0, - ( - display_name, - symbolic.get_names()[0] if symbolic else None, - scheme_uri, - None, - ), - ) - - parts = unquote(parse.path).split(sep) - - for index, part in enumerate(parts): - if not part: - continue - - segments.append((part, "", f"file://{sep.join(parts[:index+1])}", None)) - - if (path := page.gfile.get_path()) and ( - (path := Path(path)) == shared.home_path - or path.is_relative_to(shared.home_path) - ): - segments = segments[len(shared.home_path.parts) - 1 :] - segments.insert( - 0, - (_("Home"), "user-home-symbolic", shared.home_path.as_uri(), None), - ) - elif parse.scheme == "file": - # Not relative to home, so add a root segment - segments.insert( - 0, - ( - "", - "drive-harddisk-symbolic", - # Fall back to sep if the GFile doesn't have a path - Path(path.anchor if path else sep).as_uri(), - None, - ), - ) - - elif page.tags: - if not self.path_bar.tags: - self.path_bar.purge() - - self.path_bar.tags = True - - segments = tuple((tag, "", None, tag) for tag in page.tags) - - if (old_len := len(self.path_bar.segments)) > (new_len := len(segments)): - self.path_bar.remove(old_len - new_len) - - append = False - for index, new_segment in enumerate(segments): - try: - old_segment = self.path_bar.segments[index] - except IndexError: - old_segment = None - - if ( - not append - and old_segment - and new_segment[2] == old_segment.uri - and new_segment[3] == old_segment.tag - ): - continue - - if not append: - self.path_bar.remove(len(self.path_bar.segments) - index) - append = True - - self.path_bar.append(*new_segment) - def __page_attached(self, _view: Adw.TabView, page: Adw.TabPage, _pos: int) -> None: page.get_child().view.connect("popped", self.__navigation_changed) page.get_child().view.connect("pushed", self.__navigation_changed) @@ -619,39 +523,6 @@ def __reopen_tab(self, *_args: Any) -> None: return self.tab_view.append(page).set_title(title) - def __path_entry_activated(self, entry, *_args: Any) -> None: - text = entry.get_text().strip() - - if text.startswith("//"): - self.__hide_path_entry() - tags = list( - tag - for tag in shared.tags - if tag in text.lstrip("/").rstrip("/").split("//") - ) - - if not tags: - self.send_toast(_("No such tags")) - - self.new_page(tags=tags) - return - - if "://" in text: - gfile = Gio.File.new_for_uri(text) - else: - gfile = Gio.File.new_for_path(text) - - if ( - not gfile.query_file_type(Gio.FileQueryInfoFlags.NONE) - == Gio.FileType.DIRECTORY - ): - self.send_toast(_("Unable to find path")) - return - - self.__hide_path_entry() - - self.new_page(gfile) - def __title_stack_set_child(self, new: Gtk.Widget) -> None: old = self.title_stack.get_visible_child() if old == new: @@ -666,9 +537,9 @@ def __title_stack_set_child(self, new: Gtk.Widget) -> None: shared.search = "" self.searched_page.item_filter.changed(Gtk.FilterChange.LESS_STRICT) case self.path_entry_clamp: - if self.path_bar_connection: - self.path_entry.disconnect(self.path_bar_connection) - self.path_bar_connection = None + if self.path_entry_connection: + self.path_entry.disconnect(self.path_entry_connection) + self.path_entry_connection = None match new: case self.search_entry_clamp: @@ -697,7 +568,7 @@ def __title_stack_set_child(self, new: Gtk.Widget) -> None: self.set_focus(self.path_entry) self.path_entry.select_region(-1, -1) - self.path_bar_connection = self.path_entry.connect( + self.path_entry_connection = self.path_entry.connect( "notify::has-focus", self.__path_entry_focus ) case self.path_bar_clamp: @@ -854,7 +725,9 @@ def __set_actions(self, *_args: Any) -> None: ) def __nav_stack_changed(self) -> None: - self.__update_path_bar() + page = self.get_visible_page() + + self.path_bar.update(page.gfile, page.tags) self.lookup_action("back").set_enabled( bool(