Source code for sublime_music.ui.configure_provider

import uuid
from enum import Enum
from typing import Any, Optional, Type

from gi.repository import Gio, GObject, Gtk, Pango

from ..adapters import AdapterManager, UIInfo
from ..adapters.filesystem import FilesystemAdapter
from ..config import ConfigurationStore, ProviderConfiguration


[docs]class AdapterTypeModel(GObject.GObject): adapter_type = GObject.Property(type=object)
[docs] def __init__(self, adapter_type: Type): GObject.GObject.__init__(self) self.adapter_type = adapter_type
[docs]class DialogStage(Enum): SELECT_ADAPTER = "select" CONFIGURE_ADAPTER = "configure"
[docs]class ConfigureProviderDialog(Gtk.Dialog): _current_index = -1 stage = DialogStage.SELECT_ADAPTER
[docs] def set_title(self, editing: bool, provider_config: ProviderConfiguration | None = None): if editing: assert provider_config is not None title = f"Edit {provider_config.name}" else: title = "Add New Music Source" self.header.props.title = title
[docs] def __init__(self, parent: Any, provider_config: Optional[ProviderConfiguration]): Gtk.Dialog.__init__(self, transient_for=parent, flags=Gtk.DialogFlags.MODAL) self.provider_config = provider_config self.editing = provider_config is not None self.set_default_size(400, 350) # HEADER self.header = Gtk.HeaderBar() self.set_title(self.editing, provider_config) self.cancel_back_button = Gtk.Button(label="Cancel") self.cancel_back_button.connect("clicked", self._on_cancel_back_clicked) self.header.pack_start(self.cancel_back_button) self.next_add_button = Gtk.Button(label="Edit" if self.editing else "Next") self.next_add_button.get_style_context().add_class("suggested-action") self.next_add_button.connect("clicked", self._on_next_add_clicked) self.header.pack_end(self.next_add_button) self.set_titlebar(self.header) content_area = self.get_content_area() self.stack = Gtk.Stack() self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT) # ADAPTER TYPE OPTIONS adapter_type_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.adapter_type_store = Gio.ListStore() self.adapter_options_list = Gtk.ListBox( name="ground-truth-adapter-options-list", activate_on_single_click=False ) self.adapter_options_list.connect("row-activated", self._on_next_add_clicked) def create_row(model: AdapterTypeModel) -> Gtk.ListBoxRow: ui_info: UIInfo = model.adapter_type.get_ui_info() row = Gtk.ListBoxRow() rowbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) rowbox.pack_start( Gtk.Image.new_from_icon_name(ui_info.icon_name(), Gtk.IconSize.DND), False, False, 5, ) rowbox.add( Gtk.Label( label=f"<b>{ui_info.name}</b>\n{ui_info.description}", use_markup=True, margin=8, halign=Gtk.Align.START, ellipsize=Pango.EllipsizeMode.END, ) ) row.add(rowbox) row.show_all() return row self.adapter_options_list.bind_model(self.adapter_type_store, create_row) available_ground_truth_adapters = filter( lambda a: a.can_be_ground_truth, AdapterManager.available_adapters ) for adapter_type in sorted( available_ground_truth_adapters, key=lambda a: a.get_ui_info().name ): self.adapter_type_store.append(AdapterTypeModel(adapter_type)) adapter_type_box.pack_start(self.adapter_options_list, True, True, 10) self.stack.add_named(adapter_type_box, "select") self.configure_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.stack.add_named(self.configure_box, "configure") content_area.pack_start(self.stack, True, True, 0) self.show_all() if self.editing: assert self.provider_config for i, adapter_type in enumerate(self.adapter_type_store): if adapter_type.adapter_type == self.provider_config.ground_truth_adapter_type: row = self.adapter_options_list.get_row_at_index(i) self.adapter_options_list.select_row(row) break self._name_is_valid = True self._on_next_add_clicked()
def _on_cancel_back_clicked(self, _): if self.stage == DialogStage.SELECT_ADAPTER: self.close() else: self.stack.set_visible_child_name("select") self.stage = DialogStage.SELECT_ADAPTER self.cancel_back_button.set_label("Cancel") self.next_add_button.set_label("Next") self.next_add_button.set_sensitive(True) def _on_next_add_clicked(self, *args): if self.stage == DialogStage.SELECT_ADAPTER: index = self.adapter_options_list.get_selected_row().get_index() if index != self._current_index: for c in self.configure_box.get_children(): self.configure_box.remove(c) name_entry_grid = Gtk.Grid( column_spacing=10, row_spacing=5, margin_left=10, margin_right=10, name="music-source-config-name-entry-grid", ) name_label = Gtk.Label(label="Music Source Name:") name_entry_grid.attach(name_label, 0, 0, 1, 1) self.name_field = Gtk.Entry( text=self.provider_config.name if self.provider_config else "", hexpand=True, ) self.name_field.connect("changed", self._on_name_change) name_entry_grid.attach(self.name_field, 1, 0, 1, 1) self.configure_box.add(name_entry_grid) self.configure_box.add(Gtk.Separator()) self.adapter_type = self.adapter_type_store[index].adapter_type self.config_store = ( self.provider_config.ground_truth_adapter_config if self.provider_config else ConfigurationStore() ) form = self.adapter_type.get_configuration_form(self.config_store) form.connect("config-valid-changed", self._on_config_form_valid_changed) self.configure_box.pack_start(form, True, True, 0) self.configure_box.show_all() self._adapter_config_is_valid = False self.stack.set_visible_child_name("configure") self.stage = DialogStage.CONFIGURE_ADAPTER self.cancel_back_button.set_label("Change Type" if self.editing else "Back") self.next_add_button.set_label("Edit" if self.editing else "Add") self.next_add_button.set_sensitive( index == self._current_index and self._adapter_config_is_valid ) self._current_index = index else: if self.provider_config is None: self.provider_config = ProviderConfiguration( str(uuid.uuid4()), self.name_field.get_text(), self.adapter_type, self.config_store, ) if self.adapter_type.can_be_cached: self.provider_config.caching_adapter_type = FilesystemAdapter self.provider_config.caching_adapter_config = ConfigurationStore() else: self.provider_config.name = self.name_field.get_text() self.provider_config.ground_truth_adapter_config = self.config_store self.response(Gtk.ResponseType.APPLY) _name_is_valid = False _adapter_config_is_valid = False def _update_add_button_sensitive(self): self.next_add_button.set_sensitive(self._name_is_valid and self._adapter_config_is_valid) def _on_name_change(self, entry: Gtk.Entry): if entry.get_text(): self._name_is_valid = True entry.get_style_context().remove_class("invalid") entry.set_tooltip_markup(None) if self.editing: assert self.provider_config self.provider_config.name = entry.get_text() self.set_title(self.editing, self.provider_config) else: self._name_is_valid = False entry.get_style_context().add_class("invalid") entry.set_tooltip_markup("This field is required") self._update_add_button_sensitive() def _on_config_form_valid_changed(self, _, valid: bool): self._adapter_config_is_valid = valid self._update_add_button_sensitive()