Lots of comments

This commit is contained in:
Sumner Evans
2019-06-07 20:47:42 -06:00
parent c80639aac8
commit 7466a6bcde
3 changed files with 48 additions and 25 deletions

View File

@@ -60,17 +60,9 @@ def get_config(filename: str) -> AppConfiguration:
with open(filename, 'r') as f: with open(filename, 'r') as f:
try: try:
response_json = json.load(f) return from_json(AppConfiguration, json.load(f))
except json.decoder.JSONDecodeError: except json.decoder.JSONDecodeError:
response_json = None return AppConfiguration.get_default_configuration()
if not response_json:
default_configuration = AppConfiguration()
default_configuration.servers = []
default_configuration.current_server = -1
return default_configuration
return from_json(AppConfiguration, response_json)
def save_config(config: AppConfiguration, filename: str): def save_config(config: AppConfiguration, filename: str):

View File

@@ -19,35 +19,41 @@ class LibremsonicApp(Gtk.Application):
**kwargs, **kwargs,
) )
self.window = None self.window = None
self.config_file = None
self.config = None
# Specify Command Line Options
self.add_main_option( self.add_main_option(
'config', ord('c'), GLib.OptionFlags.NONE, GLib.OptionArg.FILENAME, 'config', ord('c'), GLib.OptionFlags.NONE, GLib.OptionArg.FILENAME,
'Specify a configuration file. Defaults to ~/.config/libremsonic/config.json', 'Specify a configuration file. Defaults to ~/.config/libremsonic/config.json',
None) None)
self.config_file = None # Handle command line option parsing.
self.config = None
def do_command_line(self, command_line): def do_command_line(self, command_line):
options = command_line.get_options_dict() options = command_line.get_options_dict()
self.config_file = options.lookup_value('config')
# Config File
self.config_file = options.lookup_value('config')
if self.config_file: if self.config_file:
self.config_file = self.config_file.get_bytestring().decode( self.config_file = self.config_file.get_bytestring().decode(
'utf-8') 'utf-8')
else: else:
# Default to ~/.config/libremsonic.
config_folder = (os.environ.get('XDG_CONFIG_HOME') config_folder = (os.environ.get('XDG_CONFIG_HOME')
or os.environ.get('APPDATA') or os.path.join( or os.environ.get('APPDATA') or os.path.join(
os.environ.get('HOME'), '.config')) os.environ.get('HOME'), '.config'))
config_folder = os.path.join(config_folder, 'libremsonic') config_folder = os.path.join(config_folder, 'libremsonic')
self.config_file = os.path.join(config_folder, 'config.yaml') self.config_file = os.path.join(config_folder, 'config.yaml')
# Have to do this or else the application doesn't work. Not entirely
# sure why, but C-bindings...
self.activate() self.activate()
return 0 return 0
def do_startup(self): def do_startup(self):
Gtk.Application.do_startup(self) Gtk.Application.do_startup(self)
# Add action for configuring servers
action = Gio.SimpleAction.new('configure_servers', None) action = Gio.SimpleAction.new('configure_servers', None)
action.connect('activate', self.on_configure_servers) action.connect('activate', self.on_configure_servers)
self.add_action(action) self.add_action(action)
@@ -62,6 +68,9 @@ class LibremsonicApp(Gtk.Application):
self.window.show_all() self.window.show_all()
self.window.present() self.window.present()
# Load the configuration and update the UI with the curent server, if
# it exists. If there is no current server, show the dialog to select a
# server.
self.load_settings() self.load_settings()
if self.config.current_server is None: if self.config.current_server is None:
@@ -72,18 +81,19 @@ class LibremsonicApp(Gtk.Application):
def on_configure_servers(self, action, param): def on_configure_servers(self, action, param):
self.show_configure_servers_dialog() self.show_configure_servers_dialog()
def on_server_list_changed(self, action, params): def on_server_list_changed(self, action, servers):
self.config.servers = params self.config.servers = servers
self.save_settings() self.save_settings()
def on_connected_server_changed(self, action, params): def on_connected_server_changed(self, action, current_server):
self.config.current_server = params self.config.current_server = current_server
self.save_settings() self.save_settings()
# Update the window according to the new server configuration. # Update the window according to the new server configuration.
self.window.update(self.config) self.window.update(self.config)
def show_configure_servers_dialog(self): def show_configure_servers_dialog(self):
"""Show the Connect to Server dialog."""
dialog = ConfigureServersDialog(self.window, self.config) dialog = ConfigureServersDialog(self.window, self.config)
dialog.connect('server-list-changed', self.on_server_list_changed) dialog.connect('server-list-changed', self.on_server_list_changed)
dialog.connect('connected-server-changed', dialog.connect('connected-server-changed',

View File

@@ -8,8 +8,12 @@ from libremsonic.config import ServerConfiguration
class EditServerDialog(Gtk.Dialog): class EditServerDialog(Gtk.Dialog):
"""
The Add New/Edit Server Dialog. The dialogs are the same, but when editing,
an ``existing_config`` will be specified.
"""
def __init__(self, parent, existing_config=None): def __init__(self, parent, existing_config=None):
editing = existing_config != None editing = existing_config is not None
Gtk.Dialog.__init__( Gtk.Dialog.__init__(
self, self,
f'Edit {existing_config.name}' if editing else 'Add New Server', f'Edit {existing_config.name}' if editing else 'Add New Server',
@@ -29,6 +33,7 @@ class EditServerDialog(Gtk.Dialog):
flowbox.pack_start(label_box, False, True, 10) flowbox.pack_start(label_box, False, True, 10)
flowbox.pack_start(entry_box, True, True, 10) flowbox.pack_start(entry_box, True, True, 10)
# Store a map of field label to GTK component.
self.data = {} self.data = {}
# Create all of the text entry fields for the server configuration. # Create all of the text entry fields for the server configuration.
@@ -42,10 +47,12 @@ class EditServerDialog(Gtk.Dialog):
('Password', existing_config.password, True), ('Password', existing_config.password, True),
] ]
for label, value, is_password in text_fields: for label, value, is_password in text_fields:
# Put the label in the left box.
entry_label = Gtk.Label(label + ':') entry_label = Gtk.Label(label + ':')
entry_label.set_halign(Gtk.Align.START) entry_label.set_halign(Gtk.Align.START)
label_box.pack_start(entry_label, True, True, 0) label_box.pack_start(entry_label, True, True, 0)
# Put the text entry in the right box.
entry = Gtk.Entry(text=value) entry = Gtk.Entry(text=value)
if is_password: if is_password:
entry.set_visibility(False) entry.set_visibility(False)
@@ -58,10 +65,13 @@ class EditServerDialog(Gtk.Dialog):
('Sync enabled', existing_config.sync_enabled), ('Sync enabled', existing_config.sync_enabled),
] ]
for label, value in boolean_fields: for label, value in boolean_fields:
# Put the label in the left box.
entry_label = Gtk.Label(label + ':') entry_label = Gtk.Label(label + ':')
entry_label.set_halign(Gtk.Align.START) entry_label.set_halign(Gtk.Align.START)
label_box.pack_start(entry_label, True, True, 0) label_box.pack_start(entry_label, True, True, 0)
# Put the checkbox in the right box. Note we have to pad here since
# the checkboxes are smaller than the text fields.
checkbox = Gtk.CheckButton(active=value) checkbox = Gtk.CheckButton(active=value)
entry_box.pack_start(checkbox, True, True, 5) entry_box.pack_start(checkbox, True, True, 5)
self.data[label] = checkbox self.data[label] = checkbox
@@ -84,12 +94,15 @@ class EditServerDialog(Gtk.Dialog):
self.show_all() self.show_all()
def on_test_server_clicked(self, event): def on_test_server_clicked(self, event):
# Instantiate the server.
server = Server( server = Server(
self.data['Name'].get_text(), self.data['Name'].get_text(),
self.data['Server address'].get_text(), self.data['Server address'].get_text(),
self.data['Username'].get_text(), self.data['Username'].get_text(),
self.data['Password'].get_text(), self.data['Password'].get_text(),
) )
# Try to ping, and show a message box with whether or not it worked.
try: try:
server.ping() server.ping()
dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.INFO, dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.INFO,
@@ -128,17 +141,18 @@ class ConfigureServersDialog(Gtk.Dialog):
self.selected_server_index = config.current_server self.selected_server_index = config.current_server
self.set_default_size(450, 300) self.set_default_size(450, 300)
# Flow box to hold the server list and the buttons.
flowbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) flowbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
# Server List
self.server_list = Gtk.ListBox() self.server_list = Gtk.ListBox()
self.server_list.connect('selected-rows-changed', self.server_list.connect('selected-rows-changed',
self.server_list_on_selected_rows_changed) self.server_list_on_selected_rows_changed)
flowbox.pack_start(self.server_list, True, True, 10) flowbox.pack_start(self.server_list, True, True, 10)
# Right Side button_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
button_array = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
# Tuples: (button, action function, pack side, requires_selection) # Tuples: (button, action function, pack side, requires_selection)
# Add all of the buttons to the button box.
self.buttons = [ self.buttons = [
# TODO get good icons for these # TODO get good icons for these
(Gtk.Button('Edit...'), lambda e: self.on_edit_clicked(e, False), (Gtk.Button('Edit...'), lambda e: self.on_edit_clicked(e, False),
@@ -153,14 +167,15 @@ class ConfigureServersDialog(Gtk.Dialog):
btn, action, pack_end, requires_selection = button_cfg btn, action, pack_end, requires_selection = button_cfg
if pack_end == 'end': if pack_end == 'end':
button_array.pack_end(btn, False, True, 5) button_box.pack_end(btn, False, True, 5)
else: else:
button_array.pack_start(btn, False, True, 5) button_box.pack_start(btn, False, True, 5)
btn.connect('clicked', action) btn.connect('clicked', action)
flowbox.pack_end(button_array, False, False, 0) flowbox.pack_end(button_box, False, False, 0)
# Add the flowbox to the dialog and show the dialog.
content_area = self.get_content_area() content_area = self.get_content_area()
content_area.pack_start(flowbox, True, True, 10) content_area.pack_start(flowbox, True, True, 10)
@@ -169,9 +184,11 @@ class ConfigureServersDialog(Gtk.Dialog):
self.server_list_on_selected_rows_changed(None) self.server_list_on_selected_rows_changed(None)
def refresh_server_list(self): def refresh_server_list(self):
# Clear out the list.
for el in self.server_list: for el in self.server_list:
self.server_list.remove(el) self.server_list.remove(el)
# Add all of the rows for each of the servers.
for config in self.server_configs: for config in self.server_configs:
row = Gtk.ListBoxRow() row = Gtk.ListBoxRow()
server_name_label = Gtk.Label(config.name) server_name_label = Gtk.Label(config.name)
@@ -179,6 +196,7 @@ class ConfigureServersDialog(Gtk.Dialog):
row.add(server_name_label) row.add(server_name_label)
self.server_list.add(row) self.server_list.add(row)
# Show them, and select the current server.
self.show_all() self.show_all()
if self.selected_server_index is not None and self.selected_server_index >= 0: if self.selected_server_index is not None and self.selected_server_index >= 0:
self.server_list.select_row( self.server_list.select_row(
@@ -201,6 +219,7 @@ class ConfigureServersDialog(Gtk.Dialog):
result = dialog.run() result = dialog.run()
if result == Gtk.ResponseType.OK: if result == Gtk.ResponseType.OK:
# Create a new server configuration to use.
new_config = ServerConfiguration( new_config = ServerConfiguration(
name=dialog.data['Name'].get_text(), name=dialog.data['Name'].get_text(),
server_address=dialog.data['Server address'].get_text(), server_address=dialog.data['Server address'].get_text(),
@@ -230,6 +249,8 @@ class ConfigureServersDialog(Gtk.Dialog):
self.close() self.close()
def server_list_on_selected_rows_changed(self, event): def server_list_on_selected_rows_changed(self, event):
# Update the state of the buttons depending on whether or not a row is
# selected in the server list.
has_selection = self.server_list.get_selected_row() has_selection = self.server_list.get_selected_row()
for button, *_, requires_selection in self.buttons: for button, *_, requires_selection in self.buttons: