sidebar: Remove old Sidebar code
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
35e31d0553
commit
281fda1933
|
@ -1,13 +1,6 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
from . import library
|
||||
from . import pulser
|
||||
from . import stack
|
||||
from . import tagbox
|
||||
from . import user
|
||||
from lib import settings
|
||||
from gi.repository import Gtk
|
||||
import audio
|
||||
import tagdb
|
||||
from . import stack
|
||||
|
||||
class Sidebar(Gtk.Box):
|
||||
def __init__(self):
|
||||
|
@ -15,60 +8,3 @@ class Sidebar(Gtk.Box):
|
|||
switcher = stack.Switcher()
|
||||
self.append(switcher)
|
||||
self.append(stack.Box(switcher.get_stack()))
|
||||
|
||||
Switcher = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
|
||||
Stack = Gtk.Stack()
|
||||
Box = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
|
||||
|
||||
|
||||
#
|
||||
# Add pages to the Stack and set up the switcher toggles
|
||||
#
|
||||
Toggles = [ ]
|
||||
Switcher.add_css_class("osd")
|
||||
Switcher.add_css_class("linked")
|
||||
Switcher.add_css_class("large-icons")
|
||||
Stack.set_transition_type(Gtk.StackTransitionType.OVER_UP_DOWN)
|
||||
|
||||
def initialize():
|
||||
settings.initialize("sidebar.page", "Libraries")
|
||||
initialize()
|
||||
|
||||
def switch_page(toggle):
|
||||
if toggle.get_active():
|
||||
Stack.set_visible_child_name(toggle.get_name())
|
||||
settings.set("sidebar.page", toggle.get_name())
|
||||
|
||||
def on_tag_push_pop(old, new):
|
||||
old.widgets.set_label()
|
||||
new.widgets.set_label()
|
||||
tagdb.Stack.PushPop.register(on_tag_push_pop)
|
||||
|
||||
def add_stack_page(name, page):
|
||||
toggle = Gtk.ToggleButton()
|
||||
toggle.set_icon_name(page.icon)
|
||||
toggle.set_vexpand(True)
|
||||
toggle.set_name(name)
|
||||
toggle.connect("toggled", switch_page)
|
||||
if len(Toggles) > 0:
|
||||
toggle.set_group(Toggles[0])
|
||||
|
||||
Toggles.append(toggle)
|
||||
Switcher.append(toggle)
|
||||
Stack.add_named(page, name)
|
||||
toggle.set_active(settings.get("sidebar.page") == name)
|
||||
|
||||
add_stack_page("Playlists", user.TagBox)
|
||||
add_stack_page("Artists", tagbox.ParentTagBox(tagdb.tags.Artist, "avatar-default-symbolic",
|
||||
tagdb.tags.Album, "media-optical", header=True))
|
||||
add_stack_page("Genres", tagbox.TagBox(tagdb.tags.Genre, "emblem-generic", header=True))
|
||||
add_stack_page("Decades", tagbox.ParentTagBox(tagdb.tags.Decade, "x-office-calendar",
|
||||
tagdb.tags.Year, "x-office-calendar-symbolic"))
|
||||
add_stack_page("Libraries", library.Box)
|
||||
|
||||
|
||||
Box.append(audio.Artwork())
|
||||
Box.append(Gtk.Separator.new(Gtk.Orientation.HORIZONTAL))
|
||||
Box.append(Stack)
|
||||
Box.append(Gtk.Separator.new(Gtk.Orientation.HORIZONTAL))
|
||||
Box.append(pulser.Box)
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
from . import tagbox
|
||||
from . import tagrow
|
||||
from gi.repository import Gtk
|
||||
import pathlib
|
||||
import tagdb
|
||||
|
||||
|
||||
class LibraryTagRow(tagrow.TagRow):
|
||||
def __init__(self, tag, icon):
|
||||
super().__init__(tag, icon)
|
||||
self.update = Gtk.Button.new_from_icon_name("view-refresh")
|
||||
self.update.set_hexpand(True)
|
||||
self.update.connect("clicked", self.update_clicked)
|
||||
|
||||
self.remove = Gtk.Button.new_from_icon_name("list-remove")
|
||||
self.remove.set_hexpand(True)
|
||||
self.remove.connect("clicked", self.remove_clicked)
|
||||
|
||||
self.box = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0)
|
||||
self.box.add_css_class("linked")
|
||||
self.box.append(self.update)
|
||||
self.box.append(self.remove)
|
||||
|
||||
self.grid.attach(self.box, 0, 1, 2, 1)
|
||||
|
||||
def update_clicked(self, button):
|
||||
self.tag.scan()
|
||||
|
||||
def remove_clicked(self, button):
|
||||
tagdb.Library.remove(self.tag)
|
||||
|
||||
|
||||
class LibraryTagBox(tagbox.TagBox):
|
||||
def __alloc_tagrow__(self, tag):
|
||||
return LibraryTagRow(tag, self.icon)
|
||||
TagBox = LibraryTagBox(tagdb.Library, "folder-music")
|
||||
|
||||
|
||||
#
|
||||
# Configure the directory chooser popover and menu button
|
||||
#
|
||||
DirFilter = Gtk.FileFilter()
|
||||
DirFilter.add_mime_type("inode/directory")
|
||||
|
||||
DirChooser = Gtk.FileChooserWidget()
|
||||
DirChooser.set_action(Gtk.FileChooserAction.SELECT_FOLDER)
|
||||
DirChooser.set_create_folders(False)
|
||||
DirChooser.set_filter(DirFilter)
|
||||
|
||||
def selected_path():
|
||||
if (file := DirChooser.get_file()) == None:
|
||||
file = DirChooser.get_current_folder()
|
||||
return pathlib.Path(file.get_path())
|
||||
|
||||
def on_select(button):
|
||||
if (path := selected_path()) != None:
|
||||
tagdb.Library.add(path).scan()
|
||||
Popover.popdown()
|
||||
|
||||
DirSelect = Gtk.Button.new_with_label("Select Folder")
|
||||
DirSelect.add_css_class("suggested-action")
|
||||
DirSelect.connect("clicked", on_select)
|
||||
|
||||
DirBox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
|
||||
DirBox.append(DirChooser)
|
||||
DirBox.append(DirSelect)
|
||||
|
||||
Popover = Gtk.Popover()
|
||||
Popover.add_css_class("normal-icons")
|
||||
Popover.set_child(DirBox)
|
||||
|
||||
Add = Gtk.MenuButton()
|
||||
Add.add_css_class("large-icons")
|
||||
Add.set_icon_name("folder-new")
|
||||
Add.set_direction(Gtk.ArrowType.UP)
|
||||
Add.set_popover(Popover)
|
||||
|
||||
Box = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
|
||||
Box.add_css_class("linked")
|
||||
Box.set_hexpand(True)
|
||||
Box.append(TagBox)
|
||||
Box.append(Add)
|
||||
Box.icon = TagBox.icon
|
|
@ -1,53 +0,0 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
from gi.repository import Gtk, GLib
|
||||
import lib
|
||||
import threading
|
||||
|
||||
Bar = Gtk.ProgressBar()
|
||||
Threads = [ ]
|
||||
Lock = threading.Lock()
|
||||
Timeout = None
|
||||
|
||||
Bar.hide()
|
||||
Bar.set_valign(Gtk.Align.CENTER)
|
||||
Bar.set_hexpand(True)
|
||||
|
||||
Box = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0)
|
||||
Box.append(Gtk.Label.new(str=" "))
|
||||
Box.append(Bar)
|
||||
Box.append(Gtk.Label.new(str=" "))
|
||||
|
||||
def do_pulses():
|
||||
global Timeout
|
||||
Bar.pulse()
|
||||
with Lock:
|
||||
if not Threads[0].running():
|
||||
Threads.pop(0)
|
||||
|
||||
if len(Threads) == 0:
|
||||
Timeout = None
|
||||
Bar.hide()
|
||||
return GLib.SOURCE_REMOVE
|
||||
return GLib.SOURCE_CONTINUE
|
||||
|
||||
def start_pulsing(thread):
|
||||
global Timeout
|
||||
with Lock:
|
||||
Threads.append(thread)
|
||||
if Timeout == None:
|
||||
Timeout = GLib.timeout_add(100, do_pulses)
|
||||
Bar.show()
|
||||
|
||||
def initialize():
|
||||
lib.thread.Start.register(start_pulsing)
|
||||
lib.bus.Start.register(start_pulsing)
|
||||
initialize()
|
||||
|
||||
def reset():
|
||||
global Timeout
|
||||
with Lock:
|
||||
Threads.clear()
|
||||
if Timeout != None:
|
||||
GLib.source_remove(Timeout)
|
||||
Timeout = None
|
||||
Bar.hide()
|
|
@ -1,126 +0,0 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
from . import tagrow
|
||||
from gi.repository import Gtk
|
||||
import lib
|
||||
import playlist
|
||||
import tagdb
|
||||
|
||||
class TagBox(Gtk.ScrolledWindow):
|
||||
def __init__(self, tagstore, icon, header=False):
|
||||
Gtk.ScrolledWindow.__init__(self)
|
||||
self.listbox = Gtk.ListBox()
|
||||
self.tagstore = tagstore
|
||||
self.icon = icon
|
||||
self.bus = lib.bus.Bus(50)
|
||||
|
||||
self.set_child(self.listbox)
|
||||
self.set_vexpand(True)
|
||||
|
||||
for tag in self.tagstore.tags():
|
||||
self.on_tag_added(tag)
|
||||
|
||||
self.listbox.set_activate_on_single_click(False)
|
||||
self.listbox.set_sort_func(self.sort_func)
|
||||
if header == True:
|
||||
self.listbox.set_header_func(self.header_func)
|
||||
self.listbox.connect("row-activated", self.row_activated)
|
||||
self.listbox.connect("row-selected", self.row_selected)
|
||||
|
||||
tagstore.Added.register(self.tag_added)
|
||||
tagstore.Removed.register(self.tag_removed)
|
||||
|
||||
def __alloc_tagrow__(self, tag):
|
||||
return tagrow.TagRow(tag, self.icon)
|
||||
|
||||
def __getitem__(self, i):
|
||||
return self.listbox.get_row_at_index(i)
|
||||
|
||||
def clear(self):
|
||||
while (row := self[0]) != None:
|
||||
self.on_tag_removed(row.tag)
|
||||
self.bus.clear()
|
||||
|
||||
def header_func(self, cur, prev):
|
||||
c = cur.tag.get_header()
|
||||
if prev == None or prev.tag.get_header() != c:
|
||||
cur.set_header(tagrow.TagHeader(c))
|
||||
else:
|
||||
cur.set_header(None)
|
||||
|
||||
def row_activated(self, listbox, row):
|
||||
tagdb.Stack.push(row.tag)
|
||||
|
||||
def row_selected(self, listbox, row):
|
||||
playlist.Model.switch_tag(row.tag)
|
||||
|
||||
def sort_func(self, lhs, rhs):
|
||||
if lhs.tag < rhs.tag:
|
||||
return -1
|
||||
if rhs.tag < lhs.tag:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def on_tag_added(self, tag):
|
||||
tag.widgets = self.__alloc_tagrow__(tag)
|
||||
tag.TrackAdded.register(self.tag_changed)
|
||||
tag.TrackRemoved.register(self.tag_changed)
|
||||
self.listbox.append(tag.widgets)
|
||||
|
||||
def tag_added(self, tag):
|
||||
self.bus.board(self.on_tag_added, tag)
|
||||
|
||||
def on_tag_changed(self, tag):
|
||||
tag.widgets.set_label()
|
||||
|
||||
def tag_changed(self, tag, track, pos):
|
||||
self.bus.board(self.on_tag_changed, tag)
|
||||
|
||||
def on_tag_removed(self, tag):
|
||||
self.listbox.remove(tag.widgets)
|
||||
tag.TrackAdded.unregister(self.tag_changed)
|
||||
tag.TrackRemoved.unregister(self.tag_changed)
|
||||
tag.widgets = None
|
||||
|
||||
def tag_removed(self, tag):
|
||||
self.bus.board(self.on_tag_removed, tag)
|
||||
|
||||
|
||||
class ParentTagBox(TagBox):
|
||||
def __init__(self, tagstore, icon, childstore, childicon, header=False):
|
||||
TagBox.__init__(self, tagstore, icon, header)
|
||||
self.childstore = childstore
|
||||
self.childicon = childicon
|
||||
|
||||
for child in childstore.tags():
|
||||
self.on_child_tag_added(child)
|
||||
childstore.Added.register(self.child_tag_added)
|
||||
childstore.Removed.register(self.child_tag_removed)
|
||||
|
||||
def __alloc_tagrow__(self, tag):
|
||||
return tagrow.ParentTagRow(tag, self.icon)
|
||||
|
||||
def on_child_tag_added(self, tag):
|
||||
tag.widgets = tagrow.TagRow(tag, self.childicon)
|
||||
tag.widgets.set_margin_start(35)
|
||||
tag.parent.widgets.add_child(tag.widgets)
|
||||
tag.TrackAdded.register(self.tag_changed)
|
||||
tag.TrackRemoved.register(self.tag_changed)
|
||||
self.listbox.append(tag.widgets)
|
||||
|
||||
def child_tag_added(self, tag):
|
||||
self.bus.board(self.on_child_tag_added, tag)
|
||||
|
||||
def on_child_tag_removed(self, tag):
|
||||
self.listbox.remove(tag.widgets)
|
||||
tag.TrackAdded.unregister(self.tag_changed)
|
||||
tag.TrackRemoved.unregister(self.tag_changed)
|
||||
tag.widgets = None
|
||||
|
||||
def child_tag_removed(self, tag):
|
||||
self.bus.board(self.on_child_tag_removed, tag)
|
||||
|
||||
def header_func(self, cur, prev):
|
||||
if isinstance(cur, tagrow.ParentTagRow):
|
||||
if prev and not isinstance(prev, tagrow.ParentTagRow):
|
||||
prev = prev.tag.parent.widgets
|
||||
super().header_func(cur, prev)
|
|
@ -1,67 +0,0 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
from gi.repository import Gtk, GLib, Pango
|
||||
import tagdb
|
||||
|
||||
class TagRow(Gtk.ListBoxRow):
|
||||
def __init__(self, tag, icon):
|
||||
Gtk.ListBoxRow.__init__(self)
|
||||
self.tag = tag
|
||||
self.grid = Gtk.Grid()
|
||||
self.image = Gtk.Image.new_from_icon_name(icon)
|
||||
self.image.set_margin_start(5)
|
||||
self.image.set_margin_end(5)
|
||||
|
||||
self.label = Gtk.Label()
|
||||
self.label.set_halign(Gtk.Align.START)
|
||||
self.label.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
|
||||
self.label.set_hexpand(True)
|
||||
|
||||
self.grid.attach(self.image, 0, 0, 1, 1)
|
||||
self.grid.attach(self.label, 1, 0, 1, 1)
|
||||
self.grid.set_margin_end(5)
|
||||
self.set_child(self.grid)
|
||||
self.set_label()
|
||||
|
||||
def set_label(self):
|
||||
count = len(self.tag)
|
||||
bold = tagdb.Stack.current() == self.tag
|
||||
text = f"{self.tag.name}\n{count} Track{'s' if count != 1 else ''}"
|
||||
self.label.set_markup(("<b>%s</b>" if bold else "%s") %
|
||||
GLib.markup_escape_text(text))
|
||||
|
||||
|
||||
class ParentTagRow(TagRow):
|
||||
def __init__(self, tag, icon):
|
||||
TagRow.__init__(self, tag, icon)
|
||||
self.children = [ ]
|
||||
self.expander = Gtk.ToggleButton()
|
||||
self.expander.connect("toggled", self.on_toggle)
|
||||
self.expander.set_icon_name("pan-end-symbolic")
|
||||
self.expander.add_css_class("flat")
|
||||
|
||||
self.grid.insert_column(0)
|
||||
self.grid.attach(self.expander, 0, 0, 1, 1)
|
||||
|
||||
def add_child(self, child):
|
||||
self.children.append(child)
|
||||
child.set_visible(self.expander.get_active())
|
||||
|
||||
def on_toggle(self, button):
|
||||
direction = "down" if self.expander.get_active() else "end"
|
||||
self.expander.set_icon_name(f"pan-{direction}-symbolic")
|
||||
for child in self.children:
|
||||
child.set_visible(self.expander.get_active())
|
||||
|
||||
|
||||
class TagHeader(Gtk.Box):
|
||||
def __init__(self, char):
|
||||
Gtk.Box.__init__(self)
|
||||
self.set_orientation(Gtk.Orientation.VERTICAL)
|
||||
self.set_margin_top(5)
|
||||
|
||||
self.label = Gtk.Label()
|
||||
self.label.set_markup(f"<small><b>{char}</b></small>")
|
||||
self.separator = Gtk.Separator.new(Gtk.Orientation.HORIZONTAL)
|
||||
|
||||
self.append(self.label)
|
||||
self.append(self.separator)
|
|
@ -1,99 +0,0 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
from . import library
|
||||
from . import tagbox
|
||||
from gi.repository import Gtk, Gio, GLib
|
||||
import pathlib
|
||||
import tagdb
|
||||
import unittest
|
||||
|
||||
main_context = GLib.main_context_default()
|
||||
test_library = pathlib.Path("./data/Test Library").absolute()
|
||||
test_artist1 = test_library / "Test Artist 01"
|
||||
|
||||
class TestLibrarySidebar(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
tagdb.reset()
|
||||
library.TagBox.clear()
|
||||
|
||||
def test_library_sidebar_init(self):
|
||||
self.assertIsInstance(library.TagBox, library.LibraryTagBox)
|
||||
self.assertIsInstance(library.TagBox, tagbox.TagBox)
|
||||
self.assertIsInstance(library.Add, Gtk.MenuButton)
|
||||
self.assertIsInstance(library.Box, Gtk.Box)
|
||||
|
||||
self.assertTrue(library.Box.has_css_class("linked"))
|
||||
self.assertTrue(library.Box.get_hexpand())
|
||||
|
||||
self.assertIn(library.TagBox, library.Box)
|
||||
self.assertIn(library.Add, library.Box)
|
||||
|
||||
def test_library_sidebar_row(self):
|
||||
library.TagBox = library.LibraryTagBox(tagdb.Library, "folder-music")
|
||||
lib_tag = tagdb.Library.add(test_artist1)
|
||||
lib_tag.scan().join()
|
||||
library.TagBox.bus.complete()
|
||||
|
||||
row = lib_tag.widgets
|
||||
self.assertIsInstance(row, library.LibraryTagRow)
|
||||
self.assertIsInstance(row.update, Gtk.Button)
|
||||
self.assertIsInstance(row.remove, Gtk.Button)
|
||||
self.assertIsInstance(row.box, Gtk.Box)
|
||||
|
||||
self.assertTrue(row.update.get_hexpand())
|
||||
self.assertTrue(row.remove.get_hexpand())
|
||||
self.assertTrue(row.box.has_css_class("linked"))
|
||||
|
||||
self.assertIn(row.box, row.grid)
|
||||
self.assertIn(row.update, row.box)
|
||||
self.assertIn(row.remove, row.box)
|
||||
|
||||
row.update_clicked(row.update)
|
||||
lib_tag.scan.join()
|
||||
|
||||
row.remove_clicked(row.remove)
|
||||
lib_tag.clear.join()
|
||||
library.TagBox.bus.complete()
|
||||
self.assertIsNone(library.TagBox[0])
|
||||
|
||||
def test_library_sidebar_add(self):
|
||||
self.assertIsInstance(library.Popover, Gtk.Popover)
|
||||
self.assertTrue(library.Popover.has_css_class("normal-icons"))
|
||||
|
||||
self.assertEqual(library.Add.get_icon_name(), "folder-new")
|
||||
self.assertEqual(library.Add.get_direction(), Gtk.ArrowType.UP)
|
||||
self.assertTrue(library.Add.has_css_class("large-icons"))
|
||||
|
||||
self.assertEqual(library.Add.get_popover(), library.Popover)
|
||||
self.assertEqual(library.Popover.get_child(), library.DirBox)
|
||||
|
||||
def test_library_sidebar_dir_chooser(self):
|
||||
self.assertIsInstance(library.DirFilter, Gtk.FileFilter)
|
||||
self.assertIsInstance(library.DirChooser, Gtk.FileChooserWidget)
|
||||
self.assertIsInstance(library.DirSelect, Gtk.Button)
|
||||
self.assertIsInstance(library.DirBox, Gtk.Box)
|
||||
|
||||
self.assertEqual(library.DirChooser.get_filter(), library.DirFilter)
|
||||
self.assertEqual(library.DirChooser.get_action(),
|
||||
Gtk.FileChooserAction.SELECT_FOLDER)
|
||||
self.assertFalse(library.DirChooser.get_create_folders())
|
||||
self.assertIn(library.DirChooser, library.DirBox)
|
||||
|
||||
self.assertEqual(library.DirSelect.get_label(), "Select Folder")
|
||||
self.assertTrue(library.DirSelect.has_css_class("suggested-action"))
|
||||
self.assertIn(library.DirSelect, library.DirBox)
|
||||
|
||||
#library.Popover.popup()
|
||||
gfile = Gio.File.new_for_path(str(test_library))
|
||||
self.assertTrue(library.DirChooser.set_current_folder(gfile))
|
||||
while main_context.iteration(may_block=False): pass
|
||||
self.assertEqual(library.selected_path(), test_library)
|
||||
|
||||
gfile = Gio.File.new_for_path(str(test_artist1))
|
||||
self.assertTrue(library.DirChooser.set_file(gfile))
|
||||
while main_context.iteration(may_block=False): pass
|
||||
self.assertEqual(library.selected_path(), test_artist1)
|
||||
|
||||
library.on_select(library.DirSelect)
|
||||
self.assertFalse(library.Popover.is_visible())
|
||||
self.assertIn(test_artist1, tagdb.Library.store)
|
||||
tagdb.Library[test_artist1].scan.join()
|
|
@ -1,55 +0,0 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
from . import pulser
|
||||
from gi.repository import Gtk, GLib
|
||||
import lib
|
||||
import threading
|
||||
import unittest
|
||||
|
||||
class TestThread:
|
||||
def __init__(self): pass
|
||||
def running(self): return False
|
||||
|
||||
|
||||
class TestUIPulser(unittest.TestCase):
|
||||
def setUp(self):
|
||||
pulser.reset()
|
||||
pulser.initialize()
|
||||
pulser.reset()
|
||||
|
||||
def test_pulser_init(self):
|
||||
self.assertIsInstance(pulser.Bar, Gtk.ProgressBar)
|
||||
self.assertIsInstance(pulser.Box, Gtk.Box)
|
||||
self.assertIsInstance(pulser.Lock, type(threading.Lock()))
|
||||
self.assertIsNone(pulser.Timeout)
|
||||
|
||||
self.assertTrue(pulser.Bar.get_hexpand())
|
||||
self.assertFalse(pulser.Bar.get_visible())
|
||||
self.assertEqual(pulser.Threads, [ ])
|
||||
self.assertEqual(pulser.Bar.get_valign(), Gtk.Align.CENTER)
|
||||
|
||||
self.assertIn(pulser.Bar, pulser.Box)
|
||||
self.assertIn(pulser.start_pulsing, lib.thread.Start.subscribers)
|
||||
self.assertIn(pulser.start_pulsing, lib.bus.Start.subscribers)
|
||||
|
||||
def test_pulser_pulse(self):
|
||||
t1 = TestThread()
|
||||
t2 = TestThread()
|
||||
|
||||
pulser.start_pulsing(t1)
|
||||
self.assertEqual(pulser.Threads, [ t1 ])
|
||||
tid = pulser.Timeout
|
||||
self.assertIsNotNone(tid)
|
||||
self.assertTrue(pulser.Bar.get_visible())
|
||||
|
||||
pulser.start_pulsing(t2)
|
||||
self.assertEqual(pulser.Threads, [ t1, t2 ])
|
||||
self.assertEqual(pulser.Timeout, tid)
|
||||
|
||||
pulser.do_pulses()
|
||||
self.assertEqual(pulser.Threads, [ t2 ])
|
||||
pulser.do_pulses()
|
||||
self.assertEqual(pulser.Threads, [ ])
|
||||
self.assertIsNone(pulser.Timeout)
|
||||
self.assertFalse(pulser.Bar.get_visible())
|
||||
|
||||
GLib.source_remove(tid)
|
|
@ -1,10 +1,7 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
import audio
|
||||
import sidebar
|
||||
import unittest
|
||||
from lib import settings
|
||||
from gi.repository import Gtk
|
||||
from . import stack
|
||||
|
||||
class TestSidebar(unittest.TestCase):
|
||||
def test_init(self):
|
||||
|
@ -12,79 +9,6 @@ class TestSidebar(unittest.TestCase):
|
|||
self.assertIsInstance(sbar, Gtk.Box)
|
||||
|
||||
child = sbar.get_first_child()
|
||||
self.assertIsInstance(child, stack.Switcher)
|
||||
self.assertIsInstance(child, sidebar.stack.Switcher)
|
||||
child = child.get_next_sibling()
|
||||
self.assertIsInstance(child, stack.Box)
|
||||
|
||||
|
||||
class TestOldSidebar(unittest.TestCase):
|
||||
def setUpClass():
|
||||
sidebar.initialize()
|
||||
|
||||
def test_sidebar_init(self):
|
||||
self.assertIsInstance(sidebar.Switcher, Gtk.Box)
|
||||
self.assertIsInstance(sidebar.Stack, Gtk.Stack)
|
||||
self.assertIsInstance(sidebar.Box, Gtk.Box)
|
||||
|
||||
#self.assertIn(audio.Player.Artwork, sidebar.Box)
|
||||
self.assertIn(sidebar.Stack, sidebar.Box)
|
||||
self.assertIn(sidebar.pulser.Box, sidebar.Box)
|
||||
|
||||
def test_sidebar_pages(self):
|
||||
self.assertTrue(sidebar.Switcher.has_css_class("osd"))
|
||||
self.assertTrue(sidebar.Switcher.has_css_class("linked"))
|
||||
self.assertTrue(sidebar.Switcher.has_css_class("large-icons"))
|
||||
self.assertEqual(sidebar.Stack.get_transition_type(), Gtk.StackTransitionType.OVER_UP_DOWN)
|
||||
self.assertEqual(settings.get("sidebar.page"), "Libraries")
|
||||
self.assertEqual(sidebar.Stack.get_visible_child_name(), "Libraries")
|
||||
|
||||
for toggle in sidebar.Toggles:
|
||||
self.assertIsInstance(toggle, Gtk.ToggleButton)
|
||||
self.assertIn(toggle, sidebar.Switcher)
|
||||
self.assertTrue(toggle.get_vexpand())
|
||||
|
||||
self.assertIsInstance(sidebar.Stack.get_child_by_name("Playlists"),
|
||||
sidebar.user.UserTagBox)
|
||||
self.assertEqual(sidebar.Toggles[0].get_icon_name(), "audio-x-generic")
|
||||
self.assertEqual(sidebar.Toggles[0].get_name(), "Playlists")
|
||||
sidebar.Toggles[0].set_active(True)
|
||||
self.assertEqual(sidebar.Stack.get_visible_child_name(), "Playlists")
|
||||
self.assertEqual(settings.get("sidebar.page"), "Playlists")
|
||||
|
||||
self.assertIsInstance(sidebar.Stack.get_child_by_name("Artists"),
|
||||
sidebar.tagbox.ParentTagBox)
|
||||
self.assertEqual(sidebar.Toggles[1].get_icon_name(), "avatar-default-symbolic")
|
||||
self.assertEqual(sidebar.Toggles[1].get_name(), "Artists")
|
||||
sidebar.Toggles[1].set_active(True)
|
||||
self.assertEqual(sidebar.Stack.get_visible_child_name(), "Artists")
|
||||
self.assertEqual(settings.get("sidebar.page"), "Artists")
|
||||
|
||||
self.assertIsInstance(sidebar.Stack.get_child_by_name("Genres"),
|
||||
sidebar.tagbox.TagBox)
|
||||
self.assertEqual(sidebar.Toggles[2].get_icon_name(), "emblem-generic")
|
||||
self.assertEqual(sidebar.Toggles[2].get_name(), "Genres")
|
||||
sidebar.Toggles[2].set_active(True)
|
||||
self.assertEqual(sidebar.Stack.get_visible_child_name(), "Genres")
|
||||
self.assertEqual(settings.get("sidebar.page"), "Genres")
|
||||
|
||||
self.assertIsInstance(sidebar.Stack.get_child_by_name("Decades"),
|
||||
sidebar.tagbox.ParentTagBox)
|
||||
self.assertEqual(sidebar.Toggles[3].get_icon_name(), "x-office-calendar")
|
||||
self.assertEqual(sidebar.Toggles[3].get_name(), "Decades")
|
||||
sidebar.Toggles[3].set_active(True)
|
||||
self.assertEqual(sidebar.Stack.get_visible_child_name(), "Decades")
|
||||
self.assertEqual(settings.get("sidebar.page"), "Decades")
|
||||
|
||||
self.assertEqual(sidebar.Stack.get_child_by_name("Libraries"),
|
||||
sidebar.library.Box)
|
||||
self.assertEqual(sidebar.Toggles[4].get_icon_name(), "folder-music")
|
||||
self.assertEqual(sidebar.Toggles[4].get_name(), "Libraries")
|
||||
sidebar.Toggles[4].set_active(True)
|
||||
self.assertEqual(sidebar.Stack.get_visible_child_name(), "Libraries")
|
||||
self.assertEqual(settings.get("sidebar.page"), "Libraries")
|
||||
|
||||
for toggle in sidebar.Toggles:
|
||||
if toggle != sidebar.Toggles[-1]:
|
||||
self.assertFalse(toggle.get_active())
|
||||
else:
|
||||
self.assertTrue(toggle.get_active())
|
||||
self.assertIsInstance(child, sidebar.stack.Box)
|
||||
|
|
|
@ -1,169 +0,0 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
from . import tagbox
|
||||
from . import tagrow
|
||||
from lib import fake
|
||||
from gi.repository import Gtk
|
||||
import lib
|
||||
import unittest
|
||||
|
||||
class TestTagBox(unittest.TestCase):
|
||||
def test_tag_box(self):
|
||||
store = lib.tagstore.TagStore()
|
||||
tbox = tagbox.TagBox(store, "image-missing")
|
||||
self.assertEqual(tbox.tagstore, store)
|
||||
self.assertEqual(tbox.icon, "image-missing")
|
||||
self.assertEqual(tbox.bus.timeout, 50)
|
||||
|
||||
self.assertIsInstance(tbox, Gtk.ScrolledWindow)
|
||||
self.assertIsInstance(tbox.listbox, Gtk.ListBox)
|
||||
self.assertIsInstance(tbox.bus, lib.bus.Bus)
|
||||
|
||||
viewport = tbox.get_child()
|
||||
self.assertIsInstance(viewport, Gtk.Viewport)
|
||||
self.assertEqual(viewport.get_child(), tbox.listbox)
|
||||
|
||||
self.assertTrue(tbox.get_vexpand())
|
||||
self.assertFalse(tbox.listbox.get_activate_on_single_click())
|
||||
|
||||
self.assertIn(tbox.tag_added, store.Added.subscribers)
|
||||
self.assertIn(tbox.tag_removed, store.Removed.subscribers)
|
||||
|
||||
def test_tag_box_add_remove_modify(self):
|
||||
store = lib.tagstore.TagStore()
|
||||
tbox = tagbox.TagBox(store, "missing-icon")
|
||||
|
||||
tag = store.add("Test", fake.Track(1))
|
||||
self.assertIn((tbox.on_tag_added, (tag,)), tbox.bus.passengers)
|
||||
tbox.bus.complete()
|
||||
self.assertIsInstance(tag.widgets, tagrow.TagRow)
|
||||
self.assertEqual(tbox[0], tag.widgets)
|
||||
|
||||
self.assertIn(tbox.tag_changed, tag.TrackAdded.subscribers)
|
||||
self.assertEqual(tag.widgets.label.get_text(), "Test\n1 Track")
|
||||
tag.add_track(fake.Track(2))
|
||||
self.assertIn((tbox.on_tag_changed, (tag,)), tbox.bus.passengers)
|
||||
tbox.bus.complete()
|
||||
self.assertEqual(tag.widgets.label.get_text(), "Test\n2 Tracks")
|
||||
|
||||
self.assertIn(tbox.tag_changed, tag.TrackRemoved.subscribers)
|
||||
tag.remove_track(fake.Track(2))
|
||||
self.assertIn((tbox.on_tag_changed, (tag,)), tbox.bus.passengers)
|
||||
tbox.bus.complete()
|
||||
self.assertEqual(tag.widgets.label.get_text(), "Test\n1 Track")
|
||||
|
||||
store.remove(tag)
|
||||
self.assertIn((tbox.on_tag_removed, (tag,)), tbox.bus.passengers)
|
||||
tbox.bus.complete()
|
||||
self.assertIsNone(tag.widgets)
|
||||
self.assertIsNone(tbox[0])
|
||||
|
||||
self.assertNotIn(tbox.tag_changed, tag.TrackAdded.subscribers)
|
||||
self.assertNotIn(tbox.tag_changed, tag.TrackRemoved.subscribers)
|
||||
|
||||
def test_tag_box_clear(self):
|
||||
store = lib.tagstore.TagStore()
|
||||
tbox = tagbox.TagBox(store, "missing-icon")
|
||||
tag1 = store.add("Test1", fake.Track(1))
|
||||
tag2 = store.add("Test2", fake.Track(1))
|
||||
|
||||
tbox.bus.complete()
|
||||
self.assertEqual(tbox[0].tag, tag1)
|
||||
self.assertEqual(tbox[1].tag, tag2)
|
||||
|
||||
tbox.clear()
|
||||
self.assertIsNone(tbox[0])
|
||||
self.assertNotIn(tbox.tag_changed, tag1.TrackAdded.subscribers)
|
||||
self.assertNotIn(tbox.tag_changed, tag2.TrackAdded.subscribers)
|
||||
self.assertNotIn(tbox.tag_changed, tag1.TrackRemoved.subscribers)
|
||||
self.assertNotIn(tbox.tag_changed, tag2.TrackRemoved.subscribers)
|
||||
|
||||
def test_tag_box_load(self):
|
||||
store = lib.tagstore.TagStore()
|
||||
tag1 = store.add("Test1", fake.Track(1))
|
||||
tag2 = store.add("Test2", fake.Track(2))
|
||||
tbox = tagbox.TagBox(store, "missing-icon")
|
||||
|
||||
self.assertEqual(tbox[0], tag1.widgets)
|
||||
self.assertEqual(tbox[1], tag2.widgets)
|
||||
|
||||
def test_tag_box_header(self):
|
||||
store = lib.tagstore.TagStore()
|
||||
tbox = tagbox.TagBox(store, "missing-icon", header=True)
|
||||
|
||||
tagAB = store.add("AB")
|
||||
tbox.bus.complete()
|
||||
self.assertIsNotNone(tagAB.widgets.get_header())
|
||||
|
||||
tagAA = store.add("AA")
|
||||
tbox.bus.complete()
|
||||
self.assertIsNotNone(tagAA.widgets.get_header())
|
||||
self.assertIsNone(tagAB.widgets.get_header())
|
||||
|
||||
def test_tag_box_sort(self):
|
||||
store = lib.tagstore.TagStore()
|
||||
tbox = tagbox.TagBox(store, "missing-icon")
|
||||
tagB = store.add("B", fake.Track(1))
|
||||
tagA = store.add("A", fake.Track(1))
|
||||
tagC = store.add("C", fake.Track(1))
|
||||
|
||||
tbox.bus.complete()
|
||||
self.assertEqual(tbox[0].tag, tagA)
|
||||
self.assertEqual(tbox[1].tag, tagB)
|
||||
self.assertEqual(tbox[2].tag, tagC)
|
||||
|
||||
|
||||
class TestParentTagBox(unittest.TestCase):
|
||||
def test_parent_tagbox(self):
|
||||
store = lib.tagstore.TagStore()
|
||||
superstore = lib.tagstore.TagSuperStore()
|
||||
ptbox = tagbox.ParentTagBox(store, "missing-icon",
|
||||
superstore, "missing-icon")
|
||||
|
||||
self.assertIsInstance(ptbox, tagbox.ParentTagBox)
|
||||
self.assertIsInstance(ptbox, tagbox.TagBox)
|
||||
|
||||
self.assertEqual(ptbox.tagstore, store)
|
||||
self.assertEqual(ptbox.icon, "missing-icon")
|
||||
self.assertEqual(ptbox.childstore, superstore)
|
||||
self.assertEqual(ptbox.childicon, "missing-icon")
|
||||
|
||||
def test_parent_tagbox_add_remove(self):
|
||||
store = lib.tagstore.TagStore()
|
||||
superstore = lib.tagstore.TagSuperStore()
|
||||
ptbox = tagbox.ParentTagBox(store, "missing-icon",
|
||||
superstore, "missing-icon")
|
||||
|
||||
tag = store.add("Test", fake.Track(1))
|
||||
ptbox.bus.complete()
|
||||
self.assertIsInstance(tag.widgets, tagrow.ParentTagRow)
|
||||
|
||||
tag1 = superstore.add(tag, "child", fake.Track(1))
|
||||
ptbox.bus.complete()
|
||||
self.assertIsInstance(tag1.widgets, tagrow.TagRow)
|
||||
self.assertEqual(tag1.widgets.get_margin_start(), 35)
|
||||
|
||||
superstore.remove(tag1)
|
||||
ptbox.bus.complete()
|
||||
self.assertIsNone(tag1.widgets)
|
||||
|
||||
store.remove(tag)
|
||||
ptbox.bus.complete()
|
||||
self.assertIsNone(tag.widgets)
|
||||
|
||||
def test_parent_tagbox_load(self):
|
||||
store = lib.tagstore.TagStore()
|
||||
superstore = lib.tagstore.TagSuperStore()
|
||||
|
||||
tag = store.add("Test", fake.Track(1))
|
||||
tag1 = superstore.add(tag, "Tag 1", fake.Track(1))
|
||||
tag2 = superstore.add(tag, "Tag 2", fake.Track(2))
|
||||
|
||||
ptbox = tagbox.ParentTagBox(store, "missing-icon",
|
||||
superstore, "missing-icon")
|
||||
|
||||
self.assertEqual(ptbox[0], tag.widgets)
|
||||
self.assertEqual(ptbox[1], tag1.widgets)
|
||||
self.assertEqual(ptbox[2], tag2.widgets)
|
||||
|
||||
self.assertIsNone(tag1.widgets.get_header())
|
||||
self.assertIsNone(tag2.widgets.get_header())
|
|
@ -1,99 +0,0 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
from . import tagrow
|
||||
from gi.repository import Gtk, Pango
|
||||
import unittest
|
||||
|
||||
class FakeTag:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.num = 0
|
||||
|
||||
def __len__(self):
|
||||
return self.num
|
||||
|
||||
def __lt__(self, rhs):
|
||||
return self.name < rhs.name
|
||||
|
||||
class TestTagRow(unittest.TestCase):
|
||||
def test_tag_row_init(self):
|
||||
tag = FakeTag("test")
|
||||
row = tagrow.TagRow(tag, "missing-icon")
|
||||
self.assertIsInstance(row, Gtk.ListBoxRow)
|
||||
|
||||
self.assertIsInstance(row.grid, Gtk.Grid)
|
||||
self.assertIsInstance(row.label, Gtk.Label)
|
||||
|
||||
self.assertEqual(row.image.get_icon_name(), "missing-icon")
|
||||
self.assertEqual(row.image.get_margin_start(), 5)
|
||||
self.assertEqual(row.image.get_margin_end(), 5)
|
||||
self.assertEqual(row.grid.get_margin_end(), 5)
|
||||
|
||||
self.assertEqual(row.label.get_text(), "test\n0 Tracks")
|
||||
self.assertEqual(row.label.get_halign(), Gtk.Align.START)
|
||||
self.assertEqual(row.label.get_ellipsize(), Pango.EllipsizeMode.MIDDLE)
|
||||
self.assertTrue(row.label.get_hexpand())
|
||||
|
||||
self.assertIn(row.image, row.grid)
|
||||
self.assertIn(row.label, row.grid)
|
||||
self.assertEqual(row.get_child(), row.grid)
|
||||
|
||||
def test_tag_row_count(self):
|
||||
tag = FakeTag("test")
|
||||
row = tagrow.TagRow(tag, "missing-icon")
|
||||
tag.num = 1
|
||||
row.set_label()
|
||||
self.assertEqual(row.label.get_text(), "test\n1 Track")
|
||||
tag.num = 4
|
||||
row.set_label()
|
||||
self.assertEqual(row.label.get_text(), "test\n4 Tracks")
|
||||
|
||||
|
||||
class TestParentTagRow(unittest.TestCase):
|
||||
def test_parent_tagrow_init(self):
|
||||
tag = FakeTag("test")
|
||||
row = tagrow.ParentTagRow(tag, "missing-icon")
|
||||
|
||||
self.assertIsInstance(row, tagrow.TagRow)
|
||||
self.assertIsInstance(row.expander, Gtk.ToggleButton)
|
||||
|
||||
self.assertEqual(row.expander.get_icon_name(), "pan-end-symbolic")
|
||||
self.assertEqual(row.children, [ ])
|
||||
|
||||
self.assertTrue(row.expander.has_css_class("flat"))
|
||||
self.assertIn(row.expander, row.grid)
|
||||
|
||||
def test_parent_tagrow_children(self):
|
||||
tag = FakeTag("test")
|
||||
row = tagrow.ParentTagRow(tag, "missing-icon")
|
||||
|
||||
c1 = Gtk.Label.new(str="Child 1")
|
||||
row.add_child(c1)
|
||||
self.assertEqual(row.children, [ c1 ])
|
||||
self.assertFalse(c1.is_visible())
|
||||
|
||||
row.expander.set_active(True)
|
||||
self.assertEqual(row.expander.get_icon_name(), "pan-down-symbolic")
|
||||
self.assertTrue(c1.is_visible())
|
||||
|
||||
c2 = Gtk.Label.new(str="Child 2")
|
||||
row.add_child(c2)
|
||||
self.assertEqual(row.children, [ c1, c2 ])
|
||||
|
||||
row.expander.set_active(False)
|
||||
self.assertEqual(row.expander.get_icon_name(), "pan-end-symbolic")
|
||||
self.assertFalse(c1.is_visible())
|
||||
self.assertFalse(c2.is_visible())
|
||||
|
||||
|
||||
class TestTagHeader(unittest.TestCase):
|
||||
def test_tag_header(self):
|
||||
header = tagrow.TagHeader("A")
|
||||
self.assertIsInstance(header, Gtk.Box)
|
||||
self.assertIsInstance(header.label, Gtk.Label)
|
||||
self.assertIsInstance(header.separator, Gtk.Separator)
|
||||
|
||||
self.assertEqual(header.label.get_text(), "A")
|
||||
self.assertEqual(header.get_margin_top(), 5)
|
||||
|
||||
self.assertIn(header.label, header)
|
||||
self.assertIn(header.separator, header)
|
|
@ -1,47 +0,0 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
from . import tagbox
|
||||
from . import tagrow
|
||||
from . import user
|
||||
from gi.repository import Gtk
|
||||
import tagdb
|
||||
import unittest
|
||||
|
||||
Expected = [ ("Collection", "media-playback-start", tagrow.TagRow),
|
||||
("Favorites", "emmental-favorites", tagrow.TagRow),
|
||||
("New Tracks", "starred", tagrow.TagRow),
|
||||
("Previous", "edit-undo", tagrow.TagRow),
|
||||
("Test", "audio-x-generic", user.UserTagRow),
|
||||
("Up Next", "edit-redo", tagrow.TagRow) ]
|
||||
|
||||
class TestUserSidebar(unittest.TestCase):
|
||||
def test_user_sidebar_init(self):
|
||||
self.assertIsInstance(user.TagBox, user.UserTagBox)
|
||||
self.assertIsInstance(user.TagBox, tagbox.TagBox)
|
||||
|
||||
self.assertEqual(user.Icons["Collection"], "media-playback-start")
|
||||
self.assertEqual(user.Icons["Favorites"], "emmental-favorites")
|
||||
self.assertEqual(user.Icons["New Tracks"], "starred")
|
||||
self.assertEqual(user.Icons["Previous"], "edit-undo")
|
||||
self.assertEqual(user.Icons["Up Next"], "edit-redo")
|
||||
|
||||
def test_user_sidebar_row(self):
|
||||
tag = tagdb.tags.User.add("Test")
|
||||
row = user.UserTagRow(tag, "audio-x-generic")
|
||||
|
||||
self.assertIsInstance(row.remove, Gtk.Button)
|
||||
self.assertIsInstance(row.KeyEvent, Gtk.EventControllerKey)
|
||||
self.assertEqual(row.remove.get_icon_name(), "list-remove")
|
||||
self.assertIn(row.remove, row.grid)
|
||||
|
||||
row.remove_tag(row.remove)
|
||||
self.assertIsNone(tagdb.tags.User["Test"])
|
||||
|
||||
def test_user_sidebar(self):
|
||||
user.TagBox = user.UserTagBox(tagdb.tags.User, "audio-x-generic")
|
||||
tag = tagdb.tags.User.add("Test")
|
||||
user.TagBox.bus.complete()
|
||||
|
||||
for (i, (tag, icon, type)) in enumerate(Expected):
|
||||
self.assertIsInstance(user.TagBox[i], type)
|
||||
self.assertEqual(user.TagBox[i].tag, tagdb.tags.User[tag])
|
||||
self.assertEqual(user.TagBox[i].image.get_icon_name(), icon)
|
|
@ -1,40 +0,0 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
from . import tagbox
|
||||
from . import tagrow
|
||||
from gi.repository import Gtk, Gdk
|
||||
import tagdb
|
||||
|
||||
Icons = { "Collection" : "media-playback-start",
|
||||
"Favorites" : "emmental-favorites",
|
||||
"New Tracks" : "starred",
|
||||
"Previous" : "edit-undo",
|
||||
"Up Next" : "edit-redo" }
|
||||
|
||||
|
||||
class UserTagRow(tagrow.TagRow):
|
||||
def __init__(self, tag, icon):
|
||||
tagrow.TagRow.__init__(self, tag, icon)
|
||||
self.remove = Gtk.Button.new_from_icon_name("list-remove")
|
||||
self.remove.connect("clicked", self.remove_tag)
|
||||
self.grid.attach(self.remove, 2, 0, 1, 1)
|
||||
|
||||
self.KeyEvent = Gtk.EventControllerKey()
|
||||
self.KeyEvent.connect("key-released", self.on_key_released)
|
||||
self.add_controller(self.KeyEvent)
|
||||
|
||||
def on_key_released(self, controller, keyval, keycode, state):
|
||||
if Gdk.keyval_name(keyval) == "Delete":
|
||||
tagdb.tags.User.remove(self.tag)
|
||||
|
||||
def remove_tag(self, button):
|
||||
tagdb.tags.User.remove(self.tag)
|
||||
|
||||
|
||||
class UserTagBox(tagbox.TagBox):
|
||||
def __alloc_tagrow__(self, tag):
|
||||
if tag.name not in Icons.keys():
|
||||
return UserTagRow(tag, self.icon)
|
||||
return tagrow.TagRow(tag, Icons.get(tag.name, self.icon))
|
||||
|
||||
|
||||
TagBox = UserTagBox(tagdb.tags.User, "audio-x-generic")
|
Loading…
Reference in New Issue