mirror of
https://gitlab.com/liyaowhen/youtubecollector-git.git
synced 2026-10-01 01:12:59 +00:00
new
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
/* application.vala
|
||||
*
|
||||
* Copyright 2024 Leo Wen
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace Song {
|
||||
public class Application : Adw.Application {
|
||||
public Application () {
|
||||
Object (application_id: "com.liyaowhen.Song", flags: ApplicationFlags.DEFAULT_FLAGS);
|
||||
}
|
||||
|
||||
construct {
|
||||
ActionEntry[] action_entries = {
|
||||
{ "about", this.on_about_action },
|
||||
{ "preferences", this.on_preferences_action },
|
||||
{ "quit", this.quit }
|
||||
};
|
||||
this.add_action_entries (action_entries, this);
|
||||
this.set_accels_for_action ("app.quit", {"<primary>q"});
|
||||
}
|
||||
|
||||
public override void activate () {
|
||||
base.activate ();
|
||||
var win = this.active_window;
|
||||
if (win == null) {
|
||||
win = new Song.Window (this);
|
||||
}
|
||||
win.present ();
|
||||
|
||||
}
|
||||
|
||||
private void on_about_action () {
|
||||
string[] developers = { "Leo Wen" };
|
||||
var about = new Adw.AboutWindow () {
|
||||
transient_for = this.active_window,
|
||||
application_name = "song",
|
||||
application_icon = "com.liyaowhen.Song",
|
||||
developer_name = "Leo Wen",
|
||||
version = "0.1.0",
|
||||
developers = developers,
|
||||
copyright = "© 2024 Leo Wen",
|
||||
};
|
||||
|
||||
about.present ();
|
||||
}
|
||||
|
||||
private void on_preferences_action () {
|
||||
message ("app.preferences action activated");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Gtk;
|
||||
|
||||
namespace Song {
|
||||
|
||||
|
||||
public delegate void EventQueue();
|
||||
/* to ensure that doing things on the main_view_content or sidebar_content
|
||||
in this SongController allows for those objects to exist, instead of
|
||||
doing functions related to this controller in the bare construct {},
|
||||
put it in a signal that will be released when the SongController is ready to use */
|
||||
public class SongController : Object {
|
||||
|
||||
public static MainViewContent main_view_content; // main view content should avoid using this controller during instanciation
|
||||
public static SideBarContent sidebar_content;
|
||||
|
||||
public static SongControls song_controls;
|
||||
|
||||
public static GestureDrag gesture;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GtkShortcutsWindow" id="help_overlay">
|
||||
<property name="modal">True</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsSection">
|
||||
<property name="section-name">shortcuts</property>
|
||||
<property name="max-height">10</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="title" translatable="yes" context="shortcut window">General</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes" context="shortcut window">Show Shortcuts</property>
|
||||
<property name="action-name">win.show-help-overlay</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes" context="shortcut window">Quit</property>
|
||||
<property name="action-name">app.quit</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><g fill="#222222"><path d="m 5 0 c -1.644531 0 -3 1.355469 -3 3 v 2 h 2 v -2 c 0 -0.570312 0.429688 -1 1 -1 h 8 c 0.570312 0 1 0.429688 1 1 v 10 c 0 0.570312 -0.429688 1 -1 1 h -8 c -0.570312 0 -1 -0.429688 -1 -1 v -2 h -2 v 2 c 0 1.644531 1.355469 3 3 3 h 8 c 1.644531 0 3 -1.355469 3 -3 v -10 c 0 -1.644531 -1.355469 -3 -3 -3 z m 0 0"/><path d="m 6 4 v 1 c 0 0.257812 0.128906 0.527344 0.3125 0.71875 l 1.28125 1.28125 h -7.59375 v 2 h 7.59375 l -1.28125 1.28125 c -0.183594 0.191406 -0.3125 0.410156 -0.3125 0.71875 v 1 h 1 c 0.308594 0 0.550781 -0.089844 0.75 -0.28125 l 3.65625 -3.71875 l -3.65625 -3.71875 c -0.199219 -0.191406 -0.441406 -0.28125 -0.75 -0.28125 z m 0 0"/></g></svg>
|
||||
|
After Width: | Height: | Size: 815 B |
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><path d="m 7.5 0 c -4.128906 0 -7.5 3.371094 -7.5 7.5 s 3.371094 7.5 7.5 7.5 s 7.5 -3.371094 7.5 -7.5 s -3.371094 -7.5 -7.5 -7.5 z m 1.84375 2.3125 c 0.953125 0.335938 1.78125 0.925781 2.40625 1.6875 h -1.226562 c -0.304688 -0.609375 -0.699219 -1.179688 -1.179688 -1.6875 z m -3.71875 0.011719 c -0.472656 0.507812 -0.867188 1.070312 -1.171875 1.675781 h -1.203125 c 0.617188 -0.753906 1.4375 -1.335938 2.375 -1.675781 z m 1.375 0.097656 v 1.578125 h -1.398438 c 0.363282 -0.59375 0.828126 -1.128906 1.398438 -1.578125 z m 1 0.015625 c 0.558594 0.445312 1.019531 0.976562 1.378906 1.5625 h -1.378906 z m -5.402344 2.5625 h 1.441406 c -0.214843 0.644531 -0.347656 1.320312 -0.390624 2 h -1.625 c 0.0625 -0.714844 0.265624 -1.390625 0.574218 -2 z m 2.507813 0 h 1.894531 v 2 h -2.34375 c 0.046875 -0.683594 0.195312 -1.359375 0.449219 -2 z m 2.894531 0 h 1.875 c 0.253906 0.640625 0.402344 1.316406 0.449219 2 h -2.324219 z m 2.941406 0 h 1.460938 c 0.308594 0.609375 0.511718 1.285156 0.574218 2 h -1.644531 c -0.042969 -0.679688 -0.175781 -1.355469 -0.390625 -2 z m -8.917968 3 h 1.625 c 0.046874 0.679688 0.175781 1.355469 0.394531 2 h -1.445313 c -0.308594 -0.609375 -0.511718 -1.285156 -0.574218 -2 z m 2.632812 0 h 2.34375 v 2 h -1.890625 c -0.253906 -0.636719 -0.402344 -1.316406 -0.453125 -2 z m 3.34375 0 h 2.324219 c -0.050781 0.683594 -0.199219 1.363281 -0.453125 2 h -1.871094 z m 3.332031 0 h 1.644531 c -0.0625 0.714844 -0.265624 1.390625 -0.574218 2 h -1.464844 c 0.21875 -0.644531 0.347656 -1.320312 0.394531 -2 z m -8.082031 3 h 1.210938 c 0.3125 0.609375 0.710937 1.179688 1.195312 1.6875 c -0.953125 -0.335938 -1.78125 -0.925781 -2.40625 -1.6875 z m 2.363281 0 h 1.386719 v 1.550781 c -0.5625 -0.441406 -1.027344 -0.96875 -1.386719 -1.550781 z m 2.386719 0 h 1.367188 c -0.355469 0.578125 -0.8125 1.097656 -1.367188 1.535156 z m 2.519531 0 h 1.230469 c -0.632812 0.769531 -1.472656 1.363281 -2.4375 1.695312 c 0.492188 -0.507812 0.894531 -1.082031 1.207031 -1.695312 z m 0 0" fill="#222222"/></svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1,22 @@
|
||||
using Json;
|
||||
|
||||
namespace Song {
|
||||
|
||||
public class JsonConfig : GLib.Object {
|
||||
|
||||
private Settings settings = new Settings("com.liyaowhen.Song");
|
||||
|
||||
public class JsonConfig () {
|
||||
var json_text = settings.get_string("songs");
|
||||
|
||||
var parser = new Json.Parser();
|
||||
try {
|
||||
parser.load_from_data (json_text, json_text.length);
|
||||
} catch (GLib.Error e) {
|
||||
print(e.message);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/* main.vala
|
||||
*
|
||||
* Copyright 2024 Leo Wen
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
int main (string[] args) {
|
||||
Gst.init(ref args);
|
||||
var app = new Song.Application ();
|
||||
return app.run (args);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
song_sources = [
|
||||
'main.vala',
|
||||
'application.vala',
|
||||
'window.vala',
|
||||
'music/new_music_popover.vala',
|
||||
'widgets/side_bar.vala',
|
||||
'json_config.vala',
|
||||
'widgets/main_view.vala',
|
||||
'widgets/playlist.vala',
|
||||
'controllers/song_controller.vala',
|
||||
'widgets/music_list_row.vala',
|
||||
'widgets/song_controls.vala'
|
||||
]
|
||||
|
||||
song_deps = [
|
||||
dependency('gtk4'),
|
||||
dependency('libadwaita-1', version: '>= 1.4'),
|
||||
dependency('vte-2.91-gtk4'),
|
||||
dependency('jsonrpc-glib-1.0'),
|
||||
dependency('gstreamer-1.0')
|
||||
]
|
||||
|
||||
song_sources += gnome.compile_resources('song-resources',
|
||||
'song.gresource.xml',
|
||||
c_name: 'song'
|
||||
)
|
||||
|
||||
|
||||
executable('song', song_sources,
|
||||
dependencies: song_deps,
|
||||
install: true,
|
||||
)
|
||||
@@ -0,0 +1,311 @@
|
||||
using GLib;
|
||||
|
||||
namespace Song {
|
||||
public class NewMusicPopover : Adw.Dialog {
|
||||
|
||||
private Settings settings = new Settings ("com.liyaowhen.Song");
|
||||
|
||||
public signal void download();
|
||||
|
||||
private Adw.NavigationView navigation_view_steps;
|
||||
private string steps_state = "";
|
||||
|
||||
private Gtk.Button next_button;
|
||||
private bool isPlaylistFolder;
|
||||
|
||||
public string song_title = "";
|
||||
public string song_url = "";
|
||||
|
||||
construct {
|
||||
|
||||
var header = new Adw.HeaderBar ();
|
||||
header.show_end_title_buttons = false;
|
||||
header.show_start_title_buttons = false;
|
||||
|
||||
provide_ui();
|
||||
|
||||
var cancel_button = new Gtk.Button();
|
||||
cancel_button.label = "Cancel";
|
||||
cancel_button.clicked.connect(() => {
|
||||
close();
|
||||
});
|
||||
|
||||
next_button = new Gtk.Button();
|
||||
next_button.label = "Next";
|
||||
next_button.hide();
|
||||
next_button.clicked.connect(() => {
|
||||
if (steps_state == "online") {
|
||||
var good = false;
|
||||
string command = "ping " + song_url; // Replace with your desired Linux command
|
||||
|
||||
string standard_output;
|
||||
string standard_error;
|
||||
int wait_status;
|
||||
|
||||
download();
|
||||
/*try {
|
||||
Process.spawn_command_line_sync(command,
|
||||
out standard_output,
|
||||
out standard_error,
|
||||
out wait_status);
|
||||
|
||||
print ("stdout:\n");
|
||||
// Output: ````
|
||||
print (standard_output);
|
||||
print ("stderr:\n");
|
||||
print (standard_error);
|
||||
// Output: ``0``
|
||||
print ("Status: %d\n", wait_status);
|
||||
|
||||
download();
|
||||
|
||||
} catch (SpawnError e) {
|
||||
print ("Error: %s\n", e.message);
|
||||
} */
|
||||
}
|
||||
});
|
||||
|
||||
header.pack_end(next_button);
|
||||
header.pack_start(cancel_button);
|
||||
|
||||
var action_bar = new Gtk.ActionBar ();
|
||||
|
||||
var content = new Adw.ToolbarView ();
|
||||
content.add_top_bar (header);
|
||||
|
||||
content.set_content(navigation_view_steps);
|
||||
//content.add_bottom_bar (action_bar);
|
||||
|
||||
set_child(content);
|
||||
|
||||
set_title("create new song");
|
||||
follows_content_size = true;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void provide_ui() {
|
||||
|
||||
navigation_view_steps = new Adw.NavigationView();
|
||||
|
||||
// starting page (choose what kind of app should be)
|
||||
|
||||
var song_folder_button = new Gtk.Button();
|
||||
var song_folder_button_content = new Adw.ButtonContent();
|
||||
song_folder_button_content.set_icon_name("folder-symbolic");
|
||||
song_folder_button_content.set_parent(song_folder_button);
|
||||
song_folder_button.set_hexpand(false);
|
||||
|
||||
|
||||
song_folder_button.clicked.connect(() => {
|
||||
var file_chooser = new Gtk.FileChooserDialog("Choose Folder",
|
||||
null,
|
||||
Gtk.FileChooserAction.SELECT_FOLDER,
|
||||
"_Open",
|
||||
Gtk.ResponseType.ACCEPT,
|
||||
"_Cancel",
|
||||
Gtk.ResponseType.CANCEL);
|
||||
|
||||
|
||||
file_chooser.response.connect((dialouge, response) => {
|
||||
if (response == Gtk.ResponseType.ACCEPT) {
|
||||
// ... retrieve the location from the dialog and open it
|
||||
settings.set_string("song-folder", file_chooser.get_file().get_path());
|
||||
print(settings.get_string("song-folder"));
|
||||
file_chooser.destroy();
|
||||
isPlaylistFolder = true;
|
||||
}
|
||||
if (response == Gtk.ResponseType.CANCEL) {
|
||||
file_chooser.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
file_chooser.show();
|
||||
});
|
||||
|
||||
if (settings.get_string("song-folder") == null) {
|
||||
isPlaylistFolder = false;
|
||||
} else isPlaylistFolder = true;
|
||||
|
||||
song_folder_button.destroy.connect(() => {
|
||||
// for safety
|
||||
song_folder_button_content.destroy();
|
||||
});
|
||||
|
||||
var online_button = new Gtk.Button();
|
||||
var online_button_content = new Adw.ButtonContent();
|
||||
online_button_content.set_icon_name("globe-alt2-symbolic");
|
||||
online_button_content.set_label("from the internet (spotify and youtube supported)");
|
||||
online_button_content.set_parent(online_button);
|
||||
online_button.set_hexpand(false);
|
||||
online_button.sensitive = isPlaylistFolder;
|
||||
|
||||
online_button.destroy.connect(() => {
|
||||
// for safety
|
||||
online_button_content.destroy();
|
||||
});
|
||||
|
||||
var import_button = new Gtk.Button();
|
||||
var import_button_content = new Adw.ButtonContent();
|
||||
import_button_content.set_icon_name("arrow-into-box-symbolic");
|
||||
import_button_content.set_label("use your own music");
|
||||
import_button_content.set_parent(import_button);
|
||||
import_button.set_hexpand(false);
|
||||
import_button.sensitive = isPlaylistFolder;
|
||||
|
||||
import_button.destroy.connect(() => {
|
||||
// for safety
|
||||
import_button_content.destroy();
|
||||
});
|
||||
|
||||
|
||||
|
||||
var starting_page_content = new Gtk.Box(Gtk.Orientation.VERTICAL, 5);
|
||||
starting_page_content.append(song_folder_button);
|
||||
starting_page_content.append(online_button);
|
||||
starting_page_content.append(import_button);
|
||||
|
||||
var starting_page = new Adw.NavigationPage(starting_page_content, "main");
|
||||
|
||||
//add from online
|
||||
var title_entry = new Adw.EntryRow();
|
||||
title_entry.title = "Title";
|
||||
|
||||
var url_entry = new Adw.EntryRow();
|
||||
url_entry.title = "link to song (youtube, spotify supported)";
|
||||
|
||||
title_entry.changed.connect(() => {
|
||||
song_title = title_entry.text;
|
||||
if (song_url.length != 0 && song_title.length != 0) {
|
||||
next_button.sensitive = true;
|
||||
} else {
|
||||
next_button.sensitive = false;
|
||||
}
|
||||
});
|
||||
|
||||
url_entry.changed.connect(() => {
|
||||
song_url = url_entry.text;
|
||||
if (song_url.length != 0 && song_title.length != 0) {
|
||||
next_button.sensitive = true;
|
||||
} else {
|
||||
next_button.sensitive = false;
|
||||
}
|
||||
});
|
||||
|
||||
var online_page_content = new Gtk.ListBox();
|
||||
online_page_content.append(title_entry);
|
||||
online_page_content.append(url_entry);
|
||||
|
||||
var online_page = new Adw.NavigationPage(online_page_content, "beginning");
|
||||
|
||||
|
||||
//downloading page
|
||||
var terminal = new Vte.Terminal();
|
||||
var downloading_page = new Adw.NavigationPage(terminal, "Downloading...");
|
||||
|
||||
// complete page
|
||||
var complete_page_widget = new Adw.StatusPage();
|
||||
complete_page_widget.set_icon_name("emoji-body-symbolic");
|
||||
complete_page_widget.set_title("Done importing song");
|
||||
complete_page_widget.set_description("go back to listening to songs");
|
||||
complete_page_widget.add_css_class("compact");
|
||||
var complete_page = new Adw.NavigationPage(complete_page_widget, "Done");
|
||||
|
||||
//show the views
|
||||
navigation_view_steps.add(starting_page);
|
||||
navigation_view_steps.add(online_page);
|
||||
navigation_view_steps.add(downloading_page);
|
||||
navigation_view_steps.add(complete_page);
|
||||
navigation_view_steps.margin_bottom = 5;
|
||||
navigation_view_steps.margin_top = 5;
|
||||
navigation_view_steps.margin_start = 5;
|
||||
navigation_view_steps.margin_end = 5;
|
||||
|
||||
|
||||
// handle moving around the navigation view
|
||||
online_button.clicked.connect(() => {
|
||||
navigation_view_steps.push(online_page);
|
||||
next_button.show();
|
||||
next_button.sensitive = false;
|
||||
steps_state = "online";
|
||||
terminal.spawn_async(Vte.PtyFlags.DEFAULT,
|
||||
settings.get_string("song-folder"),
|
||||
{"bash"},
|
||||
null,
|
||||
GLib.SpawnFlags.DO_NOT_REAP_CHILD,
|
||||
() => {
|
||||
|
||||
},
|
||||
30,
|
||||
GLib.Cancellable.get_current(),
|
||||
(vterm, gid) => {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// check if there is a folder for the songs to be stored
|
||||
if (this.settings.get_string("song-folder").length == 0) {
|
||||
song_folder_button_content.set_label("Set download directory");
|
||||
song_folder_button.add_css_class("suggested-action");
|
||||
online_button.set_sensitive(false);
|
||||
import_button.set_sensitive(false);
|
||||
} else {
|
||||
song_folder_button_content.set_label(settings.get_string("song-folder"));
|
||||
settings.changed.connect(() => {
|
||||
song_folder_button_content.set_label(settings.get_string("song-folder"));
|
||||
});
|
||||
}
|
||||
|
||||
download.connect(() => {
|
||||
navigation_view_steps.push(downloading_page);
|
||||
|
||||
string command = "yt-dlp " + "-x -o " + song_title + " --audio-format mp3 " + "'" + song_url + "' \nexit \n"; // \n makes sure that the terminal presses enter after receiving the command
|
||||
print(command);
|
||||
|
||||
|
||||
terminal.feed_child(command.data);
|
||||
terminal.set_input_enabled(false);
|
||||
terminal.child_exited.connect(() => {
|
||||
|
||||
Settings _list = new Settings("com.liyaowhen.Song.playlists");
|
||||
//Check if the song created had no errors
|
||||
bool file_valid = true;
|
||||
try {
|
||||
var file = File.new_for_path(settings.get_string("song-folder") + "/" + song_title + ".mp3");
|
||||
print("file is \n" + settings.get_string("song-folder") + "/" + song_title + ".mp3");
|
||||
file.read();
|
||||
} catch (GLib.Error e) {
|
||||
print(e.message);
|
||||
file_valid = false;
|
||||
}
|
||||
|
||||
if (file_valid) {
|
||||
if (SongController.main_view_content == null) return;
|
||||
var main_content = SongController.main_view_content;
|
||||
string[] _string_array = _list.get_strv(main_content.current_playlist);
|
||||
_string_array += song_title;
|
||||
_list.set_strv(main_content.current_playlist, _string_array);
|
||||
foreach(string str in _list.get_strv(main_content.current_playlist)) {
|
||||
print("this playlist has \n" + str);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO implement error page
|
||||
navigation_view_steps.push(complete_page);
|
||||
|
||||
size_t length;
|
||||
|
||||
print(settings.get_value("songs").dup_string(out length));
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/com/liyaowhen/Song">
|
||||
<file preprocess="xml-stripblanks">window.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
|
||||
<file preprocess="xml-stripblanks">icons/globe-alt2-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks">icons/arrow-into-box-symbolic.svg</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
You can type here any CSS rule recognized by GTK.
|
||||
You can temporarily disable this custom CSS by clicking on the “Pause” button above.
|
||||
|
||||
Changes are applied instantly and globally, for the whole application.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
window {
|
||||
background: rgb(238,174,202);
|
||||
background: linear-gradient(200deg, rgba(238,174,202,1) 0%, rgba(148,187,233,1) 100%);
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
|
||||
}
|
||||
|
||||
navigation-split-view widget.sidebar-pane {
|
||||
background-color: alpha(rgb(255,255,255), 0.1);
|
||||
outline: 0;
|
||||
border-radius: 5px;
|
||||
margin-left: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
label {
|
||||
filter: none;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
namespace Song {
|
||||
public class MainView : Adw.NavigationPage {
|
||||
private Window window;
|
||||
|
||||
public Settings settings = new Settings("com.liyaowhen.Song.playlists");
|
||||
public MainViewContent main_content;
|
||||
public string current_playlist;
|
||||
|
||||
public MainView(Window _window) {
|
||||
this.window = _window;
|
||||
}
|
||||
|
||||
construct {
|
||||
|
||||
// make ui
|
||||
var toolbar_view = new Adw.ToolbarView ();
|
||||
|
||||
var scrollable = new Gtk.ScrolledWindow();
|
||||
main_content = new MainViewContent();
|
||||
scrollable.set_child(main_content);
|
||||
scrollable.hexpand = true;
|
||||
scrollable.hexpand_set = true;
|
||||
|
||||
var action_bar = new MainViewActionBar (main_content);
|
||||
|
||||
var controls = new SongControls();
|
||||
|
||||
toolbar_view.add_top_bar (action_bar);
|
||||
toolbar_view.set_content(scrollable);
|
||||
toolbar_view.add_bottom_bar (controls);
|
||||
|
||||
this.child = toolbar_view;
|
||||
this.title = "main_view";
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class MainViewActionBar : Gtk.Box {
|
||||
private Gtk.ActionBar action_bar;
|
||||
private MainViewContent main_view;
|
||||
|
||||
public MainViewActionBar (MainViewContent _main_view) {
|
||||
this.main_view = _main_view;
|
||||
}
|
||||
|
||||
construct {
|
||||
orientation = Gtk.Orientation.HORIZONTAL;
|
||||
action_bar = new Gtk.ActionBar();
|
||||
|
||||
|
||||
|
||||
|
||||
action_bar.vexpand = true;
|
||||
action_bar.hexpand = true;
|
||||
append(action_bar);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void new_music_popover_show() {
|
||||
var popover = new NewMusicPopover();
|
||||
popover.present(this);
|
||||
}
|
||||
}
|
||||
|
||||
public class MainViewContent : Gtk.Box {
|
||||
|
||||
private Settings settings = new Settings("com.liyaowhen.Song.playlists");
|
||||
private Adw.NavigationView navigation_view;
|
||||
public string current_playlist;
|
||||
|
||||
public MainViewContent() {
|
||||
vexpand = true;
|
||||
hexpand = true;
|
||||
print("loading empty ui");
|
||||
navigation_view = new Adw.NavigationView();
|
||||
append(navigation_view);
|
||||
navigation_view.vexpand = true;
|
||||
navigation_view.hexpand = true;
|
||||
|
||||
}
|
||||
|
||||
construct {
|
||||
SongController.main_view_content = this;
|
||||
}
|
||||
|
||||
public void change_page(string playlist_name) {
|
||||
print("change page called");
|
||||
|
||||
bool isKeyValid = false;
|
||||
foreach (string key in settings.list_keys()){
|
||||
if (key == playlist_name) {
|
||||
print("valid playlist");
|
||||
isKeyValid = true;
|
||||
}
|
||||
}
|
||||
if (!isKeyValid) {
|
||||
print("invalid playlist_name");
|
||||
return;
|
||||
}
|
||||
|
||||
current_playlist = playlist_name;
|
||||
|
||||
string[] songs = settings.get_strv(playlist_name);
|
||||
print("\n playlist contains: \n" + songs[1]);
|
||||
if (songs.length == 1) {
|
||||
if (songs[0] == "") {empty_playlist_ui(playlist_name); return;}
|
||||
else {
|
||||
//
|
||||
}
|
||||
} else if (songs.length > 1) {
|
||||
if (songs[1] != null) {
|
||||
print("making a page with actual content");
|
||||
playlist_ui(playlist_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void empty_playlist_ui(string playlist_name) {
|
||||
var empty_page = new Adw.StatusPage();
|
||||
var parent_page = new Adw.NavigationPage(empty_page,"no songs added");
|
||||
empty_page.set_title("Empty Playlist " + playlist_name);
|
||||
empty_page.set_icon_name("edit-find-symbolic");
|
||||
empty_page.set_description("Click the button on the top left to add songs in this playlist.");
|
||||
navigation_view.push(parent_page);
|
||||
}
|
||||
|
||||
private void playlist_ui(string playlist_name) {
|
||||
var playlist_page = new Adw.StatusPage();
|
||||
playlist_page.set_title(playlist_name);
|
||||
playlist_page.set_icon_name("emblem-music-symbolic");
|
||||
|
||||
load_music(playlist_page, playlist_name);
|
||||
|
||||
var parent_page = new Adw.NavigationPage(playlist_page, playlist_name);
|
||||
navigation_view.push(parent_page);
|
||||
}
|
||||
|
||||
private void load_music(Adw.StatusPage page, string playlist_name) {
|
||||
Adw.Clamp clamp = new Adw.Clamp();
|
||||
Gtk.ListBox content = new Gtk.ListBox();
|
||||
foreach (string i in settings.get_strv(playlist_name)) {
|
||||
if (i != "") {
|
||||
content.append(new MusicListRow(i));
|
||||
}
|
||||
}
|
||||
clamp.child = content;
|
||||
page.child = clamp;
|
||||
content.hexpand = true;
|
||||
}
|
||||
|
||||
/*private Gtk.WidgetPaintable playlist_cover(string playlist_name) {
|
||||
Gtk.WidgetPaintable paintable = new Gtk.WidgetPaintable();
|
||||
return paintable;
|
||||
} */
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
namespace Song {
|
||||
public class MusicListRow : Gtk.Box {
|
||||
|
||||
private Settings settings = new Settings("com.liyaowhen.Song.playlists");
|
||||
public string song_name;
|
||||
|
||||
public MusicListRow (string _song_name) {
|
||||
this.song_name = _song_name;
|
||||
build_ui();
|
||||
}
|
||||
|
||||
construct {
|
||||
|
||||
margin_bottom = 5;
|
||||
margin_top = 5;
|
||||
margin_start = 5;
|
||||
margin_end = 5;
|
||||
vexpand = true;
|
||||
hexpand = true;
|
||||
vexpand_set = true;
|
||||
hexpand_set = true;
|
||||
orientation = Gtk.Orientation.HORIZONTAL;
|
||||
}
|
||||
|
||||
private void build_ui() {
|
||||
var label = new Gtk.Label (song_name);
|
||||
print(song_name + "making playlists song button");
|
||||
label.hexpand = true;
|
||||
append(label);
|
||||
|
||||
var play_button = new Gtk.Button.from_icon_name ("media-playback-start-symbolic");
|
||||
play_button.hexpand = false;
|
||||
play_button.add_css_class("flat");
|
||||
|
||||
play_button.clicked.connect(() => {
|
||||
if (SongController.song_controls.current_song != song_name) {
|
||||
SongController.song_controls.change_song(song_name);
|
||||
play_button.icon_name = "media-playback-pause-symbolic";
|
||||
Timeout.add(1, () => {
|
||||
if (SongController.song_controls.current_song != song_name) {
|
||||
// when another song is called to play, reset the button state
|
||||
play_button.icon_name = "media-playback-start-symbolic";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
} else if (SongController.song_controls.isPlaying) {
|
||||
SongController.song_controls.pause();
|
||||
play_button.icon_name = "media-playback-start-symbolic";
|
||||
} else if (!SongController.song_controls.isPlaying) {
|
||||
SongController.song_controls.play();
|
||||
play_button.icon_name = "media-playback-pause-symbolic";
|
||||
}
|
||||
});
|
||||
|
||||
append(play_button);
|
||||
|
||||
|
||||
spacing = 5;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
namespace Song {
|
||||
public class Playlist : Gtk.Button {
|
||||
|
||||
private Settings settings = new Settings ("com.liyaowhen.Song");
|
||||
|
||||
public signal void removal_mode();
|
||||
public signal void exit_removal_mode();
|
||||
|
||||
private string playlist_name;
|
||||
|
||||
public Playlist (string _playlist_name) {
|
||||
this.playlist_name = _playlist_name;
|
||||
|
||||
initialize();
|
||||
}
|
||||
|
||||
construct {
|
||||
hexpand = true;
|
||||
|
||||
clicked.connect(() => {
|
||||
//assumes that main_view is already instanciated
|
||||
SongController.main_view_content.change_page(playlist_name);
|
||||
});
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
set_label(playlist_name);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
namespace Song {
|
||||
|
||||
public class SideBar : Adw.NavigationPage {
|
||||
|
||||
private Settings settings = new Settings("com.liyaowhen.Song");
|
||||
private Window window;
|
||||
|
||||
public SideBarContent side_bar_content;
|
||||
public SideBarControls side_bar_controls;
|
||||
|
||||
|
||||
|
||||
public SideBar(Window _window) {
|
||||
this.window = _window;
|
||||
}
|
||||
|
||||
construct {
|
||||
|
||||
var toolbar_view = new Adw.ToolbarView();
|
||||
|
||||
var scroll_box = new Gtk.ScrolledWindow();
|
||||
side_bar_content = new SideBarContent ();
|
||||
side_bar_content.set_vexpand (true);
|
||||
side_bar_content.set_hexpand (true);
|
||||
scroll_box.child = side_bar_content;
|
||||
|
||||
side_bar_controls = new SideBarControls (side_bar_content);
|
||||
side_bar_controls.set_hexpand (true);
|
||||
|
||||
toolbar_view.set_content(scroll_box);
|
||||
toolbar_view.add_bottom_bar(side_bar_controls);
|
||||
|
||||
title = "Songs:";
|
||||
this.child = toolbar_view;
|
||||
}
|
||||
}
|
||||
|
||||
public class SideBarContent : Gtk.Box {
|
||||
|
||||
private Settings settings = new Settings("com.liyaowhen.Song.playlists");
|
||||
public List<Playlist> playlists;
|
||||
private MainView main_view;
|
||||
|
||||
public SideBarContent() {
|
||||
}
|
||||
|
||||
construct {
|
||||
orientation = Gtk.Orientation.VERTICAL;
|
||||
valign = Gtk.Align.START;
|
||||
|
||||
|
||||
spacing = 5;
|
||||
margin_bottom = 5;
|
||||
margin_top = 5;
|
||||
margin_start = 5;
|
||||
margin_end = 5;
|
||||
|
||||
vexpand = true;
|
||||
hexpand = true;
|
||||
vexpand_set = true;
|
||||
hexpand_set = true;
|
||||
|
||||
Playlist initial_playlist;
|
||||
|
||||
var playlist_names = settings.get_strv("playlists");
|
||||
foreach (string _name in playlist_names) {
|
||||
var playlist = new Playlist(_name);
|
||||
if (_name == playlist_names[0]) {
|
||||
initial_playlist = playlist;
|
||||
}
|
||||
playlists.append(playlist);
|
||||
append(playlist);
|
||||
}
|
||||
|
||||
print("sidbar requesting main_view_content switch to playlist of name:\n" + playlist_names[1]);
|
||||
Timeout.add(1, () => {
|
||||
if (SongController.main_view_content != null) {
|
||||
SongController.main_view_content.change_page(playlist_names[0]);
|
||||
return false;
|
||||
|
||||
}
|
||||
return true;
|
||||
}, 1);
|
||||
SongController.sidebar_content = this;
|
||||
|
||||
//reconfigure_playlist_button_group(); DOES NOT WORK FOR SOME REASON
|
||||
|
||||
}
|
||||
|
||||
/*private void reconfigure_playlist_button_group() {
|
||||
foreach (Playlist i in playlists) {
|
||||
foreach (Playlist j in playlists) {
|
||||
if (i != j) {
|
||||
i.set_group(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class SideBarControls : Gtk.Box {
|
||||
|
||||
private SideBarContent sidebar_content;
|
||||
private Gtk.ActionBar action_bar;
|
||||
|
||||
|
||||
public SideBarControls(SideBarContent _sidebar_content) {
|
||||
this.sidebar_content = _sidebar_content;
|
||||
|
||||
}
|
||||
|
||||
construct {
|
||||
action_bar = new Gtk.ActionBar();
|
||||
action_bar.vexpand = true;
|
||||
action_bar.hexpand = true;
|
||||
append(action_bar);
|
||||
|
||||
this.orientation = Gtk.Orientation.HORIZONTAL;
|
||||
this.add_css_class ("toolbar");
|
||||
|
||||
// make ui
|
||||
var select_button = new Gtk.ToggleButton();
|
||||
select_button.set_icon_name ("checkbox-symbolic");
|
||||
var delete_button = new Gtk.Button();
|
||||
delete_button.set_icon_name ("user-trash-symbolic");
|
||||
var export_button = new Gtk.Button();
|
||||
export_button.set_icon_name("document-save-symbolic");
|
||||
|
||||
var options_button = new Gtk.Button(); // TODO: change to Gtk.MenuButton
|
||||
options_button.set_icon_name("open-menu-symbolic");
|
||||
options_button.sensitive = true;
|
||||
|
||||
action_bar.pack_start(select_button);
|
||||
//action_bar.set_center_widget(empty_spacer());
|
||||
action_bar.pack_end(options_button);
|
||||
|
||||
|
||||
// signals
|
||||
|
||||
}
|
||||
|
||||
private Gtk.Separator empty_spacer() {
|
||||
var empty_spacer = new Gtk.Separator(Gtk.Orientation.VERTICAL);
|
||||
empty_spacer.hexpand = true;
|
||||
empty_spacer.add_css_class("spacer");
|
||||
return empty_spacer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
using Gst;
|
||||
|
||||
|
||||
namespace Song {
|
||||
public class SongControls : Gtk.Box {
|
||||
|
||||
private Settings songs_list = new Settings("com.liyaowhen.Song.playlists");
|
||||
private Settings settings = new Settings("com.liyaowhen.Song");
|
||||
|
||||
public Gtk.Scale progress_bar;
|
||||
public Gtk.Adjustment progress_bar_adjustment;
|
||||
private bool isDragging;
|
||||
|
||||
public bool isPlaying;
|
||||
public string current_song;
|
||||
|
||||
|
||||
public Gst.Element playbin;
|
||||
|
||||
public SongControls() {
|
||||
playbin = Gst.ElementFactory.make("playbin", "player");
|
||||
}
|
||||
|
||||
construct {
|
||||
// Gstreamer stuff
|
||||
isPlaying = false;
|
||||
// UI
|
||||
orientation = Gtk.Orientation.VERTICAL;
|
||||
vexpand = false;
|
||||
hexpand = true;
|
||||
hexpand_set = true;
|
||||
|
||||
progress_bar_adjustment = new Gtk.Adjustment(0, 0, 1, 1, 1, 0);
|
||||
progress_bar = new Gtk.Scale(Gtk.Orientation.HORIZONTAL, progress_bar_adjustment);
|
||||
progress_bar.set_draw_value(false);
|
||||
|
||||
|
||||
Timeout.add(1, () => {
|
||||
|
||||
if (playbin != null && isDragging != true) {
|
||||
var position = (int64) 0;
|
||||
var duration = (int64) 0;
|
||||
|
||||
// Query the current position and duration
|
||||
if (playbin.query_position(Format.TIME, out position) &&
|
||||
playbin.query_duration(Format.TIME, out duration)) {
|
||||
progress_bar.set_range(0, (double) duration / Gst.SECOND);
|
||||
progress_bar.set_value((double) position / Gst.SECOND);
|
||||
}
|
||||
}
|
||||
//print("running");
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
uint timeout_id = 0;
|
||||
|
||||
progress_bar.change_value.connect((range) => {
|
||||
|
||||
if (timeout_id != 0) {
|
||||
try {
|
||||
Source.remove(timeout_id);
|
||||
} catch (GLib.Error e) {
|
||||
// the function above often complains
|
||||
}
|
||||
}
|
||||
|
||||
isDragging = true;
|
||||
if (playbin != null) {
|
||||
var seek_time = (int64)(progress_bar.get_value() * Gst.SECOND);
|
||||
playbin.seek_simple(Format.TIME, SeekFlags.FLUSH | SeekFlags.KEY_UNIT, seek_time);
|
||||
}
|
||||
|
||||
timeout_id = Timeout.add(50, () => {
|
||||
|
||||
isDragging = false;
|
||||
|
||||
return false;
|
||||
});
|
||||
}); // emitted when user (not program) changes the scale
|
||||
|
||||
progress_bar.value_changed.connect((range) => {
|
||||
|
||||
});
|
||||
|
||||
|
||||
append(progress_bar);
|
||||
|
||||
// add controls to control the music
|
||||
music_controls();
|
||||
|
||||
SongController.song_controls = this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void music_controls() {
|
||||
var clamp = new Adw.Clamp();
|
||||
|
||||
var box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 5);
|
||||
box.hexpand = true;
|
||||
box.halign = Gtk.Align.CENTER;
|
||||
box.margin_bottom = 10;
|
||||
|
||||
var play_button = new Gtk.Button.from_icon_name("media-playback-start-symbolic");
|
||||
play_button.halign = Gtk.Align.CENTER;
|
||||
|
||||
Timeout.add(1, () => {
|
||||
if (isPlaying == true) {
|
||||
play_button.set_icon_name("media-playback-pause-symbolic");
|
||||
} else {
|
||||
play_button.set_icon_name("media-playback-start-symbolic");
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
play_button.clicked.connect(() => {
|
||||
if (isPlaying) pause();
|
||||
else play();
|
||||
});
|
||||
|
||||
box.append(play_button);
|
||||
|
||||
play_button.clicked.connect(() => {
|
||||
play_music();
|
||||
});
|
||||
|
||||
clamp.child = box;
|
||||
|
||||
append(clamp);
|
||||
}
|
||||
|
||||
private void play_music() {
|
||||
if (current_song != null) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void play() {
|
||||
playbin.set_state(Gst.State.PLAYING);
|
||||
isPlaying = true;
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
playbin.set_state(Gst.State.PAUSED);
|
||||
isPlaying = false;
|
||||
}
|
||||
|
||||
public void change_song(string song) {
|
||||
print("song is now " + song + "\n");
|
||||
current_song = song;
|
||||
string file_path = "file://" + settings.get_string("song-folder") + "/" + current_song + ".mp3";
|
||||
print("song full path is " + file_path);
|
||||
playbin.set_state(Gst.State.NULL);
|
||||
playbin.set_property("uri", file_path);
|
||||
playbin.set_state(Gst.State.PLAYING);
|
||||
isPlaying = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<requires lib="Adw" version="1.0"/>
|
||||
<template class="SongWindow" parent="AdwApplicationWindow">
|
||||
<property name="default-width">600</property>
|
||||
<property name="default-height">300</property>
|
||||
<property name="content">
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar" id="header_bar">
|
||||
<child type="end">
|
||||
<object class="GtkMenuButton">
|
||||
<property name="primary">True</property>
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
<property name="tooltip-text" translatable="yes">Menu</property>
|
||||
<property name="menu-model">primary_menu</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<property name="content">
|
||||
<object class="GtkLabel" id="label">
|
||||
<property name="label">Hello, World!</property>
|
||||
<style>
|
||||
<class name="title-1"/>
|
||||
</style>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
<menu id="primary_menu">
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Preferences</attribute>
|
||||
<attribute name="action">app.preferences</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
|
||||
<attribute name="action">win.show-help-overlay</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_About Song</attribute>
|
||||
<attribute name="action">app.about</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</menu>
|
||||
</interface>
|
||||
@@ -0,0 +1,85 @@
|
||||
namespace Song {
|
||||
public class Window : Adw.ApplicationWindow {
|
||||
|
||||
|
||||
private Settings settings = new Settings ("com.liyaowhen.Song");
|
||||
public SideBar sidebar;
|
||||
public MainView main_view;
|
||||
|
||||
public Window (Gtk.Application app) {
|
||||
Object (application: app);
|
||||
}
|
||||
|
||||
construct {
|
||||
|
||||
var gesture = new Gtk.GestureDrag();
|
||||
|
||||
var provider = new Gtk.CssProvider();
|
||||
provider.load_from_path("style.css");
|
||||
|
||||
this.get_style_context().add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
|
||||
// GSettings
|
||||
this.settings.bind ("window-width", this, "default-width", SettingsBindFlags.DEFAULT);
|
||||
this.settings.bind ("window-height", this, "default-height", SettingsBindFlags.DEFAULT);
|
||||
this.settings.bind ("window-maximized", this, "maximized", SettingsBindFlags.DEFAULT);
|
||||
|
||||
// UI
|
||||
var title_bar = new Adw.HeaderBar ();
|
||||
//title_bar.set_decoration_layout("icon:close");
|
||||
title_bar.show_title = false;
|
||||
|
||||
var add_button = new Gtk.Button();
|
||||
var add_button_content = new Adw.ButtonContent ();
|
||||
add_button_content.set_icon_name("tab-new-symbolic");
|
||||
add_button_content.set_label("new song");
|
||||
add_button_content.set_parent(add_button);
|
||||
|
||||
add_button.clicked.connect(() => {
|
||||
new_music_popover_show();
|
||||
});
|
||||
|
||||
var collapse_button = new Gtk.Button.from_icon_name ("folder-open-symbolic");
|
||||
title_bar.pack_start (collapse_button);
|
||||
title_bar.pack_start(add_button);
|
||||
|
||||
|
||||
|
||||
main_view = new MainView(this);
|
||||
sidebar = new SideBar(this);
|
||||
|
||||
var split_view = new Adw.NavigationSplitView ();
|
||||
split_view.set_sidebar (sidebar);
|
||||
split_view.set_content(main_view);
|
||||
split_view.show_content = true;
|
||||
|
||||
|
||||
var _content = new Adw.ToolbarView ();
|
||||
_content.add_top_bar (title_bar);
|
||||
_content.set_content (split_view);
|
||||
|
||||
_content.add_controller(gesture);
|
||||
SongController.gesture = gesture;
|
||||
|
||||
collapse_button.clicked.connect(() => {
|
||||
if(split_view.get_collapsed ()){
|
||||
split_view.set_collapsed (false);
|
||||
collapse_button.set_icon_name("folder-open-symbolic");
|
||||
} else {
|
||||
split_view.set_collapsed(true);
|
||||
collapse_button.set_icon_name("folder-symbolic");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
set_content(_content);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void new_music_popover_show() {
|
||||
var popover = new NewMusicPopover();
|
||||
popover.present(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user