Compare commits

...

6 Commits

Author SHA1 Message Date
Anna Schumaker e846c957a5 Emmental 3.0.3
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-06-16 10:30:19 -04:00
Anna Schumaker 37f81825b1 sidebar: Give the New Playlist entry the "card" style class
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-06-16 10:17:38 -04:00
Anna Schumaker c375d2366a sidebar: Give sidebar widgets tooltip properties
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-06-10 21:30:43 -04:00
Anna Schumaker d807f8bd36 buttons: Replace the icon-size property with large-icon
It is much easier to pass a single boolean value instead of a Gtk
constant for specifying the icon size.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-06-10 21:30:41 -04:00
Anna Schumaker a13e481754 buttons: Give the ImageToggle active and inactive tooltip texts
This is used to set the tooltip text to fixed strings based on the
active status of the button. I also update the tooltip text on the
Favorite button in the Now Playing widget at the same time.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-06-10 20:31:41 -04:00
Anna Schumaker afb0ba5d68 buttons: Add missing docstring to the SplitButton.activate() function
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-06-10 19:28:24 -04:00
20 changed files with 150 additions and 73 deletions

View File

@ -21,7 +21,7 @@ from gi.repository import Adw
MAJOR_VERSION = 3 MAJOR_VERSION = 3
MINOR_VERSION = 0 MINOR_VERSION = 0
MICRO_VERSION = 2 MICRO_VERSION = 3
VERSION_NUMBER = f"{MAJOR_VERSION}.{MINOR_VERSION}.{MICRO_VERSION}" VERSION_NUMBER = f"{MAJOR_VERSION}.{MINOR_VERSION}.{MICRO_VERSION}"
VERSION_STRING = f"Emmental {VERSION_NUMBER}{gsetup.DEBUG_STR}" VERSION_STRING = f"Emmental {VERSION_NUMBER}{gsetup.DEBUG_STR}"

View File

@ -8,22 +8,29 @@ class Button(Gtk.Button):
"""A Gtk.Button with extra properties and default large size.""" """A Gtk.Button with extra properties and default large size."""
icon_name = GObject.Property(type=str) icon_name = GObject.Property(type=str)
icon_size = GObject.Property(type=Gtk.IconSize,
default=Gtk.IconSize.NORMAL)
icon_opacity = GObject.Property(type=float, default=1.0, icon_opacity = GObject.Property(type=float, default=1.0,
minimum=0.0, maximum=1.0) minimum=0.0, maximum=1.0)
def __init__(self, **kwargs): def __init__(self, large_icon: bool = False, **kwargs):
"""Initialize a Button.""" """Initialize a Button."""
super().__init__(focusable=False, **kwargs) super().__init__(focusable=False, **kwargs)
self._image = Gtk.Image(icon_name=self.icon_name, icon_size = Gtk.IconSize.LARGE if large_icon else Gtk.IconSize.NORMAL
icon_size=self.icon_size, self._image = Gtk.Image(icon_name=self.icon_name, icon_size=icon_size,
opacity=self.icon_opacity) opacity=self.icon_opacity)
self.bind_property("icon-name", self._image, "icon-name") self.bind_property("icon-name", self._image, "icon-name")
self.bind_property("icon-size", self._image, "icon-size")
self.bind_property("icon-opacity", self._image, "opacity") self.bind_property("icon-opacity", self._image, "opacity")
self.set_child(self._image) self.set_child(self._image)
@GObject.Property(type=bool, default=False)
def large_icon(self) -> bool:
"""Get if this Button has a large icon."""
return self._image.get_icon_size() == Gtk.IconSize.LARGE
@large_icon.setter
def large_icon(self, newval: bool) -> None:
size = Gtk.IconSize.LARGE if newval else Gtk.IconSize.NORMAL
self._image.set_icon_size(size)
class PopoverButton(Gtk.MenuButton): class PopoverButton(Gtk.MenuButton):
"""A MenuButton with a Gtk.Popover attached.""" """A MenuButton with a Gtk.Popover attached."""
@ -45,20 +52,19 @@ class SplitButton(Gtk.Box):
"""A Button and secondary widget packed together.""" """A Button and secondary widget packed together."""
icon_name = GObject.Property(type=str) icon_name = GObject.Property(type=str)
icon_size = GObject.Property(type=Gtk.IconSize, large_icon = GObject.Property(type=bool, default=False)
default=Gtk.IconSize.NORMAL)
def __init__(self, secondary: Gtk.Button, **kwargs): def __init__(self, secondary: Gtk.Button, **kwargs):
"""Initialize a Split Button.""" """Initialize a Split Button."""
super().__init__(**kwargs) super().__init__(**kwargs)
self._primary = Button(hexpand=True, icon_name=self.icon_name, self._primary = Button(hexpand=True, icon_name=self.icon_name,
icon_size=self.icon_size) large_icon=self.large_icon)
self._separator = Gtk.Separator(orientation=Gtk.Orientation.VERTICAL, self._separator = Gtk.Separator(orientation=Gtk.Orientation.VERTICAL,
margin_top=12, margin_bottom=12) margin_top=12, margin_bottom=12)
self._secondary = secondary self._secondary = secondary
self.bind_property("icon-name", self._primary, "icon-name") self.bind_property("icon-name", self._primary, "icon-name")
self.bind_property("icon-size", self._primary, "icon-size") self.bind_property("large-icon", self._primary, "large-icon")
self._primary.connect("activate", self.__activate) self._primary.connect("activate", self.__activate)
self._primary.connect("clicked", self.__clicked) self._primary.connect("clicked", self.__clicked)
@ -75,6 +81,7 @@ class SplitButton(Gtk.Box):
self.emit("clicked") self.emit("clicked")
def activate(self, *args) -> None: def activate(self, *args) -> None:
"""Activate the primary button."""
self._primary.activate() self._primary.activate()
@GObject.Property(type=Gtk.Button, flags=GObject.ParamFlags.READABLE) @GObject.Property(type=Gtk.Button, flags=GObject.ParamFlags.READABLE)
@ -95,14 +102,23 @@ class ImageToggle(Button):
"""Inspired by a ToggleButton, but changes image based on state.""" """Inspired by a ToggleButton, but changes image based on state."""
active_icon_name = GObject.Property(type=str) active_icon_name = GObject.Property(type=str)
active_tooltip_text = GObject.Property(type=str)
inactive_icon_name = GObject.Property(type=str) inactive_icon_name = GObject.Property(type=str)
inactive_tooltip_text = GObject.Property(type=str)
def __init__(self, active_icon_name: str, inactive_icon_name: str, def __init__(self, active_icon_name: str, inactive_icon_name: str,
active: bool = False, **kwargs) -> None: active_tooltip_text: str | None = None,
inactive_tooltip_text: str | None = None,
*, active: bool = False, **kwargs) -> None:
"""Initialize an ImageToggle button.""" """Initialize an ImageToggle button."""
super().__init__(active_icon_name=active_icon_name, super().__init__(active_icon_name=active_icon_name,
inactive_icon_name=inactive_icon_name, inactive_icon_name=inactive_icon_name,
icon_name=inactive_icon_name, active=active, **kwargs) icon_name=inactive_icon_name,
active_tooltip_text=active_tooltip_text,
inactive_tooltip_text=inactive_tooltip_text,
tooltip_text=inactive_tooltip_text,
active=active, **kwargs)
def do_clicked(self) -> None: def do_clicked(self) -> None:
"""Handle a click event.""" """Handle a click event."""
@ -116,8 +132,12 @@ class ImageToggle(Button):
@active.setter @active.setter
def active(self, newval: bool) -> None: def active(self, newval: bool) -> None:
if newval != self.active: if newval != self.active:
icon = self.active_icon_name if newval else self.inactive_icon_name if newval:
self.icon_name = icon self.icon_name = self.active_icon_name
self.props.tooltip_text = self.active_tooltip_text
else:
self.icon_name = self.inactive_icon_name
self.props.tooltip_text = self.inactive_tooltip_text
self.emit("toggled") self.emit("toggled")
@GObject.Signal @GObject.Signal

View File

@ -41,15 +41,15 @@ class Card(Gtk.Box):
self._bottom_box = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0) self._bottom_box = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0)
self._favorite = buttons.ImageToggle("heart-filled", self._favorite = buttons.ImageToggle("heart-filled",
"heart-outline-thick-symbolic", "heart-outline-thick-symbolic",
tooltip_text="add to " "remove from 'Favorite Tracks'",
"'Favorite Tracks'", "add to 'Favorite Tracks'",
icon_size=Gtk.IconSize.LARGE, large_icon=True,
has_frame=False, sensitive=False, has_frame=False, sensitive=False,
valign=Gtk.Align.CENTER) valign=Gtk.Align.CENTER)
self._jump = buttons.Button(icon_name="go-jump", has_frame=False, self._jump = buttons.Button(icon_name="go-jump", has_frame=False,
icon_size=Gtk.IconSize.LARGE,
tooltip_text="scroll to current track", tooltip_text="scroll to current track",
valign=Gtk.Align.CENTER, sensitive=False) large_icon=True, sensitive=False,
valign=Gtk.Align.CENTER)
self._seeker = seeker.Scale(sensitive=False) self._seeker = seeker.Scale(sensitive=False)
self.bind_property("artwork", self._artwork, "filepath") self.bind_property("artwork", self._artwork, "filepath")

View File

@ -14,7 +14,7 @@ class PillButton(buttons.Button):
def __init__(self, **kwargs): def __init__(self, **kwargs):
"""Initialize a Pill Button.""" """Initialize a Pill Button."""
super().__init__(icon_size=Gtk.IconSize.LARGE, **kwargs) super().__init__(large_icon=True, **kwargs)
self.add_css_class("pill") self.add_css_class("pill")
@ -46,7 +46,7 @@ class Controls(Gtk.Box):
self._play = PillButton(icon_name="play-large", tooltip_text="play", self._play = PillButton(icon_name="play-large", tooltip_text="play",
sensitive=False) sensitive=False)
self._pause = buttons.SplitButton(icon_name="pause-large", self._pause = buttons.SplitButton(icon_name="pause-large",
icon_size=Gtk.IconSize.LARGE, large_icon=True,
tooltip_text="pause", tooltip_text="pause",
secondary=self._autopause, secondary=self._autopause,
visible=False, sensitive=False) visible=False, sensitive=False)

View File

@ -1,7 +1,6 @@
# Copyright 2022 (c) Anna Schumaker. # Copyright 2022 (c) Anna Schumaker.
"""Displays our artist and album tree.""" """Displays our artist and album tree."""
from gi.repository import GObject from gi.repository import GObject
from gi.repository import Gtk
from ..buttons import ImageToggle from ..buttons import ImageToggle
from .. import db from .. import db
from . import row from . import row
@ -36,8 +35,9 @@ class Section(section.Section):
subtitle="0 artists, 0 albums", subtitle="0 artists, 0 albums",
icon_name="library-artists", album_table=album_table) icon_name="library-artists", album_table=album_table)
self.extra_widget = ImageToggle("music-artist", "music-artist2", self.extra_widget = ImageToggle("music-artist", "music-artist2",
icon_size=Gtk.IconSize.NORMAL, "show album artists",
has_frame=False) "show all artists",
large_icon=False, has_frame=False)
self.album_table.connect("items-changed", self.__update_subtitle) self.album_table.connect("items-changed", self.__update_subtitle)
self.bind_property("show-all", self.extra_widget, "active", self.bind_property("show-all", self.extra_widget, "active",
GObject.BindingFlags.BIDIRECTIONAL) GObject.BindingFlags.BIDIRECTIONAL)

View File

@ -41,7 +41,8 @@ class Section(section.Section):
"""Initialize our library path section.""" """Initialize our library path section."""
super().__init__(table, LibraryRow, icon_name="library-music", super().__init__(table, LibraryRow, icon_name="library-music",
title="Library Paths", subtitle="0 library paths") title="Library Paths", subtitle="0 library paths")
self.extra_widget = Gtk.Button(icon_name="folder-new", has_frame=False) self.extra_widget = Gtk.Button(icon_name="folder-new", has_frame=False,
tooltip_text="add new library path")
self._dialog = Gtk.FileDialog(title="Pick a Directory", self._dialog = Gtk.FileDialog(title="Pick a Directory",
filters=DIRECTORY_FILTERS) filters=DIRECTORY_FILTERS)
self._toast = None self._toast = None

View File

@ -50,12 +50,15 @@ class Section(section.Section):
self._entry = Gtk.Entry(placeholder_text="add new playlist", self._entry = Gtk.Entry(placeholder_text="add new playlist",
primary_icon_name="list-add") primary_icon_name="list-add")
self.extra_widget = buttons.PopoverButton(icon_name="document-new", self.extra_widget = buttons.PopoverButton(icon_name="document-new",
tooltip_text=("add new "
"playlist"),
has_frame=False, has_frame=False,
popover_child=self._entry) popover_child=self._entry)
self._entry.connect("activate", self.__add_new_playlist) self._entry.connect("activate", self.__add_new_playlist)
self._entry.connect("changed", self.__entry_changed) self._entry.connect("changed", self.__entry_changed)
self._entry.connect("icon-release", self.__entry_icon_release) self._entry.connect("icon-release", self.__entry_icon_release)
self._entry.add_css_class("card")
def __add_new_playlist(self, entry: Gtk.Entry) -> None: def __add_new_playlist(self, entry: Gtk.Entry) -> None:
if self.table.create(entry.get_text()) is not None: if self.table.create(entry.get_text()) is not None:

View File

@ -63,6 +63,7 @@ class PlaylistRow(BaseRow):
self._icon = Settable() self._icon = Settable()
self._title = EditableTitle(margin_start=12, margin_end=12) self._title = EditableTitle(margin_start=12, margin_end=12)
self._delete = Gtk.Button(icon_name="big-x-symbolic", self._delete = Gtk.Button(icon_name="big-x-symbolic",
tooltip_text="delete playlist",
valign=Gtk.Align.CENTER, valign=Gtk.Align.CENTER,
has_frame=False, visible=False) has_frame=False, visible=False)
@ -109,13 +110,17 @@ class LibraryRow(BaseRow):
super().__init__(**kwargs) super().__init__(**kwargs)
self._box = Gtk.Box() self._box = Gtk.Box()
self._overlay = Gtk.Overlay(child=self._box) self._overlay = Gtk.Overlay(child=self._box)
self._switch = Gtk.Switch(active=self.enabled, valign=Gtk.Align.CENTER) self._switch = Gtk.Switch(active=self.enabled, valign=Gtk.Align.CENTER,
tooltip_text="disable library path")
self._title = PlaylistTitle(margin_start=12, margin_end=12) self._title = PlaylistTitle(margin_start=12, margin_end=12)
self._scan = Gtk.Button(icon_name="update", has_frame=False, self._scan = Gtk.Button(icon_name="update", has_frame=False,
tooltip_text="update library path",
valign=Gtk.Align.CENTER) valign=Gtk.Align.CENTER)
self._stop = Gtk.Button(icon_name="stop-sign-large", has_frame=False, self._stop = Gtk.Button(icon_name="stop-sign-large", has_frame=False,
tooltip_text="cancel update",
valign=Gtk.Align.CENTER, visible=False) valign=Gtk.Align.CENTER, visible=False)
self._delete = Gtk.Button(icon_name="big-x-symbolic", self._delete = Gtk.Button(icon_name="big-x-symbolic",
tooltip_text="delete library path",
valign=Gtk.Align.CENTER, has_frame=False) valign=Gtk.Align.CENTER, has_frame=False)
self._progress = Gtk.ProgressBar(valign=Gtk.Align.END, visible=False) self._progress = Gtk.ProgressBar(valign=Gtk.Align.END, visible=False)
@ -137,6 +142,7 @@ class LibraryRow(BaseRow):
self._delete.connect("clicked", self.__on_button_press, "delete") self._delete.connect("clicked", self.__on_button_press, "delete")
self._scan.connect("clicked", self.__on_button_press, "scan") self._scan.connect("clicked", self.__on_button_press, "scan")
self._stop.connect("clicked", self.__on_button_press, "stop") self._stop.connect("clicked", self.__on_button_press, "stop")
self._switch.connect("notify::active", self.__on_switch_activated)
self._delete.add_css_class("emmental-delete") self._delete.add_css_class("emmental-delete")
self._stop.add_css_class("emmental-stop") self._stop.add_css_class("emmental-stop")
@ -157,6 +163,10 @@ class LibraryRow(BaseRow):
case "scan": self.playlist.scan() case "scan": self.playlist.scan()
case "stop": self.playlist.stop() case "stop": self.playlist.stop()
def __on_switch_activated(self, switch: Gtk.Switch, param) -> None:
state = "disable" if self.enabled else "enable"
self._switch.set_tooltip_text(f"{state} library path")
class TreeRow(factory.TreeRow): class TreeRow(factory.TreeRow):
"""A factory Row used for displaying individual playlists.""" """A factory Row used for displaying individual playlists."""

View File

@ -54,7 +54,7 @@ class LoopButton(buttons.ImageToggle):
"""Initialize a Loop Button.""" """Initialize a Loop Button."""
super().__init__(active_icon_name="media-playlist-repeat-song", super().__init__(active_icon_name="media-playlist-repeat-song",
inactive_icon_name="media-playlist-repeat", inactive_icon_name="media-playlist-repeat",
icon_size=Gtk.IconSize.NORMAL, state="None", large_icon=False, state="None",
has_frame=False, **kwargs) has_frame=False, **kwargs)
def do_clicked(self): def do_clicked(self):
@ -94,7 +94,7 @@ class ShuffleButton(buttons.ImageToggle):
"""Initialize a Shuffle Button.""" """Initialize a Shuffle Button."""
super().__init__(active_icon_name="media-playlist-shuffle", super().__init__(active_icon_name="media-playlist-shuffle",
inactive_icon_name="media-playlist-consecutive", inactive_icon_name="media-playlist-consecutive",
icon_size=Gtk.IconSize.NORMAL, icon_opacity=0.5, large_icon=False, icon_opacity=0.5,
has_frame=False, **kwargs) has_frame=False, **kwargs)
def do_toggled(self): def do_toggled(self):
@ -113,8 +113,7 @@ class SortFieldWidget(Gtk.Box):
self._enabled = Gtk.Switch(valign=Gtk.Align.CENTER) self._enabled = Gtk.Switch(valign=Gtk.Align.CENTER)
self._name = Gtk.Label(hexpand=True, sensitive=False) self._name = Gtk.Label(hexpand=True, sensitive=False)
self._reverse = buttons.ImageToggle("arrow1-up", "arrow1-down", self._reverse = buttons.ImageToggle("arrow1-up", "arrow1-down",
icon_size=Gtk.IconSize.NORMAL, large_icon=False, sensitive=False)
sensitive=False)
self._box = Gtk.Box(sensitive=False) self._box = Gtk.Box(sensitive=False)
self._move_up = Gtk.Button(icon_name="go-up-symbolic") self._move_up = Gtk.Button(icon_name="go-up-symbolic")
self._move_down = Gtk.Button(icon_name="go-down-symbolic") self._move_down = Gtk.Button(icon_name="go-down-symbolic")

View File

@ -330,9 +330,8 @@ class FavoriteButton(TrackRow):
"""Initialize a Favorite Button.""" """Initialize a Favorite Button."""
super().__init__(listitem, property=property) super().__init__(listitem, property=property)
self.child = buttons.ImageToggle("heart-filled", "heart-outline-thick", self.child = buttons.ImageToggle("heart-filled", "heart-outline-thick",
icon_size=Gtk.IconSize.NORMAL, large_icon=False, has_frame=False,
valign=Gtk.Align.CENTER, valign=Gtk.Align.CENTER)
has_frame=False)
def do_bind(self): def do_bind(self):
"""Bind a track property to the Toggle Button.""" """Bind a track property to the Toggle Button."""

View File

@ -13,7 +13,7 @@ class TestButtons(unittest.TestCase):
"""Test that the pill button is configured correctly.""" """Test that the pill button is configured correctly."""
button = emmental.nowplaying.controls.PillButton() button = emmental.nowplaying.controls.PillButton()
self.assertIsInstance(button, emmental.buttons.Button) self.assertIsInstance(button, emmental.buttons.Button)
self.assertEqual(button.icon_size, Gtk.IconSize.LARGE) self.assertTrue(button.large_icon)
self.assertTrue(button.has_css_class("pill")) self.assertTrue(button.has_css_class("pill"))
@ -99,13 +99,13 @@ class TestControls(unittest.TestCase):
"""Test the pause button.""" """Test the pause button."""
self.assertIsInstance(self.controls._pause, self.assertIsInstance(self.controls._pause,
emmental.buttons.SplitButton) emmental.buttons.SplitButton)
self.assertEqual(self.controls._pause.get_tooltip_text(), "pause")
self.assertEqual(self.controls._pause.icon_name, "pause-large")
self.assertEqual(self.controls._pause.icon_size,
Gtk.IconSize.LARGE)
self.assertEqual(self.controls._play.get_next_sibling(), self.assertEqual(self.controls._play.get_next_sibling(),
self.controls._pause) self.controls._pause)
self.assertEqual(self.controls._pause.get_tooltip_text(), "pause")
self.assertEqual(self.controls._pause.icon_name, "pause-large")
self.assertTrue(self.controls._pause.large_icon)
self.assertFalse(self.controls._pause.get_visible()) self.assertFalse(self.controls._pause.get_visible())
self.controls.playing = True self.controls.playing = True
self.assertTrue(self.controls._pause.get_visible()) self.assertTrue(self.controls._pause.get_visible())

View File

@ -89,13 +89,15 @@ class TestNowPlaying(unittest.TestCase):
self.card._favorite) self.card._favorite)
self.assertEqual(self.card._favorite.active_icon_name, "heart-filled") self.assertEqual(self.card._favorite.active_icon_name, "heart-filled")
self.assertEqual(self.card._favorite.active_tooltip_text,
"remove from 'Favorite Tracks'")
self.assertEqual(self.card._favorite.inactive_icon_name, self.assertEqual(self.card._favorite.inactive_icon_name,
"heart-outline-thick-symbolic") "heart-outline-thick-symbolic")
self.assertEqual(self.card._favorite.get_tooltip_text(), self.assertEqual(self.card._favorite.inactive_tooltip_text,
"add to 'Favorite Tracks'") "add to 'Favorite Tracks'")
self.assertEqual(self.card._favorite.icon_size, Gtk.IconSize.LARGE)
self.assertEqual(self.card._favorite.get_valign(), Gtk.Align.CENTER) self.assertEqual(self.card._favorite.get_valign(), Gtk.Align.CENTER)
self.assertFalse(self.card._favorite.get_has_frame()) self.assertFalse(self.card._favorite.get_has_frame())
self.assertTrue(self.card._favorite.large_icon)
self.assertFalse(self.card._favorite.get_sensitive()) self.assertFalse(self.card._favorite.get_sensitive())
self.card.have_db_track = True self.card.have_db_track = True
@ -116,9 +118,9 @@ class TestNowPlaying(unittest.TestCase):
self.assertEqual(self.card._jump.icon_name, "go-jump") self.assertEqual(self.card._jump.icon_name, "go-jump")
self.assertEqual(self.card._jump.get_tooltip_text(), self.assertEqual(self.card._jump.get_tooltip_text(),
"scroll to current track") "scroll to current track")
self.assertEqual(self.card._jump.icon_size, Gtk.IconSize.LARGE)
self.assertEqual(self.card._jump.get_valign(), Gtk.Align.CENTER) self.assertEqual(self.card._jump.get_valign(), Gtk.Align.CENTER)
self.assertFalse(self.card._jump.get_has_frame()) self.assertFalse(self.card._jump.get_has_frame())
self.assertTrue(self.card._jump.large_icon)
self.assertFalse(self.card._jump.get_sensitive()) self.assertFalse(self.card._jump.get_sensitive())
self.card.have_db_track = True self.card.have_db_track = True

View File

@ -33,10 +33,13 @@ class TestArtist(tests.util.TestCase):
emmental.buttons.ImageToggle) emmental.buttons.ImageToggle)
self.assertEqual(self.artists.extra_widget.active_icon_name, self.assertEqual(self.artists.extra_widget.active_icon_name,
"music-artist") "music-artist")
self.assertEqual(self.artists.extra_widget.active_tooltip_text,
"show album artists")
self.assertEqual(self.artists.extra_widget.inactive_icon_name, self.assertEqual(self.artists.extra_widget.inactive_icon_name,
"music-artist2") "music-artist2")
self.assertEqual(self.artists.extra_widget.icon_size, self.assertEqual(self.artists.extra_widget.inactive_tooltip_text,
Gtk.IconSize.NORMAL) "show all artists")
self.assertFalse(self.artists.extra_widget.large_icon)
self.assertFalse(self.artists.extra_widget.get_has_frame()) self.assertFalse(self.artists.extra_widget.get_has_frame())
def test_subtitle(self): def test_subtitle(self):

View File

@ -33,6 +33,8 @@ class TestLibraries(tests.util.TestCase):
self.assertIsInstance(self.libraries.extra_widget, Gtk.Button) self.assertIsInstance(self.libraries.extra_widget, Gtk.Button)
self.assertEqual(self.libraries.extra_widget.get_icon_name(), self.assertEqual(self.libraries.extra_widget.get_icon_name(),
"folder-new") "folder-new")
self.assertEqual(self.libraries.extra_widget.get_tooltip_text(),
"add new library path")
self.assertFalse(self.libraries.extra_widget.get_has_frame()) self.assertFalse(self.libraries.extra_widget.get_has_frame())
mock_set_initial_file = unittest.mock.Mock() mock_set_initial_file = unittest.mock.Mock()

View File

@ -52,6 +52,8 @@ class TestPlaylists(tests.util.TestCase):
emmental.buttons.PopoverButton) emmental.buttons.PopoverButton)
self.assertEqual(self.playlists.extra_widget.get_icon_name(), self.assertEqual(self.playlists.extra_widget.get_icon_name(),
"document-new") "document-new")
self.assertEqual(self.playlists.extra_widget.get_tooltip_text(),
"add new playlist")
self.assertEqual(self.playlists.extra_widget.popover_child, self.assertEqual(self.playlists.extra_widget.popover_child,
self.playlists._entry) self.playlists._entry)
self.assertFalse(self.playlists.extra_widget.get_has_frame()) self.assertFalse(self.playlists.extra_widget.get_has_frame())
@ -65,6 +67,7 @@ class TestPlaylists(tests.util.TestCase):
Gtk.EntryIconPosition.PRIMARY), "list-add") Gtk.EntryIconPosition.PRIMARY), "list-add")
self.assertIsNone(self.playlists._entry.get_icon_name( self.assertIsNone(self.playlists._entry.get_icon_name(
Gtk.EntryIconPosition.SECONDARY)) Gtk.EntryIconPosition.SECONDARY))
self.assertTrue(self.playlists._entry.has_css_class("card"))
with unittest.mock.patch.object(self.playlists.extra_widget, with unittest.mock.patch.object(self.playlists.extra_widget,
"popdown") as mock_popdown: "popdown") as mock_popdown:

View File

@ -147,6 +147,8 @@ class TestPlaylistRow(unittest.TestCase):
self.assertEqual(self.row._title.get_next_sibling(), self.row._delete) self.assertEqual(self.row._title.get_next_sibling(), self.row._delete)
self.assertEqual(self.row._delete.get_icon_name(), "big-x-symbolic") self.assertEqual(self.row._delete.get_icon_name(), "big-x-symbolic")
self.assertEqual(self.row._delete.get_tooltip_text(),
"delete playlist")
self.assertEqual(self.row._delete.get_valign(), Gtk.Align.CENTER) self.assertEqual(self.row._delete.get_valign(), Gtk.Align.CENTER)
self.assertFalse(self.row._delete.get_has_frame()) self.assertFalse(self.row._delete.get_has_frame())
self.assertTrue(self.row._delete.has_css_class("emmental-delete")) self.assertTrue(self.row._delete.has_css_class("emmental-delete"))
@ -209,14 +211,20 @@ class TestLibraryRow(unittest.TestCase):
self.assertTrue(self.row.enabled) self.assertTrue(self.row.enabled)
self.assertTrue(self.row._switch.get_active()) self.assertTrue(self.row._switch.get_active())
self.assertTrue(self.row._title.get_sensitive()) self.assertTrue(self.row._title.get_sensitive())
self.assertEqual(self.row._switch.get_tooltip_text(),
"disable library path")
self.row.enabled = False self.row.enabled = False
self.assertFalse(self.row._switch.get_active()) self.assertFalse(self.row._switch.get_active())
self.assertFalse(self.row._title.get_sensitive()) self.assertFalse(self.row._title.get_sensitive())
self.assertEqual(self.row._switch.get_tooltip_text(),
"enable library path")
self.row._switch.set_active(True) self.row._switch.set_active(True)
self.assertTrue(self.row.enabled) self.assertTrue(self.row.enabled)
self.assertTrue(self.row._title.get_sensitive()) self.assertTrue(self.row._title.get_sensitive())
self.assertEqual(self.row._switch.get_tooltip_text(),
"disable library path")
def test_progress(self): def test_progress(self):
"""Test the progress bar widget and property.""" """Test the progress bar widget and property."""
@ -247,6 +255,8 @@ class TestLibraryRow(unittest.TestCase):
"""Test the scan button.""" """Test the scan button."""
self.assertIsInstance(self.row._scan, Gtk.Button) self.assertIsInstance(self.row._scan, Gtk.Button)
self.assertEqual(self.row._scan.get_icon_name(), "update") self.assertEqual(self.row._scan.get_icon_name(), "update")
self.assertEqual(self.row._scan.get_tooltip_text(),
"update library path")
self.assertEqual(self.row._scan.get_valign(), Gtk.Align.CENTER) self.assertEqual(self.row._scan.get_valign(), Gtk.Align.CENTER)
self.assertFalse(self.row._scan.get_has_frame()) self.assertFalse(self.row._scan.get_has_frame())
self.assertEqual(self.row._title.get_next_sibling(), self.row._scan) self.assertEqual(self.row._title.get_next_sibling(), self.row._scan)
@ -262,6 +272,7 @@ class TestLibraryRow(unittest.TestCase):
"""Test the stop button.""" """Test the stop button."""
self.assertIsInstance(self.row._stop, Gtk.Button) self.assertIsInstance(self.row._stop, Gtk.Button)
self.assertEqual(self.row._stop.get_icon_name(), "stop-sign-large") self.assertEqual(self.row._stop.get_icon_name(), "stop-sign-large")
self.assertEqual(self.row._stop.get_tooltip_text(), "cancel update")
self.assertEqual(self.row._stop.get_valign(), Gtk.Align.CENTER) self.assertEqual(self.row._stop.get_valign(), Gtk.Align.CENTER)
self.assertFalse(self.row._stop.get_has_frame()) self.assertFalse(self.row._stop.get_has_frame())
self.assertTrue(self.row._stop.has_css_class("emmental-stop")) self.assertTrue(self.row._stop.has_css_class("emmental-stop"))
@ -278,6 +289,8 @@ class TestLibraryRow(unittest.TestCase):
"""Test the delete button.""" """Test the delete button."""
self.assertIsInstance(self.row._delete, Gtk.Button) self.assertIsInstance(self.row._delete, Gtk.Button)
self.assertEqual(self.row._delete.get_icon_name(), "big-x-symbolic") self.assertEqual(self.row._delete.get_icon_name(), "big-x-symbolic")
self.assertEqual(self.row._delete.get_tooltip_text(),
"delete library path")
self.assertEqual(self.row._delete.get_valign(), Gtk.Align.CENTER) self.assertEqual(self.row._delete.get_valign(), Gtk.Align.CENTER)
self.assertFalse(self.row._delete.get_has_frame()) self.assertFalse(self.row._delete.get_has_frame())
self.assertTrue(self.row._delete.has_css_class("emmental-delete")) self.assertTrue(self.row._delete.has_css_class("emmental-delete"))

View File

@ -30,17 +30,6 @@ class TestButton(unittest.TestCase):
self.assertEqual(button2.icon_name, "icon-name") self.assertEqual(button2.icon_name, "icon-name")
self.assertEqual(button2._image.get_icon_name(), "icon-name") self.assertEqual(button2._image.get_icon_name(), "icon-name")
def test_icon_size(self):
"""Test the icon-size property."""
self.assertEqual(self.button.icon_size, Gtk.IconSize.NORMAL)
self.button.icon_size = Gtk.IconSize.LARGE
self.assertEqual(self.button._image.get_icon_size(),
Gtk.IconSize.LARGE)
button2 = emmental.buttons.Button(icon_size=Gtk.IconSize.LARGE)
self.assertEqual(button2.icon_size, Gtk.IconSize.LARGE)
self.assertEqual(button2._image.get_icon_size(), Gtk.IconSize.LARGE)
def test_icon_opacity(self): def test_icon_opacity(self):
"""Test the icon-opacity property.""" """Test the icon-opacity property."""
self.assertEqual(self.button.icon_opacity, 1.0) self.assertEqual(self.button.icon_opacity, 1.0)
@ -52,6 +41,20 @@ class TestButton(unittest.TestCase):
self.assertAlmostEqual(button2.icon_opacity, 0.25, delta=0.005) self.assertAlmostEqual(button2.icon_opacity, 0.25, delta=0.005)
self.assertAlmostEqual(button2._image.get_opacity(), 0.25, delta=0.005) self.assertAlmostEqual(button2._image.get_opacity(), 0.25, delta=0.005)
def test_large_icon(self):
"""Test the large-icon property."""
self.assertFalse(self.button.large_icon)
self.assertEqual(self.button._image.get_icon_size(),
Gtk.IconSize.NORMAL)
self.button.large_icon = True
self.assertEqual(self.button._image.get_icon_size(),
Gtk.IconSize.LARGE)
button2 = emmental.buttons.Button(large_icon=True)
self.assertTrue(button2.large_icon)
self.assertEqual(button2._image.get_icon_size(), Gtk.IconSize.LARGE)
class TestPopoverButton(unittest.TestCase): class TestPopoverButton(unittest.TestCase):
"""Test a Popover Button.""" """Test a Popover Button."""
@ -123,16 +126,16 @@ class TestSplitButton(unittest.TestCase):
self.assertEqual(button2.icon_name, "icon-name") self.assertEqual(button2.icon_name, "icon-name")
self.assertEqual(button2._primary.icon_name, "icon-name") self.assertEqual(button2._primary.icon_name, "icon-name")
def test_icon_size(self): def test_large_icon(self):
"""Test the icon size property.""" """Test the large icon property."""
self.assertEqual(self.button.icon_size, Gtk.IconSize.NORMAL) self.assertFalse(self.button.large_icon)
self.button.icon_size = Gtk.IconSize.LARGE self.button.large_icon = True
self.assertEqual(self.button._primary.icon_size, Gtk.IconSize.LARGE) self.assertTrue(self.button._primary.large_icon)
button2 = emmental.buttons.SplitButton(icon_size=Gtk.IconSize.LARGE, button2 = emmental.buttons.SplitButton(large_icon=True,
secondary=Gtk.Button()) secondary=Gtk.Button())
self.assertEqual(button2.icon_size, Gtk.IconSize.LARGE) self.assertTrue(button2.large_icon)
self.assertEqual(button2._primary.icon_size, Gtk.IconSize.LARGE) self.assertTrue(button2._primary.large_icon)
def test_secondary(self): def test_secondary(self):
"""Test the secondary property.""" """Test the secondary property."""
@ -190,6 +193,24 @@ class TestImageToggle(unittest.TestCase):
active=True) active=True)
self.assertTrue(button2.active) self.assertTrue(button2.active)
def test_tooltip_text(self):
"""Test the active and inactive tooltip text."""
self.assertEqual(self.button.active_tooltip_text, None)
self.assertEqual(self.button.inactive_tooltip_text, None)
button2 = emmental.buttons.ImageToggle("active", "inactive",
"active tooltip text",
"inactive tooltip text")
self.assertEqual(button2.active_tooltip_text, "active tooltip text")
self.assertEqual(button2.inactive_tooltip_text,
"inactive tooltip text")
self.assertEqual(button2.get_tooltip_text(), "inactive tooltip text")
button2.active = True
self.assertEqual(button2.get_tooltip_text(), "active tooltip text")
button2.active = False
self.assertEqual(button2.get_tooltip_text(), "inactive tooltip text")
def test_toggle(self): def test_toggle(self):
"""Test the toggle signal.""" """Test the toggle signal."""
toggled = unittest.mock.Mock() toggled = unittest.mock.Mock()

View File

@ -22,9 +22,9 @@ class TestEmmental(unittest.TestCase):
"""Check that version constants have been set properly.""" """Check that version constants have been set properly."""
self.assertEqual(emmental.MAJOR_VERSION, 3) self.assertEqual(emmental.MAJOR_VERSION, 3)
self.assertEqual(emmental.MINOR_VERSION, 0) self.assertEqual(emmental.MINOR_VERSION, 0)
self.assertEqual(emmental.MICRO_VERSION, 2) self.assertEqual(emmental.MICRO_VERSION, 3)
self.assertEqual(emmental.VERSION_NUMBER, "3.0.2") self.assertEqual(emmental.VERSION_NUMBER, "3.0.3")
self.assertEqual(emmental.VERSION_STRING, "Emmental 3.0.2-debug") self.assertEqual(emmental.VERSION_STRING, "Emmental 3.0.3-debug")
def test_application(self): def test_application(self):
"""Check that the application instance is initialized properly.""" """Check that the application instance is initialized properly."""
@ -63,7 +63,7 @@ class TestEmmental(unittest.TestCase):
mock_startup.assert_called() mock_startup.assert_called()
mock_load.assert_called() mock_load.assert_called()
mock_add_window.assert_called_with(self.application.win) mock_add_window.assert_called_with(self.application.win)
mock_set_useragent.assert_called_with("emmental-debug", "3.0.2") mock_set_useragent.assert_called_with("emmental-debug", "3.0.3")
@unittest.mock.patch("sys.stdout") @unittest.mock.patch("sys.stdout")
@unittest.mock.patch("gi.repository.Adw.Application.add_window") @unittest.mock.patch("gi.repository.Adw.Application.add_window")

View File

@ -84,7 +84,7 @@ class TestLoopButton(unittest.TestCase):
self.assertEqual(self.loop.active_icon_name, self.assertEqual(self.loop.active_icon_name,
"media-playlist-repeat-song") "media-playlist-repeat-song")
self.assertEqual(self.loop.inactive_icon_name, "media-playlist-repeat") self.assertEqual(self.loop.inactive_icon_name, "media-playlist-repeat")
self.assertEqual(self.loop.icon_size, Gtk.IconSize.NORMAL) self.assertFalse(self.loop.large_icon)
self.assertFalse(self.loop.get_has_frame()) self.assertFalse(self.loop.get_has_frame())
def test_state(self): def test_state(self):
@ -143,12 +143,12 @@ class TestShuffleButtons(unittest.TestCase):
def test_init(self): def test_init(self):
"""Test that the shuffle button is configured correctly.""" """Test that the shuffle button is configured correctly."""
self.assertIsInstance(self.shuffle, emmental.buttons.ImageToggle) self.assertIsInstance(self.shuffle, emmental.buttons.ImageToggle)
self.assertEqual(self.shuffle.icon_size, Gtk.IconSize.NORMAL)
self.assertEqual(self.shuffle.active_icon_name, self.assertEqual(self.shuffle.active_icon_name,
"media-playlist-shuffle") "media-playlist-shuffle")
self.assertEqual(self.shuffle.inactive_icon_name, self.assertEqual(self.shuffle.inactive_icon_name,
"media-playlist-consecutive") "media-playlist-consecutive")
self.assertAlmostEqual(self.shuffle.icon_opacity, 0.5, delta=0.005) self.assertAlmostEqual(self.shuffle.icon_opacity, 0.5, delta=0.005)
self.assertFalse(self.shuffle.large_icon)
self.assertFalse(self.shuffle.get_has_frame()) self.assertFalse(self.shuffle.get_has_frame())
def test_opacity(self): def test_opacity(self):
@ -262,12 +262,13 @@ class TestSortFieldWidget(unittest.TestCase):
def test_reverse(self): def test_reverse(self):
"""Test reversing a sort field.""" """Test reversing a sort field."""
self.assertIsInstance(self.sort._reverse, emmental.buttons.ImageToggle) self.assertIsInstance(self.sort._reverse, emmental.buttons.ImageToggle)
self.assertEqual(self.sort._reverse.active_icon_name, "arrow1-up")
self.assertEqual(self.sort._reverse.inactive_icon_name, "arrow1-down")
self.assertEqual(self.sort._reverse.icon_size, Gtk.IconSize.NORMAL)
self.assertEqual(self.sort._name.get_next_sibling(), self.assertEqual(self.sort._name.get_next_sibling(),
self.sort._reverse) self.sort._reverse)
self.assertEqual(self.sort._reverse.active_icon_name, "arrow1-up")
self.assertEqual(self.sort._reverse.inactive_icon_name, "arrow1-down")
self.assertFalse(self.sort._reverse.large_icon)
self.sort._reverse.emit("clicked") self.sort._reverse.emit("clicked")
self.sort.set_sort_field(self.model[0]) self.sort.set_sort_field(self.model[0])

View File

@ -232,9 +232,9 @@ class TestTrackRowWidgets(tests.util.TestCase):
self.assertEqual(row.property, "favorite") self.assertEqual(row.property, "favorite")
self.assertEqual(row.child.active_icon_name, "heart-filled") self.assertEqual(row.child.active_icon_name, "heart-filled")
self.assertEqual(row.child.inactive_icon_name, "heart-outline-thick") self.assertEqual(row.child.inactive_icon_name, "heart-outline-thick")
self.assertEqual(row.child.icon_size, Gtk.IconSize.NORMAL)
self.assertEqual(row.child.get_valign(), Gtk.Align.CENTER) self.assertEqual(row.child.get_valign(), Gtk.Align.CENTER)
self.assertFalse(row.child.get_has_frame()) self.assertFalse(row.child.get_has_frame())
self.assertFalse(row.child.large_icon)
self.track.favorite = True self.track.favorite = True
row.bind() row.bind()