Skip to content

Commit

Permalink
Implement HypHoverPageOpener
Browse files Browse the repository at this point in the history
  • Loading branch information
kra-mo committed Jan 14, 2024
1 parent 4ce53b9 commit fd20f32
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 34 deletions.
5 changes: 4 additions & 1 deletion hyperplane/editable_row.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@
from gi.repository import GLib, GObject, Gtk, Pango

from hyperplane import shared
from hyperplane.hover_page_opener import HypHoverPageOpener


class HypEditableRow(Gtk.ListBoxRow):
class HypEditableRow(Gtk.ListBoxRow, HypHoverPageOpener):
"""A row in the sidebar representing a tag."""

__gtype_name__ = "HypEditableRow"
Expand All @@ -41,6 +42,8 @@ class HypEditableRow(Gtk.ListBoxRow):

def __init__(self, identifier: Optional[str] = None, **kwargs) -> None:
super().__init__(**kwargs)
HypHoverPageOpener.__init__(self)

self.image = Gtk.Image.new()
self.label = Gtk.Label(ellipsize=Pango.EllipsizeMode.END)

Expand Down
62 changes: 62 additions & 0 deletions hyperplane/hover_page_opener.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# hover_page_opener.py
#
# Copyright 2024 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 <http://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-or-later

"""
`GtkWidget`s inheriting from this class will become targets for
opening a page representing their items while a DnD operation is ongoing.
"""
from typing import Any, Iterable, Optional

from gi.repository import Gio, GLib, Gtk


class HypHoverPageOpener:
"""
`GtkWidget`s inheriting from this class will become targets for
opening a page representing their items while a DnD operation is ongoing.
They must have either a `gfile`, `tag` or `tags` attribute.
The class should only be used by widgets inside a `HypWindow`.
"""

gfile: Optional[Gio.File]
tag: Optional[str]
tags: Optional[Iterable[str]]

def __init__(self) -> None:
self.can_open_page = True

self.drop_controller_motion = Gtk.DropControllerMotion.new()
self.drop_controller_motion.connect("enter", self.__dnd_motion_enter)
Gtk.Widget.add_controller(self, self.drop_controller_motion)

def __hover_open(self, *_args: Any) -> None:
win = Gtk.Widget.get_root(self)

if self.drop_controller_motion.contains_pointer():
win.new_page(
getattr(self, "gfile", None),
getattr(self, "tag", None),
getattr(self, "tags", None),
)

def __dnd_motion_enter(self, *_args: Any) -> None:
if self.can_open_page:
GLib.timeout_add(500, self.__hover_open)
19 changes: 4 additions & 15 deletions hyperplane/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@

from hyperplane import shared
from hyperplane.file_properties import DOT_IS_NOT_EXTENSION
from hyperplane.hover_page_opener import HypHoverPageOpener
from hyperplane.utils.files import rm
from hyperplane.utils.symbolics import get_color_for_symbolic, get_symbolic
from hyperplane.utils.thumbnail import generate_thumbnail


@Gtk.Template(resource_path=shared.PREFIX + "/gtk/item.ui")
class HypItem(Adw.Bin):
class HypItem(Adw.Bin, HypHoverPageOpener):
"""An item representing a file to be set up through a `GtkSignalListItemFactory`."""

__gtype_name__ = "HypItem"
Expand Down Expand Up @@ -81,6 +82,8 @@ class HypItem(Adw.Bin):

def __init__(self, item, page, **kwargs) -> None:
super().__init__(**kwargs)
HypHoverPageOpener.__init__(self)

self.full_name = None
self.stem = None
self._thumbnail_paintable = None
Expand Down Expand Up @@ -132,10 +135,6 @@ def set_rubberband(*_args: Any) -> None:
drag_source.connect("drag-cancel", self.__drag_cancel)
self.add_controller(drag_source)

self.motion = Gtk.DropControllerMotion.new()
self.motion.connect("enter", self.__motion_enter)
self.add_controller(self.motion)

# Save initial style classes
self.thumb_init_classes = self.thumbnail_overlay.get_css_classes()
self.icon_init_classes = self.icon.get_css_classes()
Expand Down Expand Up @@ -360,16 +359,6 @@ def __drag_cancel(
) -> None:
self.page.view.set_enable_rubberband(True)

def __open_folder(self, *_args: Any) -> None:
win = self.get_root()

if self.motion.contains_pointer() and win.drop_target.get_current_drop():
win.new_page(self.gfile)

def __motion_enter(self, *_args: Any) -> None:
if self.is_dir and self.get_root().drop_target.get_current_drop():
GLib.timeout_add(500, self.__open_folder)

def __dir_children_cb(self, gfile: Gio.File, result: Gio.AsyncResult) -> None:
try:
files = gfile.enumerate_children_finish(result)
Expand Down
1 change: 1 addition & 0 deletions hyperplane/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ hyperplane_sources = [
'file_manager_dbus.py',
'file_properties.py',
'guide.py',
'hover_page_opener.py',
'item_filter.py',
'item_sorter.py',
'item.py',
Expand Down
17 changes: 2 additions & 15 deletions hyperplane/tag_row.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later

"""A row in the sidebar representing a tag."""
from typing import Any, Self
from typing import Self

from gi.repository import Gdk, GLib, Gtk
from gi.repository import Gdk, Gtk

from hyperplane import shared
from hyperplane.editable_row import HypEditableRow
Expand Down Expand Up @@ -51,10 +51,6 @@ def __init__(self, tag: str, icon_name: str, **kwargs) -> None:
self.add_controller(middle_click)

# Drag and drop
self.motion = Gtk.DropControllerMotion.new()
self.motion.connect("enter", self.__motion_enter)
self.add_controller(self.motion)

drag_source = Gtk.DragSource.new()
drag_source.connect("prepare", self.__drag_prepare)
drag_source.connect("drag-begin", self.__drag_begin)
Expand All @@ -67,15 +63,6 @@ def __init__(self, tag: str, icon_name: str, **kwargs) -> None:
drop_target.connect("drop", self.__drop)
self.add_controller(drop_target)

def __motion_open_tag(self, *_args: Any) -> None:
win = self.get_root()

if self.motion.contains_pointer():
win.new_page(tag=self.tag)

def __motion_enter(self, *_args: Any) -> None:
GLib.timeout_add(500, self.__motion_open_tag)

def __drag_prepare(self, _src: Gtk.DragSource, _x: float, _y: float) -> None:
return Gdk.ContentProvider.new_for_value(self)

Expand Down
1 change: 1 addition & 0 deletions hyperplane/volumes_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from hyperplane.navigation_bin import HypNavigationBin


# TODO: Subclass HypHoverPageOpener
@Gtk.Template(resource_path=shared.PREFIX + "/gtk/volumes-box.ui")
class HypVolumesBox(Adw.Bin):
"""
Expand Down
8 changes: 5 additions & 3 deletions hyperplane/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,9 @@ def __init__(
self.trash_row: Gio.File.new_for_uri("trash://"),
}

for widget, gfile in self.sidebar_rows.items():
for row, gfile in self.sidebar_rows.items():
row.gfile = gfile

(right_click := Gtk.GestureClick(button=Gdk.BUTTON_SECONDARY)).connect(
"pressed", self.__sidebar_right_click, gfile
)
Expand All @@ -268,8 +270,8 @@ def __init__(
"pressed", self.__sidebar_middle_click, gfile
)

widget.add_controller(right_click)
widget.add_controller(middle_click)
row.add_controller(right_click)
row.add_controller(middle_click)

# Drag and drop
self.drop_target = Gtk.DropTarget.new(
Expand Down

0 comments on commit fd20f32

Please sign in to comment.