header: Convert the Open button to an Adw.ActionRow
And put it in the new Menu button popover list. I don't expect this to be a common action, so the extra button press is acceptable. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
c5867badae
commit
a944af7f3e
|
@ -49,10 +49,11 @@ class Header(Gtk.HeaderBar):
|
||||||
|
|
||||||
icon = "sidebar-show-symbolic"
|
icon = "sidebar-show-symbolic"
|
||||||
self._show_sidebar = Gtk.ToggleButton(icon_name=icon, has_frame=False)
|
self._show_sidebar = Gtk.ToggleButton(icon_name=icon, has_frame=False)
|
||||||
self._open = open.Button()
|
self._open = open.OpenRow()
|
||||||
|
|
||||||
self._menu_box = Gtk.ListBox(selection_mode=Gtk.SelectionMode.NONE)
|
self._menu_box = Gtk.ListBox(selection_mode=Gtk.SelectionMode.NONE)
|
||||||
self._menu_box.add_css_class("boxed-list")
|
self._menu_box.add_css_class("boxed-list")
|
||||||
|
self._menu_box.append(self._open)
|
||||||
|
|
||||||
icon = "open-menu-symbolic"
|
icon = "open-menu-symbolic"
|
||||||
self._menu_button = buttons.PopoverButton(popover_child=self._menu_box,
|
self._menu_button = buttons.PopoverButton(popover_child=self._menu_box,
|
||||||
|
@ -94,7 +95,6 @@ class Header(Gtk.HeaderBar):
|
||||||
GObject.BindingFlags.BIDIRECTIONAL)
|
GObject.BindingFlags.BIDIRECTIONAL)
|
||||||
|
|
||||||
self.pack_start(self._show_sidebar)
|
self.pack_start(self._show_sidebar)
|
||||||
self.pack_start(self._open)
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
self._window = settings.Window(sql)
|
self._window = settings.Window(sql)
|
||||||
self._settings = Gtk.Button(icon_name="settings-symbolic",
|
self._settings = Gtk.Button(icon_name="settings-symbolic",
|
||||||
|
@ -131,7 +131,7 @@ class Header(Gtk.HeaderBar):
|
||||||
f"normalizing: {rg_status}")
|
f"normalizing: {rg_status}")
|
||||||
self._vol_button.set_tooltip_text(status)
|
self._vol_button.set_tooltip_text(status)
|
||||||
|
|
||||||
def __track_requested(self, button: open.Button,
|
def __track_requested(self, button: open.OpenRow,
|
||||||
path: pathlib.Path) -> None:
|
path: pathlib.Path) -> None:
|
||||||
self.emit("track-requested", path)
|
self.emit("track-requested", path)
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
# Copyright 2023 (c) Anna Schumaker.
|
# Copyright 2023 (c) Anna Schumaker.
|
||||||
"""A custom Button that opens a FileDialog to select a file for playback."""
|
"""A custom Adw.ActionRow to select a file for playback."""
|
||||||
import pathlib
|
import pathlib
|
||||||
from gi.repository import GObject
|
from gi.repository import GObject
|
||||||
from gi.repository import GLib
|
from gi.repository import GLib
|
||||||
from gi.repository import Gio
|
from gi.repository import Gio
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import Adw
|
||||||
|
|
||||||
|
|
||||||
class Button(Gtk.Button):
|
class OpenRow(Adw.ActionRow):
|
||||||
"""Our pre-configured open button."""
|
"""Our pre-configured open Adw.ActionRow."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Initialize our open button."""
|
"""Initialize our open ActionRow."""
|
||||||
super().__init__(icon_name="document-open-symbolic",
|
super().__init__(activatable=True, title="Open File",
|
||||||
tooltip_text="open a file for playback")
|
subtitle="Select a file for playback")
|
||||||
|
self._prefix = Gtk.Image(icon_name="document-open-symbolic")
|
||||||
self._filters = Gio.ListStore()
|
self._filters = Gio.ListStore()
|
||||||
self._filter = Gtk.FileFilter(name="Audio Files",
|
self._filter = Gtk.FileFilter(name="Audio Files",
|
||||||
mime_types=["inode/directory",
|
mime_types=["inode/directory",
|
||||||
|
@ -23,6 +25,9 @@ class Button(Gtk.Button):
|
||||||
|
|
||||||
self._filters.append(self._filter)
|
self._filters.append(self._filter)
|
||||||
|
|
||||||
|
self.connect("activated", self.__on_activated)
|
||||||
|
self.add_prefix(self._prefix)
|
||||||
|
|
||||||
def __async_ready(self, dialog: Gtk.FileDialog, task: Gio.Task) -> None:
|
def __async_ready(self, dialog: Gtk.FileDialog, task: Gio.Task) -> None:
|
||||||
try:
|
try:
|
||||||
file = dialog.open_finish(task)
|
file = dialog.open_finish(task)
|
||||||
|
@ -30,8 +35,9 @@ class Button(Gtk.Button):
|
||||||
except GLib.Error:
|
except GLib.Error:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def do_clicked(self) -> None:
|
def __on_activated(self, row: Adw.ActionRow) -> None:
|
||||||
"""Handle a click event."""
|
"""Handle activating an OpenRow."""
|
||||||
|
self.get_ancestor(Gtk.Popover).popdown()
|
||||||
self._dialog.open(self.get_ancestor(Gtk.Window), None,
|
self._dialog.open(self.get_ancestor(Gtk.Window), None,
|
||||||
self.__async_ready)
|
self.__async_ready)
|
||||||
|
|
||||||
|
|
|
@ -52,8 +52,10 @@ class TestHeader(tests.util.TestCase):
|
||||||
self.assertFalse(self.header.show_sidebar)
|
self.assertFalse(self.header.show_sidebar)
|
||||||
|
|
||||||
def test_open(self):
|
def test_open(self):
|
||||||
"""Check that the Open button works as expected."""
|
"""Check that the Open ActionRow works as expected."""
|
||||||
self.assertIsInstance(self.header._open, emmental.header.open.Button)
|
self.assertIsInstance(self.header._open, emmental.header.open.OpenRow)
|
||||||
|
self.assertEqual(self.header._menu_box.get_row_at_index(0),
|
||||||
|
self.header._open)
|
||||||
|
|
||||||
signal = unittest.mock.Mock()
|
signal = unittest.mock.Mock()
|
||||||
self.header.connect("track-requested", signal)
|
self.header.connect("track-requested", signal)
|
||||||
|
@ -95,6 +97,9 @@ class TestHeader(tests.util.TestCase):
|
||||||
Gtk.SelectionMode.NONE)
|
Gtk.SelectionMode.NONE)
|
||||||
self.assertTrue(self.header._menu_box.has_css_class("boxed-list"))
|
self.assertTrue(self.header._menu_box.has_css_class("boxed-list"))
|
||||||
|
|
||||||
|
self.assertEqual(self.header._menu_box.get_row_at_index(0),
|
||||||
|
self.header._open)
|
||||||
|
|
||||||
def test_volume_icons(self):
|
def test_volume_icons(self):
|
||||||
"""Check that the volume icons box is set up properly."""
|
"""Check that the volume icons box is set up properly."""
|
||||||
self.assertIsInstance(self.header._icons, Gtk.Box)
|
self.assertIsInstance(self.header._icons, Gtk.Box)
|
||||||
|
|
|
@ -1,58 +1,69 @@
|
||||||
# Copyright 2023 (c) Anna Schumaker.
|
# Copyright 2023 (c) Anna Schumaker.
|
||||||
"""Tests our Open button."""
|
"""Tests our Open Adw.ActionRow."""
|
||||||
import emmental.header.open
|
import emmental.header.open
|
||||||
import pathlib
|
import pathlib
|
||||||
import unittest
|
import unittest
|
||||||
from gi.repository import Gio
|
from gi.repository import Gio
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import Adw
|
||||||
|
|
||||||
|
|
||||||
class TestButton(unittest.TestCase):
|
class TestOpenRow(unittest.TestCase):
|
||||||
"""Test the Open button."""
|
"""Test the Open row."""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Set up common variables."""
|
"""Set up common variables."""
|
||||||
self.button = emmental.header.open.Button()
|
self.row = emmental.header.open.OpenRow()
|
||||||
|
|
||||||
def test_button(self):
|
def test_action_row(self):
|
||||||
"""Check that the button was set up properly."""
|
"""Check that the action row was set up properly."""
|
||||||
self.assertIsInstance(self.button, Gtk.Button)
|
self.assertIsInstance(self.row, Adw.ActionRow)
|
||||||
self.assertEqual(self.button.get_icon_name(), "document-open-symbolic")
|
self.assertIsInstance(self.row._prefix, Gtk.Image)
|
||||||
self.assertEqual(self.button.get_tooltip_text(),
|
|
||||||
"open a file for playback")
|
self.assertEqual(self.row.props.title, "Open File")
|
||||||
|
self.assertEqual(self.row.props.subtitle, "Select a file for playback")
|
||||||
|
self.assertTrue(self.row.props.activatable)
|
||||||
|
|
||||||
|
self.assertEqual(self.row._prefix.props.icon_name,
|
||||||
|
"document-open-symbolic")
|
||||||
|
|
||||||
def test_filter(self):
|
def test_filter(self):
|
||||||
"""Check that the file filter is set up properly."""
|
"""Check that the file filter is set up properly."""
|
||||||
self.assertIsInstance(self.button._filter, Gtk.FileFilter)
|
self.assertIsInstance(self.row._filter, Gtk.FileFilter)
|
||||||
self.assertIsInstance(self.button._filters, Gio.ListStore)
|
self.assertIsInstance(self.row._filters, Gio.ListStore)
|
||||||
|
|
||||||
self.assertEqual(self.button._filter.get_name(), "Audio Files")
|
self.assertEqual(self.row._filter.get_name(), "Audio Files")
|
||||||
self.assertEqual(self.button._filters[0], self.button._filter)
|
self.assertEqual(self.row._filters[0], self.row._filter)
|
||||||
|
|
||||||
def test_dialog(self):
|
def test_dialog(self):
|
||||||
"""Check that the file dialog is set up properly."""
|
"""Check that the file dialog is set up properly."""
|
||||||
self.assertIsInstance(self.button._dialog, Gtk.FileDialog)
|
self.assertIsInstance(self.row._dialog, Gtk.FileDialog)
|
||||||
self.assertEqual(self.button._dialog.get_title(), "Pick a Track")
|
self.assertEqual(self.row._dialog.get_title(), "Pick a Track")
|
||||||
self.assertEqual(self.button._dialog.get_filters(),
|
self.assertEqual(self.row._dialog.get_filters(),
|
||||||
self.button._filters)
|
self.row._filters)
|
||||||
self.assertTrue(self.button._dialog.get_modal())
|
self.assertTrue(self.row._dialog.get_modal())
|
||||||
|
|
||||||
def test_clicked(self):
|
def test_activate(self):
|
||||||
"""Test clicking on the button."""
|
"""Test activating an OpenRow."""
|
||||||
with unittest.mock.patch.object(self.button._dialog,
|
listbox = Gtk.ListBox()
|
||||||
"open") as mock_open:
|
popover = Gtk.Popover(child=listbox)
|
||||||
self.button.emit("clicked")
|
listbox.append(self.row)
|
||||||
mock_open.assert_called_with(None, None,
|
|
||||||
self.button._Button__async_ready)
|
|
||||||
|
|
||||||
with unittest.mock.patch.object(self.button._dialog,
|
with unittest.mock.patch.object(popover, "popdown") as mock_popdown:
|
||||||
|
with unittest.mock.patch.object(self.row._dialog,
|
||||||
|
"open") as mock_open:
|
||||||
|
self.row.emit("activated")
|
||||||
|
mock_popdown.assert_called()
|
||||||
|
mock_open.assert_called_with(None, None,
|
||||||
|
self.row._OpenRow__async_ready)
|
||||||
|
|
||||||
|
with unittest.mock.patch.object(self.row._dialog,
|
||||||
"open_finish") as mock_finish:
|
"open_finish") as mock_finish:
|
||||||
task = Gio.Task()
|
task = Gio.Task()
|
||||||
signal = unittest.mock.Mock()
|
signal = unittest.mock.Mock()
|
||||||
mock_finish.return_value = Gio.File.new_for_path("/a/b/c/1.ogg")
|
mock_finish.return_value = Gio.File.new_for_path("/a/b/c/1.ogg")
|
||||||
self.button.connect("track-requested", signal)
|
self.row.connect("track-requested", signal)
|
||||||
|
|
||||||
self.button._Button__async_ready(self.button._dialog, task)
|
self.row._OpenRow__async_ready(self.row._dialog, task)
|
||||||
mock_finish.assert_called_with(task)
|
mock_finish.assert_called_with(task)
|
||||||
signal.assert_called_with(self.button,
|
signal.assert_called_with(self.row, pathlib.Path("/a/b/c/1.ogg"))
|
||||||
pathlib.Path("/a/b/c/1.ogg"))
|
|
||||||
|
|
Loading…
Reference in New Issue