Skip to content

Commit 91f4964

Browse files
committed
Adds an "Open Folder…" button to open folders only
- Eases the opening of directories by not automatically selecting one - Validating with "Open" imports the current directory and its subdirectories (if no element has been manually selected) - Prevents selecting individual files
1 parent f0325df commit 91f4964

3 files changed

Lines changed: 72 additions & 23 deletions

File tree

src/Application.vala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ public class Music.Application : Gtk.Application {
131131
return elements;
132132
}
133133

134+
/**
135+
* Flattens files and those contained in (sub)directories
136+
*/
134137
public static File[] loop_through_files (File[] files) {
135138
// All of these will be returned later in bulk
136139
File[] elements = {};

src/MainWindow.vala

Lines changed: 56 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
public class Music.MainWindow : Gtk.ApplicationWindow {
77
public const string ACTION_PREFIX = "win.";
88
public const string ACTION_OPEN = "action-open";
9+
public const string ACTION_OPEN_FOLDER = "action-open-folder";
910

1011
private QueueView queue_view;
1112

@@ -61,8 +62,13 @@ public class Music.MainWindow : Gtk.ApplicationWindow {
6162
open_action.activate.connect (open_files);
6263
add_action (open_action);
6364

65+
var open_folder_action = new SimpleAction (ACTION_OPEN_FOLDER, null);
66+
open_folder_action.activate.connect (open_folder);
67+
add_action (open_folder_action);
68+
6469
unowned var app = ((Gtk.Application) GLib.Application.get_default ());
6570
app.set_accels_for_action (ACTION_PREFIX + ACTION_OPEN, {"<Ctrl>O"});
71+
app.set_accels_for_action (ACTION_PREFIX + ACTION_OPEN_FOLDER, {"<Ctrl><Shift>O"});
6672
}
6773

6874
public void start_search () {
@@ -96,30 +102,59 @@ public class Music.MainWindow : Gtk.ApplicationWindow {
96102
try {
97103
var files = file_dialog.open_multiple.end (res);
98104

99-
File[] file_array = {};
100-
for (int i = 0; i < files.get_n_items (); i++) {
101-
file_array += (File)(files.get_item (i));
102-
}
105+
handle_selected_files (files);
106+
} catch (Error e) {
107+
handle_file_dialog_error (e);
108+
}
109+
});
110+
}
111+
112+
/**
113+
* Same as open_files, except there is not filter and it uses the Folder dialog :
114+
* No folder/file is pre-selected when entering a directory and individual files cannot be selected
115+
*/
116+
private void open_folder () {
117+
var file_dialog = new Gtk.FileDialog () {
118+
accept_label = _("Open"),
119+
modal = true,
120+
title = _("Open folder(s) containing audio files")
121+
};
122+
123+
file_dialog.select_multiple_folders.begin (this, null, (obj, res) => {
124+
try {
125+
var folders = file_dialog.select_multiple_folders.end (res);
103126

104-
var files_to_play = Application.loop_through_files (file_array);
105-
PlaybackManager.get_default ().queue_files (files_to_play);
127+
handle_selected_files (folders);
106128
} catch (Error e) {
107-
if (e.matches (Gtk.DialogError.quark (), Gtk.DialogError.DISMISSED)) {
108-
return;
109-
}
110-
111-
var dialog = new Granite.MessageDialog (
112-
_("Couldn't add audio files"),
113-
e.message,
114-
new ThemedIcon ("document-open")
115-
) {
116-
badge_icon = new ThemedIcon ("dialog-error"),
117-
modal = true,
118-
transient_for = this
119-
};
120-
dialog.present ();
121-
dialog.response.connect (dialog.destroy);
129+
handle_file_dialog_error (e);
122130
}
123131
});
124132
}
133+
134+
private void handle_selected_files (GLib.ListModel files) {
135+
File[] file_array = {};
136+
for (int i = 0; i < files.get_n_items (); i++) {
137+
file_array += (File)(files.get_item (i));
138+
}
139+
var files_to_play = Application.loop_through_files (file_array);
140+
PlaybackManager.get_default ().queue_files (files_to_play);
141+
}
142+
143+
private void handle_file_dialog_error (Error e) {
144+
if (e.matches (Gtk.DialogError.quark (), Gtk.DialogError.DISMISSED)) {
145+
return;
146+
}
147+
148+
var dialog = new Granite.MessageDialog (
149+
_("Couldn't add audio files"),
150+
e.message,
151+
new ThemedIcon ("document-open")
152+
) {
153+
badge_icon = new ThemedIcon ("dialog-error"),
154+
modal = true,
155+
transient_for = this
156+
};
157+
dialog.present ();
158+
dialog.response.connect (dialog.destroy);
159+
}
125160
}

src/Views/QueueView.vala

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ public class Music.QueueView : Granite.Bin {
7878
var drop_target = new Gtk.DropTarget (typeof (Gdk.FileList), Gdk.DragAction.COPY);
7979

8080
var add_button_label = new Gtk.Label (_("Open Files…"));
81-
8281
var add_button_box = new Gtk.Box (HORIZONTAL, 0);
8382
add_button_box.append (new Gtk.Image.from_icon_name ("document-open-symbolic"));
8483
add_button_box.append (add_button_label);
@@ -88,9 +87,20 @@ public class Music.QueueView : Granite.Bin {
8887
action_name = MainWindow.ACTION_PREFIX + MainWindow.ACTION_OPEN
8988
};
9089
add_button.add_css_class (Granite.STYLE_CLASS_FLAT);
91-
9290
add_button_label.mnemonic_widget = add_button;
9391

92+
var add_folder_button_label = new Gtk.Label (_("Open Folder…"));
93+
var add_folder_button_box = new Gtk.Box (HORIZONTAL, 0);
94+
add_folder_button_box.append (new Gtk.Image.from_icon_name ("document-open-symbolic"));
95+
add_folder_button_box.append (add_folder_button_label);
96+
97+
var add_folder_button = new Gtk.Button () {
98+
child = add_folder_button_box,
99+
action_name = MainWindow.ACTION_PREFIX + MainWindow.ACTION_OPEN_FOLDER
100+
};
101+
add_folder_button.add_css_class (Granite.STYLE_CLASS_FLAT);
102+
add_folder_button_label.mnemonic_widget = add_folder_button;
103+
94104
var clear_button_label = new Gtk.Label (_("Clear Queue"));
95105

96106
var clear_button_box = new Gtk.Box (HORIZONTAL, 0);
@@ -107,6 +117,7 @@ public class Music.QueueView : Granite.Bin {
107117

108118
var queue_action_bar = new Gtk.ActionBar ();
109119
queue_action_bar.pack_start (add_button);
120+
queue_action_bar.pack_start (add_folder_button);
110121
queue_action_bar.pack_end (clear_button);
111122

112123
var queue = new Adw.ToolbarView () {

0 commit comments

Comments
 (0)