From 48a02206722eaf091864be1842d927923eaa7864 Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Thu, 14 Dec 2023 17:39:54 +0000 Subject: [PATCH 1/6] Add button in action bar --- src/MainWindow.vala | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 01a51903e..82073f1de 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -48,10 +48,25 @@ public class Music.MainWindow : Gtk.ApplicationWindow { var drop_target = new Gtk.DropTarget (typeof (Gdk.FileList), Gdk.DragAction.COPY); + var add_button_label = new Gtk.Label (_("Add Music…")); + var add_button_box = new Gtk.Box (HORIZONTAL, 0); + add_button_box.append (new Gtk.Image.from_icon_name ("list-add-symbolic")); + add_button_box.append (add_button_label); + + var add_button = new Gtk.Button () { + child = add_button_box + }; + add_button.add_css_class (Granite.STYLE_CLASS_FLAT); + + var queue_action_bar = new Gtk.ActionBar (); + queue_action_bar.pack_start (add_button); + queue_action_bar.add_css_class (Granite.STYLE_CLASS_FLAT); + var queue = new Gtk.Grid (); queue.add_css_class (Granite.STYLE_CLASS_VIEW); queue.attach (queue_header, 0, 0); queue.attach (scrolled, 0, 1); + queue.attach (queue_action_bar, 0, 2); queue.add_controller (drop_target); var error_toast = new Granite.Toast (""); From db764d659c78f7e4fc8b5216fa3d98259d32831e Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Thu, 14 Dec 2023 18:54:12 +0000 Subject: [PATCH 2/6] Implement open files action --- src/Application.vala | 49 +++++++++++++++++++++++++++++++++++++++++++- src/MainWindow.vala | 42 ++++++++++++++++++++----------------- 2 files changed, 71 insertions(+), 20 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index 1b3c4df39..ce582c57a 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -9,12 +9,14 @@ public class Music.Application : Gtk.Application { public const string ACTION_PLAY_PAUSE = "action-play-pause"; public const string ACTION_PREVIOUS = "action-previous"; public const string ACTION_SHUFFLE = "action-shuffle"; + public const string ACTION_OPEN = "action-open"; private const ActionEntry[] ACTION_ENTRIES = { { ACTION_PLAY_PAUSE, action_play_pause, null, "false" }, { ACTION_NEXT, action_next }, { ACTION_PREVIOUS, action_previous }, - { ACTION_SHUFFLE, action_shuffle } + { ACTION_SHUFFLE, action_shuffle }, + { ACTION_OPEN, action_open } }; private PlaybackManager? playback_manager = null; @@ -175,6 +177,51 @@ public class Music.Application : Gtk.Application { playback_manager.shuffle (); } + private void action_open () { + var all_files_filter = new Gtk.FileFilter () { + name = _("All files"), + }; + all_files_filter.add_pattern ("*"); + var music_files_filter = new Gtk.FileFilter () { + name = _("Music Files"), + }; + music_files_filter.add_mime_type ("audio/*"); + + var filter_model = new ListStore (typeof (Gtk.FileFilter)); + filter_model.append (all_files_filter); + filter_model.append (music_files_filter); + + var file_chooser = new Gtk.FileChooserNative ( + _("Open some files"), + active_window, + Gtk.FileChooserAction.OPEN, + _("Open"), + _("Cancel") + ); + file_chooser.add_filter (music_files_filter); + file_chooser.add_filter (all_files_filter); + file_chooser.select_multiple = true; + + file_chooser.response.connect ((response) => { + SList file_list = null; + if (response == Gtk.ResponseType.ACCEPT) { + var files = file_chooser.get_files (); + File? file; + int index = 0; + while (files.get_item (index) != null) { + file_list.prepend ((File)(files.get_item (index))); + index++; + } + + ((MainWindow)active_window).queue_files (file_list); + } + + file_chooser.destroy (); + }); + + file_chooser.show (); + } + private void on_bus_acquired (DBusConnection connection, string name) { try { connection.register_object ("/org/mpris/MediaPlayer2", new MprisRoot ()); diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 82073f1de..edab9fee6 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -54,7 +54,8 @@ public class Music.MainWindow : Gtk.ApplicationWindow { add_button_box.append (add_button_label); var add_button = new Gtk.Button () { - child = add_button_box + child = add_button_box, + action_name = Application.ACTION_PREFIX + Application.ACTION_OPEN }; add_button.add_css_class (Granite.STYLE_CLASS_FLAT); @@ -130,24 +131,8 @@ public class Music.MainWindow : Gtk.ApplicationWindow { drop_target.drop.connect ((target, value, x, y) => { if (value.type () == typeof (Gdk.FileList)) { - File[] files; - SList file_list = null; - foreach (unowned var file in (SList) value.get_boxed ()) { - var file_type = file.query_file_type (FileQueryInfoFlags.NONE); - if (file_type == FileType.DIRECTORY) { - prepend_directory_files (file, ref file_list); - } else { - file_list.prepend (file); - } - } - - file_list.reverse (); - foreach (unowned var file in file_list) { - files += file; - } - - playback_manager.queue_files (files); - + var list = (Gdk.FileList)value; + queue_files (list.get_files ()); return true; } @@ -176,6 +161,25 @@ public class Music.MainWindow : Gtk.ApplicationWindow { }); } + public void queue_files (SList files) { + File[] file_array = {}; + SList file_list = null; + foreach (unowned var file in files) { + var file_type = file.query_file_type (FileQueryInfoFlags.NONE); + if (file_type == FileType.DIRECTORY) { + prepend_directory_files (file, ref file_list); + } else { + file_list.prepend (file); + } + } + + file_list.reverse (); + foreach (unowned var file in file_list) { + file_array += file; + } + + PlaybackManager.get_default ().queue_files (file_array); + } //Array concatenation not permitted for parameters so use a list instead private void prepend_directory_files (GLib.File dir, ref SList file_list) { try { From 378052822fe6262d5c66d368913efc0ef197e15d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 14 May 2024 09:55:58 -0700 Subject: [PATCH 3/6] Address review comments --- src/Application.vala | 42 +++++++++++++++++------------------------- src/MainWindow.vala | 1 + 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index 8a07cb45d..ce87481a6 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -186,8 +186,9 @@ public class Music.Application : Gtk.Application { name = _("All files"), }; all_files_filter.add_pattern ("*"); + var music_files_filter = new Gtk.FileFilter () { - name = _("Music Files"), + name = _("Music files"), }; music_files_filter.add_mime_type ("audio/*"); @@ -195,35 +196,26 @@ public class Music.Application : Gtk.Application { filter_model.append (all_files_filter); filter_model.append (music_files_filter); - var file_chooser = new Gtk.FileChooserNative ( - _("Open some files"), - active_window, - Gtk.FileChooserAction.OPEN, - _("Open"), - _("Cancel") - ); - file_chooser.add_filter (music_files_filter); - file_chooser.add_filter (all_files_filter); - file_chooser.select_multiple = true; + var file_dialog = new Gtk.FileDialog () { + accept_label = _("Open"), + default_filter = music_files_filter, + filters = filter_model, + modal = true, + title = _("Open audio files") + }; - file_chooser.response.connect ((response) => { - SList file_list = null; - if (response == Gtk.ResponseType.ACCEPT) { - var files = file_chooser.get_files (); - File? file; - int index = 0; - while (files.get_item (index) != null) { - file_list.prepend ((File)(files.get_item (index))); - index++; - } + file_dialog.open_multiple.begin (active_window, null, (obj, res) => { + var files = file_dialog.open_multiple.end (res); - ((MainWindow)active_window).queue_files (file_list); + SList file_list = null; + int index = 0; + while (files.get_item (index) != null) { + file_list.prepend ((File)(files.get_item (index))); + index++; } - file_chooser.destroy (); + ((MainWindow) active_window).queue_files (file_list); }); - - file_chooser.show (); } private void on_bus_acquired (DBusConnection connection, string name) { diff --git a/src/MainWindow.vala b/src/MainWindow.vala index edab9fee6..599737702 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -180,6 +180,7 @@ public class Music.MainWindow : Gtk.ApplicationWindow { PlaybackManager.get_default ().queue_files (file_array); } + //Array concatenation not permitted for parameters so use a list instead private void prepend_directory_files (GLib.File dir, ref SList file_list) { try { From 3e04983b2b27244600afa5ef8ad5662066203509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 14 May 2024 09:59:58 -0700 Subject: [PATCH 4/6] Move open to Window so we're not reaching across classes --- src/Application.vala | 41 +---------------------------------------- src/MainWindow.vala | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index ce87481a6..f27503c75 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -9,14 +9,12 @@ public class Music.Application : Gtk.Application { public const string ACTION_PLAY_PAUSE = "action-play-pause"; public const string ACTION_PREVIOUS = "action-previous"; public const string ACTION_SHUFFLE = "action-shuffle"; - public const string ACTION_OPEN = "action-open"; private const ActionEntry[] ACTION_ENTRIES = { { ACTION_PLAY_PAUSE, action_play_pause, null, "false" }, { ACTION_NEXT, action_next }, { ACTION_PREVIOUS, action_previous }, - { ACTION_SHUFFLE, action_shuffle }, - { ACTION_OPEN, action_open } + { ACTION_SHUFFLE, action_shuffle } }; private PlaybackManager? playback_manager = null; @@ -181,43 +179,6 @@ public class Music.Application : Gtk.Application { playback_manager.shuffle (); } - private void action_open () { - var all_files_filter = new Gtk.FileFilter () { - name = _("All files"), - }; - all_files_filter.add_pattern ("*"); - - var music_files_filter = new Gtk.FileFilter () { - name = _("Music files"), - }; - music_files_filter.add_mime_type ("audio/*"); - - var filter_model = new ListStore (typeof (Gtk.FileFilter)); - filter_model.append (all_files_filter); - filter_model.append (music_files_filter); - - var file_dialog = new Gtk.FileDialog () { - accept_label = _("Open"), - default_filter = music_files_filter, - filters = filter_model, - modal = true, - title = _("Open audio files") - }; - - file_dialog.open_multiple.begin (active_window, null, (obj, res) => { - var files = file_dialog.open_multiple.end (res); - - SList file_list = null; - int index = 0; - while (files.get_item (index) != null) { - file_list.prepend ((File)(files.get_item (index))); - index++; - } - - ((MainWindow) active_window).queue_files (file_list); - }); - } - private void on_bus_acquired (DBusConnection connection, string name) { try { connection.register_object ("/org/mpris/MediaPlayer2", new MprisRoot ()); diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 599737702..ad470784b 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -55,7 +55,6 @@ public class Music.MainWindow : Gtk.ApplicationWindow { var add_button = new Gtk.Button () { child = add_button_box, - action_name = Application.ACTION_PREFIX + Application.ACTION_OPEN }; add_button.add_css_class (Granite.STYLE_CLASS_FLAT); @@ -147,6 +146,8 @@ public class Music.MainWindow : Gtk.ApplicationWindow { error_toast.send_notification (); }); + add_button.clicked.connect (action_open); + repeat_button.clicked.connect (() => { var enum_step = settings.get_enum ("repeat-mode"); if (enum_step < 2) { @@ -161,6 +162,47 @@ public class Music.MainWindow : Gtk.ApplicationWindow { }); } + private void action_open () { + var all_files_filter = new Gtk.FileFilter () { + name = _("All files"), + }; + all_files_filter.add_pattern ("*"); + + var music_files_filter = new Gtk.FileFilter () { + name = _("Music files"), + }; + music_files_filter.add_mime_type ("audio/*"); + + var filter_model = new ListStore (typeof (Gtk.FileFilter)); + filter_model.append (all_files_filter); + filter_model.append (music_files_filter); + + var file_dialog = new Gtk.FileDialog () { + accept_label = _("Open"), + default_filter = music_files_filter, + filters = filter_model, + modal = true, + title = _("Open audio files") + }; + + file_dialog.open_multiple.begin (this, null, (obj, res) => { + try { + var files = file_dialog.open_multiple.end (res); + + SList file_list = null; + int index = 0; + while (files.get_item (index) != null) { + file_list.prepend ((File)(files.get_item (index))); + index++; + } + + queue_files (file_list); + } catch (Error e) { + // FIXME: throw error dialog + } + }); + } + public void queue_files (SList files) { File[] file_array = {}; SList file_list = null; From 6869bb6d426dd5f59a8838ba3c9dc0fcaac387d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 14 May 2024 10:25:41 -0700 Subject: [PATCH 5/6] DRY --- src/Application.vala | 4 +-- src/MainWindow.vala | 64 ++++++++++---------------------------------- 2 files changed, 16 insertions(+), 52 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index f27503c75..ce0db16b8 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -107,7 +107,7 @@ public class Music.Application : Gtk.Application { settings.bind ("window-maximized", main_window, "maximized", SettingsBindFlags.SET); } - private File[] list_directory (string directory) { + private static File[] list_directory (string directory) { Dir dir; try { dir = Dir.open (directory, 0); @@ -129,7 +129,7 @@ public class Music.Application : Gtk.Application { return elements; } - private File[] loop_through_files (File[] files) { + public static File[] loop_through_files (File[] files) { // All of these will be returned later in bulk File[] elements = {}; diff --git a/src/MainWindow.vala b/src/MainWindow.vala index d7d8e517d..f5d8f34cc 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -134,7 +134,15 @@ public class Music.MainWindow : Gtk.ApplicationWindow { drop_target.drop.connect ((target, value, x, y) => { if (value.type () == typeof (Gdk.FileList)) { var list = (Gdk.FileList)value; - queue_files (list.get_files ()); + + File[] file_array = {}; + foreach (unowned var file in list.get_files ()) { + file_array += file; + } + + var files_to_play = Application.loop_through_files (file_array); + PlaybackManager.get_default ().queue_files (files_to_play); + return true; } @@ -192,63 +200,19 @@ public class Music.MainWindow : Gtk.ApplicationWindow { try { var files = file_dialog.open_multiple.end (res); - SList file_list = null; - int index = 0; - while (files.get_item (index) != null) { - file_list.prepend ((File)(files.get_item (index))); - index++; + File[] file_array = {}; + for (int i = 0; i < files.get_n_items (); i++) { + file_array += (File)(files.get_item (i)); } - queue_files (file_list); + var files_to_play = Application.loop_through_files (file_array); + PlaybackManager.get_default ().queue_files (files_to_play); } catch (Error e) { // FIXME: throw error dialog } }); } - public void queue_files (SList files) { - File[] file_array = {}; - SList file_list = null; - foreach (unowned var file in files) { - var file_type = file.query_file_type (FileQueryInfoFlags.NONE); - if (file_type == FileType.DIRECTORY) { - prepend_directory_files (file, ref file_list); - } else { - file_list.prepend (file); - } - } - - file_list.reverse (); - foreach (unowned var file in file_list) { - file_array += file; - } - - PlaybackManager.get_default ().queue_files (file_array); - } - - //Array concatenation not permitted for parameters so use a list instead - private void prepend_directory_files (GLib.File dir, ref SList file_list) { - try { - var enumerator = dir.enumerate_children ( - "standard::*", - FileQueryInfoFlags.NOFOLLOW_SYMLINKS, - null - ); - - FileInfo info = null; - while ((info = enumerator.next_file (null)) != null) { - var child = dir.resolve_relative_path (info.get_name ()); - if (info.get_file_type () == FileType.DIRECTORY) { - prepend_directory_files (child, ref file_list); - } else { - file_list.prepend (child); - } - } - } catch (Error e) { - warning ("Error while enumerating children of %s: %s", dir.get_uri (), e.message); - } - } - private void update_repeat_button () { switch (settings.get_string ("repeat-mode")) { case "disabled": From 9611ebf9c2f7d7fbf1ed022eba516a86237c7927 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 14 May 2024 10:43:41 -0700 Subject: [PATCH 6/6] Handle error, button text icon --- src/MainWindow.vala | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/MainWindow.vala b/src/MainWindow.vala index f5d8f34cc..e542cdf63 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -47,10 +47,10 @@ public class Music.MainWindow : Gtk.ApplicationWindow { var drop_target = new Gtk.DropTarget (typeof (Gdk.FileList), Gdk.DragAction.COPY); - var add_button_label = new Gtk.Label (_("Add Music…")); + var add_button_label = new Gtk.Label (_("Open Files…")); var add_button_box = new Gtk.Box (HORIZONTAL, 0); - add_button_box.append (new Gtk.Image.from_icon_name ("list-add-symbolic")); + add_button_box.append (new Gtk.Image.from_icon_name ("document-open-symbolic")); add_button_box.append (add_button_label); var add_button = new Gtk.Button () { @@ -208,7 +208,21 @@ public class Music.MainWindow : Gtk.ApplicationWindow { var files_to_play = Application.loop_through_files (file_array); PlaybackManager.get_default ().queue_files (files_to_play); } catch (Error e) { - // FIXME: throw error dialog + if (e.matches (Gtk.DialogError.quark (), Gtk.DialogError.DISMISSED)) { + return; + } + + var dialog = new Granite.MessageDialog ( + "Couldn't add audio files", + e.message, + new ThemedIcon ("document-open") + ) { + badge_icon = new ThemedIcon ("dialog-error"), + modal = true, + transient_for = this + }; + dialog.present (); + dialog.response.connect (dialog.destroy); } }); }