diff --git a/data/Application.css b/data/Application.css index 749802e..ff4d984 100644 --- a/data/Application.css +++ b/data/Application.css @@ -13,14 +13,14 @@ } /* Window and titlebar inactive */ -.lyrics:backdrop, -.lyrics:backdrop .titlebar { +.lyrics:backdrop.translucid-backdrop, +.lyrics:backdrop.translucid-backdrop .titlebar { color: #0c0c0c; background: rgba(255, 255, 255, 0.25); } -.lyrics.dark:backdrop, -.lyrics.dark:backdrop .titlebar { +.lyrics.dark:backdrop.translucid-backdrop, +.lyrics.dark:backdrop.translucid-backdrop .titlebar { color: #fff; background: rgba(0, 0, 0, 0.5); } diff --git a/data/com.github.naaando.lyrics.gschema.xml b/data/com.github.naaando.lyrics.gschema.xml index c7a45ec..7ac0a11 100644 --- a/data/com.github.naaando.lyrics.gschema.xml +++ b/data/com.github.naaando.lyrics.gschema.xml @@ -16,5 +16,22 @@ Most recent y position Most recent y position + + + + + + + 'When playing' + Keep the window on the top + + + true + Set window's opacity low when it goes out of focus + + + '' + Location to download and search for lyrics + diff --git a/meson.build b/meson.build index bb26a18..61d81bf 100644 --- a/meson.build +++ b/meson.build @@ -17,7 +17,6 @@ executable( meson.project_name (), asresources, 'src/Controller/DisplayController.vala', - 'src/Controller/StackController.vala', 'src/Core/Factory/MetasongFactory.vala', 'src/Core/Lyric.vala', 'src/Core/Metasong.vala', @@ -35,14 +34,18 @@ executable( 'src/Mpris/MprisPlayer.vala', 'src/Mpris/MprisService.vala', 'src/Parser/LRC-Parser.vala', + 'src/View/HeaderBar.vala', + 'src/View/MainStack.vala', + 'src/View/MainWindow.vala', + 'src/View/SettingsPopover.vala', 'src/Widgets/Displays/IDisplay.vala', 'src/Widgets/Displays/SimpleDisplay.vala', 'src/Widgets/Displays/ScrolledDisplay.vala', 'src/Widgets/Download.vala', + 'src/Widgets/FileChooserButton.vala', 'src/Widgets/ModeSwitch.vala', 'src/Widgets/SearchLyric.vala', 'src/Application.vala', - 'src/MainWindow.vala', 'src/SimplePlayer.vala', dependencies: [ dependency ('glib-2.0'), diff --git a/src/Application.vala b/src/Application.vala index 8b93eeb..66c4bf7 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -1,14 +1,14 @@ public class Lyrics.Application : Gtk.Application { - public static GLib.Settings settings; + public static string DEFAULT_LYRICS_DIR = Environment.get_home_dir ()+"/.lyrics/"; + public static GLib.Settings settings = new Settings ("com.github.naaando.lyrics"); public Application () { Object (application_id: "com.github.naaando.lyrics", flags: ApplicationFlags.FLAGS_NONE); - } - - static construct { - settings = new Settings ("com.github.naaando.lyrics"); + if (settings.get_string ("download-location") == "") { + settings.set_string ("download-location", DEFAULT_LYRICS_DIR); + } } protected override void activate () { @@ -19,15 +19,12 @@ public class Lyrics.Application : Gtk.Application { var players = new Players (); - var stack_controller = new Controller.StackController (players); - var scanner = new Mpris.Service (); scanner.found.connect ((player) => players.add (player)); scanner.lost.connect (players.remove_by_busname); scanner.setup_dbus (); - var main_window = new MainWindow (this, stack_controller.get_stack ()); - main_window.players = players; + var main_window = new MainWindow (this, players, new MainStack (players)); var window_x = settings.get_int ("window-x"); var window_y = settings.get_int ("window-y"); diff --git a/src/Controller/StackController.vala b/src/Controller/StackController.vala deleted file mode 100644 index 2312da3..0000000 --- a/src/Controller/StackController.vala +++ /dev/null @@ -1,102 +0,0 @@ - -public class Lyrics.Controller.StackController : Object { - Players players; - Gtk.Stack stack; - DisplayController display_controller = new DisplayController (); - - public StackController (Players _players) { - var download = new Download (); - stack = factory_gtk_stack (display_controller.display, download); - - players = _players; - - // FIXME: Signal not working outside thread - new Thread ("players-signals",() => { - var loop = new MainLoop (); - players.notify["active-player"].connect (() => { - if (players.active_player != null) { - players.active_player.notify.connect (() => { - update_stack (); - }); - } - update_stack (); - }); - - loop.run (); - - return 0; - }); - } - - public void update_stack () { - if (players.active_player == null) { - stack.visible_child_name = "NO_PLAYER"; - return; - } - - if (players.active_player.state.to_string () == "PLAYING") { - display_controller.start (players.active_player) ? stack.visible_child_name = players.active_player.state.to_string () : stack.visible_child_name = "NO_LYRICS"; - } else { - display_controller.stop (); - stack.visible_child_name = "STOPPED"; - } - } - - public Gtk.Stack get_stack () { - return stack; - } - - private Gtk.Stack factory_gtk_stack (IDisplay display, Download download) { - var stack = new Gtk.Stack (); - stack.transition_type = Gtk.StackTransitionType.CROSSFADE; - stack.border_width = 24; - stack.margin = 6; - stack.expand = true; - - var context = stack.get_style_context (); - context.add_class ("stack"); - - stack.add_named (build_no_player (), "NO_PLAYER"); - stack.add_named (build_not_playing (), "STOPPED"); - stack.add_named (display_controller.display, "PLAYING"); - stack.add_named (download, "DOWNLOADING"); - stack.add_named (build_no_lyrics (), "NO_LYRICS"); - return stack; - } - - private Gtk.Box build_no_player () { - var label = new Gtk.Label ("Couldn't find any player, check your player's MPRIS configuration"); - label.wrap = true; - label.get_style_context ().add_class ("description"); - - var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); - box.valign = Gtk.Align.CENTER; - box.add (label); - - return box; - } - - private Gtk.Box build_not_playing () { - var label = new Gtk.Label ("Currently not playing"); - label.wrap = true; - label.get_style_context ().add_class ("description"); - - var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); - box.valign = Gtk.Align.CENTER; - box.add (label); - - return box; - } - - private Gtk.Box build_no_lyrics () { - var label = new Gtk.Label ("Couldn't find lyrics for song"); - label.wrap = true; - label.get_style_context ().add_class ("description"); - - var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); - box.valign = Gtk.Align.CENTER; - box.add (label); - - return box; - } -} diff --git a/src/MainWindow.vala b/src/MainWindow.vala deleted file mode 100644 index 0a0b074..0000000 --- a/src/MainWindow.vala +++ /dev/null @@ -1,156 +0,0 @@ - -public class Lyrics.MainWindow : Gtk.ApplicationWindow { - public Players players { - get { - return _players; - } - set { - _players = value; - connect_to_playpause (players); - } - } - - Player active_player { - get { - return (players == null) ? null : players.active_player; - } - } - - Players _players; - Gtk.Button playpause; - - public MainWindow (Gtk.Application application, Gtk.Stack stack) { - Object ( - application: application, - icon_name: "com.github.naaando.lyrics", - resizable: true, - title: _("Lyrics"), - window_position: Gtk.WindowPosition.CENTER - ); - - var context = get_style_context (); - context.add_class ("rounded"); - context.add_class ("lyrics"); - - var provider = new Gtk.CssProvider (); - provider.load_from_resource ("/com/github/naaando/lyrics/Application.css"); - Gtk.StyleContext.add_provider_for_screen (Gdk.Screen.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - - set_titlebar (generate_header ()); - set_keep_above (true); - stick (); - - add (stack); - } - - Gtk.HeaderBar generate_header () { - var header = new Gtk.HeaderBar (); - header.decoration_layout = "close:menu"; - header.show_close_button = true; - var header_context = header.get_style_context (); - header_context.add_class ("titlebar"); - header_context.add_class ("default-decoration"); - - var mode_switch = new ModeSwitch ( - "display-brightness-symbolic", - "weather-clear-night-symbolic" - ); - mode_switch.margin_end = 6; - mode_switch.primary_icon_tooltip_text = _("Light background"); - mode_switch.secondary_icon_tooltip_text = _("Dark background"); - mode_switch.valign = Gtk.Align.CENTER; - - var gtk_settings = Gtk.Settings.get_default (); - mode_switch.bind_property ("active", gtk_settings, "gtk_application_prefer_dark_theme"); - mode_switch.notify["active"].connect (() => { - var context = get_style_context (); - if (gtk_settings.gtk_application_prefer_dark_theme) { - context.add_class ("dark"); - } else { - context.remove_class ("dark"); - } - }); - - Application.settings.bind ("dark", mode_switch, "active", GLib.SettingsBindFlags.DEFAULT); - - /** - * Left side of headerbar - */ - - /* Player controls */ - // Previous music button - header.pack_start (build_button_from_icon ("media-skip-backward-symbolic", null, (btn) => { - if (active_player != null) { - active_player.previous (); - } - })); - - // Play/Pause button - playpause = build_button_from_icon ("media-playback-start-symbolic", null, (btn) => { - if (active_player != null) { - active_player.toggle_play_pause (); - } - }); - header.pack_start (playpause); - - // Next music button - header.pack_start (build_button_from_icon ("media-skip-forward-symbolic", null, (btn) => { - if (active_player != null) { - active_player.next (); - } - })); - - - /** - * Right side of headerbar - */ - - // Switch color button - header.pack_end (mode_switch); - return header; - } - - Gtk.Button build_button_from_icon (string icon_name, string? tooltip = null, Func? clicked_cb = null) { - var button = new Gtk.Button.from_icon_name (icon_name); - - if (tooltip != null) { - button.tooltip_text = tooltip; - } - - if (clicked_cb != null) { - button.clicked.connect (() => clicked_cb (button)); - } - - return button; - } - - void connect_to_playpause (Players plrs) { - update_playpause_icon (plrs); - - // Update play/pause button - plrs.notify["active-player"].connect (() => { - if (plrs.active_player == null) { - return; - } - - update_playpause_icon (plrs); - plrs.active_player.notify.connect (() => { - update_playpause_icon (plrs); - }); - }); - } - - void update_playpause_icon (Players plrs) { - var path = (plrs.active_player != null && plrs.active_player.state != PAUSED) ? "media-playback-pause-symbolic" : "media-playback-start-symbolic"; - playpause.image = new Gtk.Image.from_icon_name (path, Gtk.IconSize.SMALL_TOOLBAR); - } - - public override bool configure_event (Gdk.EventConfigure event) { - int root_x, root_y; - get_position (out root_x, out root_y); - Application.settings.set_int ("window-x", root_x); - Application.settings.set_int ("window-y", root_y); - - return base.configure_event (event); - } -} diff --git a/src/Repository/Local/LocalRepository.vala b/src/Repository/Local/LocalRepository.vala index eafcd58..5b24615 100644 --- a/src/Repository/Local/LocalRepository.vala +++ b/src/Repository/Local/LocalRepository.vala @@ -1,6 +1,6 @@ public class Lyrics.LocalRepository : IRepository, Object { - string local_storage = Environment.get_home_dir ()+"/.lyrics/"; + public string local_storage { get; set; default = Environment.get_home_dir ()+"/.lyrics/"; } public bool save (Metasong song, ILyricFile lyric_file) { var file = File.new_for_path (local_storage+get_filename_for_song (song)); diff --git a/src/Repository/Repository.vala b/src/Repository/Repository.vala index 0b55790..cbe3a83 100644 --- a/src/Repository/Repository.vala +++ b/src/Repository/Repository.vala @@ -8,6 +8,9 @@ public class Lyrics.Repository : IRepository, Object { public Repository () { lyricsources["viewlyrics"] = new LyricSources.Repository (viewlyrics_dbus[0], viewlyrics_dbus[1]); + + Application.settings.changed["download-location"].connect (configure_download_local); + configure_download_local (); } public ILyricFile? find_first (Metasong song) { @@ -31,4 +34,10 @@ public class Lyrics.Repository : IRepository, Object { collection.add_all (lyricsources["viewlyrics"].find (song)); return collection; } + + void configure_download_local () { + var settings_location = Application.settings.get_string ("download-location"); + local_repository.local_storage = settings_location == "" ? Environment.get_home_dir ()+"/.lyrics/" : settings_location+"/"; + debug ("Setting local storage to " + local_repository.local_storage); + } } diff --git a/src/View/HeaderBar.vala b/src/View/HeaderBar.vala new file mode 100644 index 0000000..6e214e8 --- /dev/null +++ b/src/View/HeaderBar.vala @@ -0,0 +1,83 @@ +public class Lyrics.HeaderBar : Gtk.HeaderBar { + Gtk.Settings settings = Gtk.Settings.get_default (); + Gtk.Button play_n_pause_btn; + Players players; + + public HeaderBar (Players players) { + decoration_layout = "close:menu"; + show_close_button = true; + get_style_context ().add_class ("titlebar"); + get_style_context ().add_class ("default-decoration"); + players.notify["active-player"].connect (on_active_player_changes); + + var previous_btn = new Gtk.Button.from_icon_name ("media-skip-backward-symbolic"); + previous_btn.clicked.connect (on_previous_btn_clicked); + + play_n_pause_btn = new Gtk.Button.from_icon_name ("media-playback-start-symbolic"); + play_n_pause_btn.clicked.connect (on_play_n_pause_btn_clicked); + + var next_btn = new Gtk.Button.from_icon_name ("media-skip-forward-symbolic"); + next_btn.clicked.connect (on_next_btn_clicked); + + var settings = new Gtk.MenuButton (); + settings.image = new Gtk.Image.from_icon_name ("open-menu-symbolic", Gtk.IconSize.SMALL_TOOLBAR); + settings.popover = new SettingsPopover (); + + pack_start (previous_btn); + pack_start (play_n_pause_btn); + pack_start (next_btn); + + pack_end (settings); + pack_end (create_mode_switch ()); + } + + void update_play_n_pause_icon () { + var icon_name = (players.active_player == null || players.active_player.state != PAUSED) ? "media-playback-start-symbolic" : "media-playback-pause-symbolic"; + if (play_n_pause_btn != null) { + play_n_pause_btn.image = new Gtk.Image.from_icon_name (icon_name, Gtk.IconSize.SMALL_TOOLBAR); + } + } + + void on_active_player_changes () { + if (players == null | players.active_player == null) { + return; + } + + update_play_n_pause_icon (); + players.active_player.notify.connect (update_play_n_pause_icon); + } + + void on_previous_btn_clicked () { + if (players.active_player != null) { + players.active_player.previous (); + } + } + + void on_play_n_pause_btn_clicked () { + if (players.active_player != null) { + players.active_player.toggle_play_pause (); + } + } + + void on_next_btn_clicked () { + if (players.active_player != null) { + players.active_player.next (); + } + } + + Gtk.Widget create_mode_switch () { + var mode_switch = new ModeSwitch ( + "display-brightness-symbolic", + "weather-clear-night-symbolic" + ); + + mode_switch.margin_end = 6; + mode_switch.primary_icon_tooltip_text = _("Light background"); + mode_switch.secondary_icon_tooltip_text = _("Dark background"); + mode_switch.valign = Gtk.Align.CENTER; + mode_switch.bind_property ("active", settings, "gtk_application_prefer_dark_theme"); + Application.settings.bind ("dark", mode_switch, "active", GLib.SettingsBindFlags.DEFAULT); + + return mode_switch; + } +} diff --git a/src/View/MainStack.vala b/src/View/MainStack.vala new file mode 100644 index 0000000..c1596ae --- /dev/null +++ b/src/View/MainStack.vala @@ -0,0 +1,92 @@ +public class Lyrics.MainStack : Gtk.Stack { + public Gtk.Widget no_player_view { get;set; default = MainStack.build_no_player (); } + public Gtk.Widget not_playing_view { get; set; default = MainStack.build_not_playing (); } + public Gtk.Widget lyrics_not_found_view { get; set; default = MainStack.build_no_lyrics (); } + + public Gtk.Widget? lyrics_display { get; set; } + public Gtk.Widget? downloading_view { get; set; } + Controller.DisplayController display_controller = new Controller.DisplayController (); + Players players; + + public MainStack (Players _players) { + transition_type = Gtk.StackTransitionType.CROSSFADE; + border_width = 24; + margin = 6; + expand = true; + + get_style_context ().add_class ("stack"); + + lyrics_display = display_controller.display; + downloading_view = new Download (); + + add_named (no_player_view, "NO_PLAYER"); + add_named (not_playing_view, "STOPPED"); + add_named (lyrics_display, "PLAYING"); + add_named (downloading_view, "DOWNLOADING"); + add_named (lyrics_not_found_view, "NO_LYRICS"); + + players = _players; + + players.notify["active-player"].connect (on_active_player_change); + } + + void on_active_player_change () { + if (players.active_player != null) { + players.active_player.notify.connect (() => { + update_stack (); + }); + } + + update_stack (); + } + + public void update_stack () { + if (players.active_player == null) { + visible_child_name = "NO_PLAYER"; + return; + } + + if (players.active_player.state.to_string () == "PLAYING") { + display_controller.start (players.active_player) ? visible_child_name = players.active_player.state.to_string () : visible_child_name = "NO_LYRICS"; + } else { + display_controller.stop (); + visible_child_name = "STOPPED"; + } + } + + static Gtk.Box build_no_player () { + var label = new Gtk.Label ("Couldn't find any player, check your player's MPRIS configuration"); + label.wrap = true; + label.get_style_context ().add_class ("description"); + + var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); + box.valign = Gtk.Align.CENTER; + box.add (label); + + return box; + } + + static Gtk.Box build_not_playing () { + var label = new Gtk.Label ("Currently not playing"); + label.wrap = true; + label.get_style_context ().add_class ("description"); + + var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); + box.valign = Gtk.Align.CENTER; + box.add (label); + + return box; + } + + static Gtk.Box build_no_lyrics () { + var label = new Gtk.Label ("Couldn't find lyrics for song"); + label.wrap = true; + label.get_style_context ().add_class ("description"); + + var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); + box.valign = Gtk.Align.CENTER; + box.add (label); + + return box; + } +} diff --git a/src/View/MainWindow.vala b/src/View/MainWindow.vala new file mode 100644 index 0000000..cce2949 --- /dev/null +++ b/src/View/MainWindow.vala @@ -0,0 +1,99 @@ + +public class Lyrics.MainWindow : Gtk.ApplicationWindow { + Gtk.Stack main_stack; + Players players; + bool keep_above_when_playing; + + public MainWindow (Gtk.Application application, Players _players, Gtk.Stack stack) { + Object ( + application: application, + icon_name: "com.github.naaando.lyrics", + resizable: true, + title: _("Lyrics"), + window_position: Gtk.WindowPosition.CENTER + ); + + // Add css classes to main window + get_style_context ().add_class ("rounded"); + get_style_context ().add_class ("lyrics"); + + main_stack = stack; + players = _players; + + set_titlebar (new Lyrics.HeaderBar (players)); + + Application.settings.changed["window-keep-above"].connect (configure_window_keep_above_settings); + Application.settings.changed["window-out-of-focus-translucid"].connect (configure_window_opacity_on_focus_loss); + main_stack.notify["visible-child-name"].connect (on_stack_visible_child_changed); + + add (main_stack); + setup (); + } + + public override bool configure_event (Gdk.EventConfigure event) { + int root_x, root_y; + get_position (out root_x, out root_y); + Application.settings.set_int ("window-x", root_x); + Application.settings.set_int ("window-y", root_y); + + return base.configure_event (event); + } + + void setup () { + configure_dark_theme (); + configure_css_provider (); + configure_window_keep_above_settings (); + configure_window_opacity_on_focus_loss (); + stick (); + } + + void configure_css_provider () { + var provider = new Gtk.CssProvider (); + provider.load_from_resource ("/com/github/naaando/lyrics/Application.css"); + Gtk.StyleContext.add_provider_for_screen (Gdk.Screen.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + } + + void configure_dark_theme () { + update_dark_mode (); + Application.settings.changed["dark"].connect (update_dark_mode); + } + + void update_dark_mode () { + if (Application.settings.get_boolean ("dark")) { + get_style_context ().add_class ("dark"); + } else { + get_style_context ().remove_class ("dark"); + } + } + + void configure_window_keep_above_settings () { + switch (Application.settings.get_string ("window-keep-above")) { + case "Always": + set_keep_above (true); + keep_above_when_playing = false; + break; + case "When playing": + keep_above_when_playing = true; + set_keep_above (main_stack.visible_child_name == "PLAYING" ? true : false); + break; + case "Never keep above": + set_keep_above (false); + keep_above_when_playing = false; + break; + } + } + + void configure_window_opacity_on_focus_loss () { + if (Application.settings.get_boolean ("window-out-of-focus-translucid")) { + get_style_context ().add_class ("translucid-backdrop"); + } else { + get_style_context ().remove_class ("translucid-backdrop"); + } + } + + void on_stack_visible_child_changed () { + if (keep_above_when_playing) { + set_keep_above (main_stack.visible_child_name == "PLAYING" ? true : false); + } + } +} diff --git a/src/View/SettingsPopover.vala b/src/View/SettingsPopover.vala new file mode 100644 index 0000000..6d422ac --- /dev/null +++ b/src/View/SettingsPopover.vala @@ -0,0 +1,70 @@ +public class Lyrics.SettingsPopover : Gtk.Popover { + FileChooserButton folder_chooser_button; + Gtk.ComboBox combobox; + Gtk.Switch opacity_switch; + + public SettingsPopover () { + var grid = new Gtk.Grid (); + grid.margin = 12; + grid.row_spacing = grid.column_spacing = 12; + + var lyrics_folder_label = new Gtk.Label ("Lyrics download folder:"); + folder_chooser_button = new FileChooserButton (_("Select folder to download lyrics"), Gtk.FileChooserAction.SELECT_FOLDER); + try { + folder_chooser_button.add_shortcut_folder (Application.DEFAULT_LYRICS_DIR); + } catch (Error e) { + info ("Couldn't add default lyrics folder to FileChooserButton " + e.message); + } + + var window_behavior_label = new Gtk.Label ("Keep window above:"); + window_behavior_label.halign = Gtk.Align.START; + + combobox = create_combobox (); + var reset_default_button = create_reset_button (); + + grid.attach (lyrics_folder_label, 0, 0); + grid.attach (folder_chooser_button, 1, 0); + grid.attach (window_behavior_label, 0, 1); + grid.attach (combobox, 1, 1); + grid.attach (create_translucid_switch (), 0, 2, 2); + grid.attach (reset_default_button, 0, 3, 2); + grid.show_all (); + + add (grid); + + Application.settings.bind ("download-location", folder_chooser_button, "filename", GLib.SettingsBindFlags.DEFAULT); + Application.settings.bind ("window-keep-above", combobox, "active-id", GLib.SettingsBindFlags.DEFAULT); + Application.settings.bind ("window-out-of-focus-translucid", opacity_switch, "active", GLib.SettingsBindFlags.DEFAULT); + } + + Gtk.ComboBox create_combobox () { + var combobox = new Gtk.ComboBoxText (); + combobox.append ("Always", "Always"); + combobox.append ("When playing", "When playing"); + combobox.append ("Never keep above", "Never keep above"); + + return combobox; + } + + Gtk.Container create_translucid_switch () { + var box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6); + box.add (opacity_switch = new Gtk.Switch ()); + box.add (new Gtk.Label ("Make translucid on focus loss")); + box.halign = Gtk.Align.START; + + return box; + } + + Gtk.Button create_reset_button () { + var btn = new Gtk.Button.with_label (_("Restore default settings")); + btn.halign = Gtk.Align.CENTER; + btn.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); + btn.clicked.connect (() => { + Application.settings.set_string ("download-location", Application.DEFAULT_LYRICS_DIR); + Application.settings.reset ("window-keep-above"); + Application.settings.reset ("window-out-of-focus-translucid"); + }); + + return btn; + } +} diff --git a/src/Widgets/FileChooserButton.vala b/src/Widgets/FileChooserButton.vala new file mode 100644 index 0000000..ff4ba5f --- /dev/null +++ b/src/Widgets/FileChooserButton.vala @@ -0,0 +1,27 @@ +public class Lyrics.FileChooserButton : Gtk.FileChooserButton { + string? _filename; + public string filename { + get { + return _filename; + } + set { + if (value == null) { + return; + } + + _filename = value; + set_filename (_filename); + } + } + + public FileChooserButton (string _title, Gtk.FileChooserAction _action) { + title = _title; + action = _action; + + selection_changed.connect (() => { + if (filename != get_filename()) { + filename = get_filename(); + } + }); + } +}