diff --git a/libremsonic/config.py b/libremsonic/config.py index 618c82c..8030fc8 100644 --- a/libremsonic/config.py +++ b/libremsonic/config.py @@ -60,17 +60,9 @@ def get_config(filename: str) -> AppConfiguration: with open(filename, 'r') as f: try: - response_json = json.load(f) + return from_json(AppConfiguration, json.load(f)) except json.decoder.JSONDecodeError: - response_json = None - - if not response_json: - default_configuration = AppConfiguration() - default_configuration.servers = [] - default_configuration.current_server = -1 - return default_configuration - - return from_json(AppConfiguration, response_json) + return AppConfiguration.get_default_configuration() def save_config(config: AppConfiguration, filename: str): diff --git a/libremsonic/ui/app.py b/libremsonic/ui/app.py index 6018467..7ed0821 100644 --- a/libremsonic/ui/app.py +++ b/libremsonic/ui/app.py @@ -19,35 +19,41 @@ class LibremsonicApp(Gtk.Application): **kwargs, ) self.window = None + self.config_file = None + self.config = None + # Specify Command Line Options self.add_main_option( 'config', ord('c'), GLib.OptionFlags.NONE, GLib.OptionArg.FILENAME, 'Specify a configuration file. Defaults to ~/.config/libremsonic/config.json', None) - self.config_file = None - self.config = None - + # Handle command line option parsing. def do_command_line(self, command_line): 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: self.config_file = self.config_file.get_bytestring().decode( 'utf-8') else: + # Default to ~/.config/libremsonic. config_folder = (os.environ.get('XDG_CONFIG_HOME') or os.environ.get('APPDATA') or os.path.join( os.environ.get('HOME'), '.config')) config_folder = os.path.join(config_folder, 'libremsonic') 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() return 0 def do_startup(self): Gtk.Application.do_startup(self) + # Add action for configuring servers action = Gio.SimpleAction.new('configure_servers', None) action.connect('activate', self.on_configure_servers) self.add_action(action) @@ -62,6 +68,9 @@ class LibremsonicApp(Gtk.Application): self.window.show_all() 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() if self.config.current_server is None: @@ -72,18 +81,19 @@ class LibremsonicApp(Gtk.Application): def on_configure_servers(self, action, param): self.show_configure_servers_dialog() - def on_server_list_changed(self, action, params): - self.config.servers = params + def on_server_list_changed(self, action, servers): + self.config.servers = servers self.save_settings() - def on_connected_server_changed(self, action, params): - self.config.current_server = params + def on_connected_server_changed(self, action, current_server): + self.config.current_server = current_server self.save_settings() # Update the window according to the new server configuration. self.window.update(self.config) def show_configure_servers_dialog(self): + """Show the Connect to Server dialog.""" dialog = ConfigureServersDialog(self.window, self.config) dialog.connect('server-list-changed', self.on_server_list_changed) dialog.connect('connected-server-changed', diff --git a/libremsonic/ui/configure_servers.py b/libremsonic/ui/configure_servers.py index 3717a2b..6a94b08 100644 --- a/libremsonic/ui/configure_servers.py +++ b/libremsonic/ui/configure_servers.py @@ -8,8 +8,12 @@ from libremsonic.config import ServerConfiguration 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): - editing = existing_config != None + editing = existing_config is not None Gtk.Dialog.__init__( self, 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(entry_box, True, True, 10) + # Store a map of field label to GTK component. self.data = {} # Create all of the text entry fields for the server configuration. @@ -42,10 +47,12 @@ class EditServerDialog(Gtk.Dialog): ('Password', existing_config.password, True), ] for label, value, is_password in text_fields: + # Put the label in the left box. entry_label = Gtk.Label(label + ':') entry_label.set_halign(Gtk.Align.START) label_box.pack_start(entry_label, True, True, 0) + # Put the text entry in the right box. entry = Gtk.Entry(text=value) if is_password: entry.set_visibility(False) @@ -58,10 +65,13 @@ class EditServerDialog(Gtk.Dialog): ('Sync enabled', existing_config.sync_enabled), ] for label, value in boolean_fields: + # Put the label in the left box. entry_label = Gtk.Label(label + ':') entry_label.set_halign(Gtk.Align.START) 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) entry_box.pack_start(checkbox, True, True, 5) self.data[label] = checkbox @@ -84,12 +94,15 @@ class EditServerDialog(Gtk.Dialog): self.show_all() def on_test_server_clicked(self, event): + # Instantiate the server. server = Server( self.data['Name'].get_text(), self.data['Server address'].get_text(), self.data['Username'].get_text(), self.data['Password'].get_text(), ) + + # Try to ping, and show a message box with whether or not it worked. try: server.ping() dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.INFO, @@ -128,17 +141,18 @@ class ConfigureServersDialog(Gtk.Dialog): self.selected_server_index = config.current_server self.set_default_size(450, 300) + # Flow box to hold the server list and the buttons. flowbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) + # Server List self.server_list = Gtk.ListBox() self.server_list.connect('selected-rows-changed', self.server_list_on_selected_rows_changed) - flowbox.pack_start(self.server_list, True, True, 10) - # Right Side - button_array = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) + button_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) # Tuples: (button, action function, pack side, requires_selection) + # Add all of the buttons to the button box. self.buttons = [ # TODO get good icons for these (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 if pack_end == 'end': - button_array.pack_end(btn, False, True, 5) + button_box.pack_end(btn, False, True, 5) else: - button_array.pack_start(btn, False, True, 5) + button_box.pack_start(btn, False, True, 5) 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.pack_start(flowbox, True, True, 10) @@ -169,9 +184,11 @@ class ConfigureServersDialog(Gtk.Dialog): self.server_list_on_selected_rows_changed(None) def refresh_server_list(self): + # Clear out the list. for el in self.server_list: self.server_list.remove(el) + # Add all of the rows for each of the servers. for config in self.server_configs: row = Gtk.ListBoxRow() server_name_label = Gtk.Label(config.name) @@ -179,6 +196,7 @@ class ConfigureServersDialog(Gtk.Dialog): row.add(server_name_label) self.server_list.add(row) + # Show them, and select the current server. self.show_all() if self.selected_server_index is not None and self.selected_server_index >= 0: self.server_list.select_row( @@ -201,6 +219,7 @@ class ConfigureServersDialog(Gtk.Dialog): result = dialog.run() if result == Gtk.ResponseType.OK: + # Create a new server configuration to use. new_config = ServerConfiguration( name=dialog.data['Name'].get_text(), server_address=dialog.data['Server address'].get_text(), @@ -230,6 +249,8 @@ class ConfigureServersDialog(Gtk.Dialog): self.close() 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() for button, *_, requires_selection in self.buttons: