From d1a3871630ab3cc53a289df4bf7c490596deafbc Mon Sep 17 00:00:00 2001 From: teamcons_atwork Date: Wed, 11 Jun 2025 13:22:12 +0200 Subject: [PATCH 01/17] move lambdas to handlers --- src/Window.vala | 113 ++++++++++++++++++++++++++---------------------- 1 file changed, 62 insertions(+), 51 deletions(-) diff --git a/src/Window.vala b/src/Window.vala index df204e0..46a0b30 100644 --- a/src/Window.vala +++ b/src/Window.vala @@ -9,6 +9,10 @@ public class AppWindow : Gtk.Window { public string file_name { get; set; default = "unknown"; } public bool is_new { get; set; default = false; } + // Add a debounce so we aren't writing the entire buffer every character input + public int interval = 500; // ms + public uint debounce_timer_id = 0; + public AppWindow () { debug ("Constructing GUI"); @@ -76,57 +80,9 @@ public class AppWindow : Gtk.Window { // Signal callbacks are heavily derived from similar operations in // elementary/code - save_as_button.clicked.connect (() => { - var save_dialog = new Gtk.FileDialog () { initial_name = file_name }; - - save_dialog.save.begin (this, null, (obj, res) => { - try { - file = save_dialog.save.end (res); - file_name = file.get_basename (); - if (is_new) { is_new = false; } - save_file (file); - } catch (Error err) { - warning ("Failed to save file: %s", err.message); - } - }); - }); - - this.close_request.connect (() => { - save_file (); - - if (is_new) { - try { - this.file.delete (); - } catch (Error err) { - warning ( - "The persistent file couldn't be deleted: %s", - err.message - ); - } - } - - return false; - }); - - // Add a debounce so we aren't writing the entire buffer every character input - var interval = 500; // ms - uint debounce_timer_id = 0; - - buf.changed.connect (() => { - debug ("The buffer has been modified, starting the debounce timer"); - - if (debounce_timer_id != 0) { - GLib.Source.remove (debounce_timer_id); - } - - debounce_timer_id = Timeout.add (interval, () => { - debounce_timer_id = 0; - if (file.query_exists ()) { - save_file (); - } - return GLib.Source.REMOVE; - }); - }); + save_as_button.clicked.connect (on_save); + this.close_request.connect (on_close); + buf.changed.connect (on_buffer_changed); debug ("Binding window title to file_name"); @@ -135,6 +91,8 @@ public class AppWindow : Gtk.Window { debug ("Success!"); } + + /* ---------------- FILE OPERATIONS ---------------- */ public void open_file (File file = this.file) { this.file = file; @@ -176,4 +134,57 @@ public class AppWindow : Gtk.Window { warning ("Couldn't save file: %s", err.message); } } + + + /* ---------------- HANDLERS ---------------- */ + public void on_save () { + debug ("Save event!"); + var save_dialog = new Gtk.FileDialog () { initial_name = file_name }; + + save_dialog.save.begin (this, null, (obj, res) => { + try { + file = save_dialog.save.end (res); + file_name = file.get_basename (); + if (is_new) { is_new = false; } + save_file (file); + + } catch (Error err) { + warning ("Failed to save file: %s", err.message); + } + }); + } + + public void on_buffer_changed () { + debug ("The buffer has been modified, starting the debounce timer"); + + if (debounce_timer_id != 0) { + GLib.Source.remove (debounce_timer_id); + } + + debounce_timer_id = Timeout.add (interval, () => { + debounce_timer_id = 0; + if (file.query_exists ()) { + save_file (); + } + return GLib.Source.REMOVE; + }); + + } + + public void on_close () { + debug ("Close event!"); + save_file (); + + if (is_new) { + try { + this.file.delete (); + } catch (Error err) { + warning ( + "The persistent file couldn't be deleted: %s", + err.message + ); + } + } + return false; + } } From 0e11f2c1583e4f306fe8f109b1d30be0a7100627 Mon Sep 17 00:00:00 2001 From: teamcons_atwork Date: Wed, 11 Jun 2025 15:24:45 +0200 Subject: [PATCH 02/17] Add managing several unsaved documents --- src/Application.vala | 61 ++++++++++++++++++++++---------------------- src/Utils.vala | 39 ++++++++++++++++++++++++++++ src/Window.vala | 47 ++++++++++++++++++++++++---------- src/meson.build | 1 + 4 files changed, 104 insertions(+), 44 deletions(-) create mode 100644 src/Utils.vala diff --git a/src/Application.vala b/src/Application.vala index 7fdd0cb..60d0d12 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -8,7 +8,7 @@ const string APP_ID = "io.github.wpkelso.slate"; public class Application : Gtk.Application { - uint created_documents = 1; + public static uint created_documents = 1; public Application () { Object ( @@ -43,6 +43,7 @@ public class Application : Gtk.Application { "new-document", null ); + new_document_action.activate.connect (() => { var name = get_new_document_name (); var path = Path.build_filename (Environment.get_user_data_dir (), name); @@ -86,21 +87,37 @@ public class Application : Gtk.Application { } protected override void activate () { - var name = get_new_document_name (); - var path = Path.build_filename (Environment.get_user_data_dir (), name); - var file = File.new_for_path (path); - debug ( - "Document is unsaved, creating an save location at: %s", - path - ); - var new_window = new AppWindow () { - is_new = true, - }; - new_window.open_file (file); + Slate.Utils.check_if_datadir (); + saved_unsaved_documents = Environment.get_user_data_dir (); + pile_unsaved_documents = saved_unsaved_documents.open (); + + // Conveniently, if there is no unsaved document, we just get NULL + // Which AppWindow will process as a new unsaved doc + foreach (unsaved_document in pile_unsaved_documents.read_name() ) { + + debug ( + "Document is unsaved, creating an save location at: %s", + path + ); + + var new_window = new AppWindow (unsaved_document) { + is_new = true, + }; + + add_window (new_window); + new_window.present (); + } - add_window (new_window); - new_window.present (); + + if (args[1] != null) { + + open_at = File.new_for_path(args[1]); + var new_window = new AppWindow (open_at); + + add_window (new_window); + new_window.present (); + } } protected override void open (File[] files, string hint) { @@ -115,22 +132,6 @@ public class Application : Gtk.Application { } } - string get_new_document_name () { - var name = "New Document"; - if (created_documents > 1) { - name = name + " " + created_documents.to_string (); - } - - debug ( - "New document name is: %s", - name - ); - - this.created_documents++; - - return name; - } - public static int main (string[] args) { return new Application ().run (args); } diff --git a/src/Utils.vala b/src/Utils.vala new file mode 100644 index 0000000..88cc713 --- /dev/null +++ b/src/Utils.vala @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: GPL-3.0-or-later + * SPDX-FileCopyrightText: 2025 William Kelso + */ + + +namespace Slate.Utils { + + public string get_new_document_name () { + var name = _"New Document"; + + if (created_documents > 1) { + name = name + " " + created_documents.to_string (); + } + + debug ( + "New document name is: %s", + name + ); + + created_documents++; + + return name; + } + + public void check_if_datadir () { + debug ("do we have a data directory?"); + var data_directory = File.new_for_path (Environment.get_user_data_dir ()); + try { + if (!data_directory.query_exists ()) { + data_directory.make_directory (); + print("Prepared target data directory"); + } + } catch (Error e) { + warning ("Failed to prepare target data directory %s\n", e.message); + } + } + +} diff --git a/src/Window.vala b/src/Window.vala index 46a0b30..0124bbf 100644 --- a/src/Window.vala +++ b/src/Window.vala @@ -6,14 +6,14 @@ public class AppWindow : Gtk.Window { public File file { get; set; } private Gtk.TextBuffer buf; - public string file_name { get; set; default = "unknown"; } - public bool is_new { get; set; default = false; } + public string? file_name { get; set; default = null; } + public bool is_new; // Add a debounce so we aren't writing the entire buffer every character input public int interval = 500; // ms public uint debounce_timer_id = 0; - public AppWindow () { + public AppWindow (File? document) { debug ("Constructing GUI"); Intl.setlocale (); @@ -80,7 +80,7 @@ public class AppWindow : Gtk.Window { // Signal callbacks are heavily derived from similar operations in // elementary/code - save_as_button.clicked.connect (on_save); + save_as_button.clicked.connect (on_save_as); this.close_request.connect (on_close); buf.changed.connect (on_buffer_changed); @@ -89,22 +89,35 @@ public class AppWindow : Gtk.Window { bind_property ("file_name", this, "title"); debug ("Success!"); + + + if (document == null) { + new_empty_doc (); + } + + open_file (document); } /* ---------------- FILE OPERATIONS ---------------- */ - public void open_file (File file = this.file) { - this.file = file; + public void open_file (File? file = this.file) { + debug ("Attempting to open file %s", file.get_basename ()); + + if (file = null) { + is_new = true; + + this.file_name = Slate.Utils.get_new_document_name (); + this.file = File.new_for_path (Environment.get_user_data_dir () + '/' + name); - if (this.is_new) { try { - file.create (GLib.FileCreateFlags.REPLACE_DESTINATION); - this.file_name = file.get_basename (); + this.file.create (GLib.FileCreateFlags.REPLACE_DESTINATION); } catch (Error err) { - warning ("Couldn't create file: %s", err.message); + warning ("Couldn't create file: %s", err.message); } + } else { - debug ("Attempting to open file %s", file.get_basename ()); + this.file = file; + try { this.file_name = file.get_basename (); var distream = new DataInputStream (file.read (null)); @@ -117,6 +130,13 @@ public class AppWindow : Gtk.Window { } public void save_file (File file = this.file) { + + // We have to always check if nothing happened to datadir + // This way if the user deleted in the meantime everything, we still can save unsaved docs + if (is_new) { + Slate.Utils.check_if_datadir; + } + try { debug ("Attempting to save the buffer to disk.."); DataOutputStream dostream; @@ -135,9 +155,8 @@ public class AppWindow : Gtk.Window { } } - /* ---------------- HANDLERS ---------------- */ - public void on_save () { + public void on_save_as () { debug ("Save event!"); var save_dialog = new Gtk.FileDialog () { initial_name = file_name }; @@ -147,7 +166,7 @@ public class AppWindow : Gtk.Window { file_name = file.get_basename (); if (is_new) { is_new = false; } save_file (file); - + } catch (Error err) { warning ("Failed to save file: %s", err.message); } diff --git a/src/meson.build b/src/meson.build index cc9af95..f5f77ac 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,4 +1,5 @@ sources += files( 'Window.vala', 'Application.vala', + 'Utils.vala', ) From 12a58874fae1b9911a232ba6ebc4d094e8ad7b2c Mon Sep 17 00:00:00 2001 From: teamcons_atwork Date: Wed, 11 Jun 2025 15:31:05 +0200 Subject: [PATCH 03/17] the app already handles opens --- src/Application.vala | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index 60d0d12..f2ef69d 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -108,16 +108,6 @@ public class Application : Gtk.Application { add_window (new_window); new_window.present (); } - - - if (args[1] != null) { - - open_at = File.new_for_path(args[1]); - var new_window = new AppWindow (open_at); - - add_window (new_window); - new_window.present (); - } } protected override void open (File[] files, string hint) { From b11864ced0c9eecdd2ee9a23e055b4a36b5a2b6f Mon Sep 17 00:00:00 2001 From: teamcons_atwork Date: Wed, 11 Jun 2025 15:49:01 +0200 Subject: [PATCH 04/17] clean up a bit --- src/Application.vala | 2 +- src/Utils.vala | 20 +++++++++----------- src/Window.vala | 8 +------- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index f2ef69d..64ecf12 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -94,7 +94,7 @@ public class Application : Gtk.Application { // Conveniently, if there is no unsaved document, we just get NULL // Which AppWindow will process as a new unsaved doc - foreach (unsaved_document in pile_unsaved_documents.read_name() ) { + foreach (unsaved_document in pile_unsaved_documents.read_name () ) { debug ( "Document is unsaved, creating an save location at: %s", diff --git a/src/Utils.vala b/src/Utils.vala index 88cc713..fc09d6d 100644 --- a/src/Utils.vala +++ b/src/Utils.vala @@ -8,7 +8,7 @@ namespace Slate.Utils { public string get_new_document_name () { var name = _"New Document"; - + if (created_documents > 1) { name = name + " " + created_documents.to_string (); } @@ -26,14 +26,12 @@ namespace Slate.Utils { public void check_if_datadir () { debug ("do we have a data directory?"); var data_directory = File.new_for_path (Environment.get_user_data_dir ()); - try { - if (!data_directory.query_exists ()) { - data_directory.make_directory (); - print("Prepared target data directory"); - } - } catch (Error e) { - warning ("Failed to prepare target data directory %s\n", e.message); - } - } - + try { + if (!data_directory.query_exists ()) { + data_directory.make_directory (); + } + } catch (Error e) { + warning ("Failed to prepare target data directory %s\n", e.message); + } + } } diff --git a/src/Window.vala b/src/Window.vala index 0124bbf..abd0a17 100644 --- a/src/Window.vala +++ b/src/Window.vala @@ -90,15 +90,9 @@ public class AppWindow : Gtk.Window { debug ("Success!"); - - if (document == null) { - new_empty_doc (); - } - open_file (document); } - /* ---------------- FILE OPERATIONS ---------------- */ public void open_file (File? file = this.file) { debug ("Attempting to open file %s", file.get_basename ()); @@ -134,7 +128,7 @@ public class AppWindow : Gtk.Window { // We have to always check if nothing happened to datadir // This way if the user deleted in the meantime everything, we still can save unsaved docs if (is_new) { - Slate.Utils.check_if_datadir; + Slate.Utils.check_if_datadir (); } try { From 17e7922e6dc06bcf28f6af7def7654049473501f Mon Sep 17 00:00:00 2001 From: teamcons_atwork Date: Wed, 11 Jun 2025 15:54:23 +0200 Subject: [PATCH 05/17] again --- src/Utils.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utils.vala b/src/Utils.vala index fc09d6d..38573be 100644 --- a/src/Utils.vala +++ b/src/Utils.vala @@ -25,7 +25,7 @@ namespace Slate.Utils { public void check_if_datadir () { debug ("do we have a data directory?"); - var data_directory = File.new_for_path (Environment.get_user_data_dir ()); + var data_directory = File.new_for_path (Environment.get_user_data_dir ()); try { if (!data_directory.query_exists ()) { data_directory.make_directory (); From 0c4b266ad896f66864dbc9284d5d1be3152b7707 Mon Sep 17 00:00:00 2001 From: teamcons_atwork Date: Wed, 11 Jun 2025 16:06:27 +0200 Subject: [PATCH 06/17] foreach --- src/Application.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Application.vala b/src/Application.vala index 64ecf12..16df937 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -94,7 +94,7 @@ public class Application : Gtk.Application { // Conveniently, if there is no unsaved document, we just get NULL // Which AppWindow will process as a new unsaved doc - foreach (unsaved_document in pile_unsaved_documents.read_name () ) { + foreach (var unsaved_document in pile_unsaved_documents.read_name () ) { debug ( "Document is unsaved, creating an save location at: %s", From 87c643fac452e6c8afe0607e1c8445320af8a605 Mon Sep 17 00:00:00 2001 From: teamcons_atwork Date: Wed, 11 Jun 2025 16:14:30 +0200 Subject: [PATCH 07/17] Msgstring for the builder. The rest ill do at home --- src/Utils.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utils.vala b/src/Utils.vala index 38573be..69452d4 100644 --- a/src/Utils.vala +++ b/src/Utils.vala @@ -7,7 +7,7 @@ namespace Slate.Utils { public string get_new_document_name () { - var name = _"New Document"; + var name = _("New Document"); if (created_documents > 1) { name = name + " " + created_documents.to_string (); From e6be20e4a51e946268474bd1c681f863d88e3e8f Mon Sep 17 00:00:00 2001 From: teamcons Date: Wed, 11 Jun 2025 20:40:18 +0200 Subject: [PATCH 08/17] Revert fucky changes and rewrite from scratch --- .gitignore | 3 +- meson.build | 5 ++ src/Application.vala | 140 +++++++++++++++++++++++++------------------ src/Utils.vala | 37 ------------ src/Window.vala | 87 +++++++++++++-------------- src/meson.build | 1 - 6 files changed, 132 insertions(+), 141 deletions(-) delete mode 100644 src/Utils.vala diff --git a/.gitignore b/.gitignore index 79e31ca..fb7962a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ builddir # subprojects/*/ .flatpak-builder -.vscode \ No newline at end of file +.vscode +.flatpak/meson.sh diff --git a/meson.build b/meson.build index 0e329a8..820d29a 100644 --- a/meson.build +++ b/meson.build @@ -48,3 +48,8 @@ executable( subdir('data') subdir('po') + +gnome.post_install( + gtk_update_icon_cache: true, + update_desktop_database: true + ) \ No newline at end of file diff --git a/src/Application.vala b/src/Application.vala index 16df937..f12d3e9 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -43,86 +43,112 @@ public class Application : Gtk.Application { "new-document", null ); - - new_document_action.activate.connect (() => { - var name = get_new_document_name (); - var path = Path.build_filename (Environment.get_user_data_dir (), name); - var file = File.new_for_path (path); - debug ( - "Document is unsaved, creating an save location at: %s", - path - ); - - var new_window = new AppWindow () { - is_new = true, - }; - new_window.open_file (file); - - debug ("Created new window with name %s", name); - add_window (new_window); - new_window.present (); - }); + new_document_action.activate.connect (on_new_document); this.add_action (new_document_action); SimpleAction open_document_action = new SimpleAction ( "open-document", null ); - open_document_action.activate.connect (() => { - var open_dialog = new Gtk.FileDialog (); - var new_window = new AppWindow (); - - open_dialog.open.begin (new_window, null, (obj, res) => { - try { - var file = open_dialog.open.end (res); - new_window.open_file (file); - add_window (new_window); - new_window.present (); - } catch (Error err) { - warning ("Failed to select file to open: %s", err.message); - } - }); - }); + open_document_action.activate.connect (on_open_document); this.add_action (open_document_action); } protected override void activate () { - Slate.Utils.check_if_datadir (); - saved_unsaved_documents = Environment.get_user_data_dir (); - pile_unsaved_documents = saved_unsaved_documents.open (); - - // Conveniently, if there is no unsaved document, we just get NULL - // Which AppWindow will process as a new unsaved doc - foreach (var unsaved_document in pile_unsaved_documents.read_name () ) { - - debug ( - "Document is unsaved, creating an save location at: %s", - path - ); - - var new_window = new AppWindow (unsaved_document) { - is_new = true, - }; + // Reopen all the unsaved documents we have in datadir + check_if_datadir (); + var datadir = Environment.get_user_data_dir (); + try { + var pile_unsaved_documents = Dir.open (datadir); + + string? unsaved_doc = null; + while ((unsaved_doc = pile_unsaved_documents.read_name ()) != null) { + print (unsaved_doc); + string path = Path.build_filename (datadir, unsaved_doc); + File file = File.new_for_path (path); + open_file (file); + created_documents++; + } + + } catch (Error e) { + warning ("Cannot read datadir! Is the disk okay? %s\n", e.message); + } - add_window (new_window); - new_window.present (); + // What if there was none ? The loop wouldnt happen at all. + if (created_documents == 1) { + on_new_document (); } + } protected override void open (File[] files, string hint) { foreach (var file in files) { debug ("Creating window with file: %s", file.get_basename ()); - var window = new AppWindow (); - window.open_file (file); + open_file (file); + } + } + + string get_new_document_name () { + var name = _("New Document"); + if (created_documents > 1) { + name = name + " " + created_documents.to_string (); + } - debug ("Adding new window to application"); - add_window (window); - window.present (); + debug ("New document name is: %s",name); + + created_documents++; + + return name; + } + + public void check_if_datadir () { + debug ("do we have a data directory?"); + var data_directory = File.new_for_path (Environment.get_user_data_dir ()); + try { + if (!data_directory.query_exists ()) { + data_directory.make_directory (); + } + } catch (Error e) { + warning ("Failed to prepare target data directory %s\n", e.message); } } public static int main (string[] args) { return new Application ().run (args); } + + public void on_new_document () { + var name = get_new_document_name (); + var path = Path.build_filename (Environment.get_user_data_dir (), name); + var file = File.new_for_path (path); + + check_if_datadir (); + try { + file.create_readwrite (GLib.FileCreateFlags.REPLACE_DESTINATION); + } catch (Error e) { + warning ("Failed to prepare target file %s\n", e.message); + } + + open_file (file); + + } + + public void open_file (File file) { + var new_window = new AppWindow (file); + add_window (new_window); + new_window.present (); + } + + public void on_open_document() { + var open_dialog = new Gtk.FileDialog (); + open_dialog.open.begin (this.active_window, null, (obj, res) => { + try { + var file = open_dialog.open.end (res); + open_file (file); + } catch (Error err) { + warning ("Failed to select file to open: %s", err.message); + } + }); + } } diff --git a/src/Utils.vala b/src/Utils.vala deleted file mode 100644 index 69452d4..0000000 --- a/src/Utils.vala +++ /dev/null @@ -1,37 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0-or-later - * SPDX-FileCopyrightText: 2025 William Kelso - */ - - -namespace Slate.Utils { - - public string get_new_document_name () { - var name = _("New Document"); - - if (created_documents > 1) { - name = name + " " + created_documents.to_string (); - } - - debug ( - "New document name is: %s", - name - ); - - created_documents++; - - return name; - } - - public void check_if_datadir () { - debug ("do we have a data directory?"); - var data_directory = File.new_for_path (Environment.get_user_data_dir ()); - try { - if (!data_directory.query_exists ()) { - data_directory.make_directory (); - } - } catch (Error e) { - warning ("Failed to prepare target data directory %s\n", e.message); - } - } -} diff --git a/src/Window.vala b/src/Window.vala index abd0a17..af9b51c 100644 --- a/src/Window.vala +++ b/src/Window.vala @@ -6,14 +6,14 @@ public class AppWindow : Gtk.Window { public File file { get; set; } private Gtk.TextBuffer buf; - public string? file_name { get; set; default = null; } - public bool is_new; + public string file_name { get; set; } + public bool is_new { get; set; default = false; } // Add a debounce so we aren't writing the entire buffer every character input public int interval = 500; // ms public uint debounce_timer_id = 0; - public AppWindow (File? document) { + public AppWindow (File file) { debug ("Constructing GUI"); Intl.setlocale (); @@ -63,6 +63,7 @@ public class AppWindow : Gtk.Window { wrap_mode = WORD_CHAR, }; buf = text_view.buffer; + buf.text = ""; var scrolled_view = new Gtk.ScrolledWindow () { @@ -90,47 +91,25 @@ public class AppWindow : Gtk.Window { debug ("Success!"); - open_file (document); + open_file (file); } - /* ---------------- FILE OPERATIONS ---------------- */ - public void open_file (File? file = this.file) { - debug ("Attempting to open file %s", file.get_basename ()); - - if (file = null) { - is_new = true; - - this.file_name = Slate.Utils.get_new_document_name (); - this.file = File.new_for_path (Environment.get_user_data_dir () + '/' + name); - - try { - this.file.create (GLib.FileCreateFlags.REPLACE_DESTINATION); - } catch (Error err) { - warning ("Couldn't create file: %s", err.message); - } - } else { - this.file = file; - - try { - this.file_name = file.get_basename (); - var distream = new DataInputStream (file.read (null)); - var contents = distream.read_upto ("", -1, null); - buf.set_text (contents); - } catch (Error err) { - warning ("Couldn't open file: %s", err.message); - } + /* ---------------- FILE OPERATIONS ---------------- */ + public void open_file (File file = this.file) { + this.file = file; + debug ("Attempting to open file %s", file.get_basename ()); + try { + this.file_name = file.get_basename (); + var distream = new DataInputStream (file.read (null)); + var contents = distream.read_upto ("", -1, null); + buf.set_text (contents); + } catch (Error err) { + warning ("Couldn't open file: %s", err.message); } } public void save_file (File file = this.file) { - - // We have to always check if nothing happened to datadir - // This way if the user deleted in the meantime everything, we still can save unsaved docs - if (is_new) { - Slate.Utils.check_if_datadir (); - } - try { debug ("Attempting to save the buffer to disk.."); DataOutputStream dostream; @@ -149,22 +128,36 @@ public class AppWindow : Gtk.Window { } } + /* ---------------- HANDLERS ---------------- */ public void on_save_as () { debug ("Save event!"); var save_dialog = new Gtk.FileDialog () { initial_name = file_name }; + File oldfile = this.file; + bool delete_after = false; + + if (Environment.get_user_data_dir () in this.file.get_path ()) { + delete_after = true; + } save_dialog.save.begin (this, null, (obj, res) => { try { + + file = save_dialog.save.end (res); file_name = file.get_basename (); - if (is_new) { is_new = false; } save_file (file); + if ((delete_after) && (oldfile != file)) { + oldfile.delete (); + } + } catch (Error err) { warning ("Failed to save file: %s", err.message); } }); + + } public void on_buffer_changed () { @@ -184,20 +177,24 @@ public class AppWindow : Gtk.Window { } - public void on_close () { + public bool on_close () { debug ("Close event!"); - save_file (); - if (is_new) { + bool is_unsaved_doc = (Environment.get_user_data_dir () in this.file.get_path ()); + + // We want to delete empty unsaved documents + if ((is_unsaved_doc) && (buf.text == "")) { + try { this.file.delete (); } catch (Error err) { - warning ( - "The persistent file couldn't be deleted: %s", - err.message - ); + warning ("Failed to delete empty temp file: %s", err.message); } + + } else { + save_file (); } + return false; } } diff --git a/src/meson.build b/src/meson.build index f5f77ac..cc9af95 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,5 +1,4 @@ sources += files( 'Window.vala', 'Application.vala', - 'Utils.vala', ) From 0dd18024006f417a6eb7831464d600a601c0949a Mon Sep 17 00:00:00 2001 From: teamcons Date: Wed, 11 Jun 2025 20:59:55 +0200 Subject: [PATCH 09/17] cleanup and add actions --- src/Application.vala | 33 ++++++++++++++++++++++++--------- src/Window.vala | 13 ++++--------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index f12d3e9..3b346af 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -39,19 +39,30 @@ public class Application : Gtk.Application { ); }); - SimpleAction new_document_action = new SimpleAction ( - "new-document", - null - ); + SimpleAction new_document_action = new SimpleAction ("new-document",null); + set_accels_for_action ("app.new-document", {"n"}); new_document_action.activate.connect (on_new_document); this.add_action (new_document_action); - SimpleAction open_document_action = new SimpleAction ( - "open-document", - null - ); + SimpleAction open_document_action = new SimpleAction ("open-document",null); + set_accels_for_action ("app.open-document", {"o"}); open_document_action.activate.connect (on_open_document); this.add_action (open_document_action); + + //SimpleAction saveas_action = new SimpleAction ("saveas", null); + //set_accels_for_action ("app.saveas", {"s"}); + //add_action (saveas); + //saveas_action.activate.connect (this.on_save_as); + + SimpleAction quit_action = new SimpleAction ("quit", null); + set_accels_for_action ("app.quit", {"q"}); + add_action (quit_action); + quit_action.activate.connect (() => { + foreach (var window in this.get_windows ()) { + window.close (); + } + this.quit (); + }); } protected override void activate () { @@ -140,7 +151,7 @@ public class Application : Gtk.Application { new_window.present (); } - public void on_open_document() { + public void on_open_document () { var open_dialog = new Gtk.FileDialog (); open_dialog.open.begin (this.active_window, null, (obj, res) => { try { @@ -151,4 +162,8 @@ public class Application : Gtk.Application { } }); } + + public void on_save_as () { + (AppWindow)this.active_window.on_save_as (); + } } diff --git a/src/Window.vala b/src/Window.vala index af9b51c..6189f48 100644 --- a/src/Window.vala +++ b/src/Window.vala @@ -7,7 +7,6 @@ public class AppWindow : Gtk.Window { public File file { get; set; } private Gtk.TextBuffer buf; public string file_name { get; set; } - public bool is_new { get; set; default = false; } // Add a debounce so we aren't writing the entire buffer every character input public int interval = 500; // ms @@ -21,20 +20,20 @@ public class AppWindow : Gtk.Window { var new_button = new Gtk.Button.from_icon_name ("document-new") { action_name = "app.new-document", tooltip_markup = Granite.markup_accel_tooltip ( - {""}, + {"n"}, _("New Document") ) }; var open_button = new Gtk.Button.from_icon_name ("document-open") { action_name = "app.open-document", tooltip_markup = Granite.markup_accel_tooltip ( - {""}, + {"o"}, _("Open file") ) }; var save_as_button = new Gtk.Button.from_icon_name ("document-save-as") { tooltip_markup = Granite.markup_accel_tooltip ( - {""}, + {"s"}, _("Save as") ) }; @@ -134,11 +133,7 @@ public class AppWindow : Gtk.Window { debug ("Save event!"); var save_dialog = new Gtk.FileDialog () { initial_name = file_name }; File oldfile = this.file; - bool delete_after = false; - - if (Environment.get_user_data_dir () in this.file.get_path ()) { - delete_after = true; - } + bool delete_after = (Environment.get_user_data_dir () in this.file.get_path ()); save_dialog.save.begin (this, null, (obj, res) => { try { From e32196de2210f54173bf60b09a94362a9da42154 Mon Sep 17 00:00:00 2001 From: teamcons Date: Wed, 11 Jun 2025 21:02:07 +0200 Subject: [PATCH 10/17] make the linter happy --- src/Application.vala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index 3b346af..c3f1580 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -74,7 +74,7 @@ public class Application : Gtk.Application { var pile_unsaved_documents = Dir.open (datadir); string? unsaved_doc = null; - while ((unsaved_doc = pile_unsaved_documents.read_name ()) != null) { + while ((unsaved_doc = pile_unsaved_documents.read_name ()) != null) { print (unsaved_doc); string path = Path.build_filename (datadir, unsaved_doc); File file = File.new_for_path (path); @@ -90,7 +90,7 @@ public class Application : Gtk.Application { if (created_documents == 1) { on_new_document (); } - + } protected override void open (File[] files, string hint) { @@ -106,7 +106,7 @@ public class Application : Gtk.Application { name = name + " " + created_documents.to_string (); } - debug ("New document name is: %s",name); + debug ("New document name is: %s", name); created_documents++; From 9226d17320b27c2db8a78afe689a18e915ed39c3 Mon Sep 17 00:00:00 2001 From: teamcons Date: Wed, 11 Jun 2025 21:04:00 +0200 Subject: [PATCH 11/17] this should build --- src/Application.vala | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index c3f1580..4e9c0c1 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -162,8 +162,4 @@ public class Application : Gtk.Application { } }); } - - public void on_save_as () { - (AppWindow)this.active_window.on_save_as (); - } } From 39798d8a514fd58852beca8eee4c0930cf1a8c54 Mon Sep 17 00:00:00 2001 From: teamcons Date: Wed, 11 Jun 2025 21:17:49 +0200 Subject: [PATCH 12/17] proper method for handles, and leave the broken accel alone --- src/Application.vala | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index 4e9c0c1..d77e0e0 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -49,17 +49,20 @@ public class Application : Gtk.Application { open_document_action.activate.connect (on_open_document); this.add_action (open_document_action); - //SimpleAction saveas_action = new SimpleAction ("saveas", null); - //set_accels_for_action ("app.saveas", {"s"}); - //add_action (saveas); - //saveas_action.activate.connect (this.on_save_as); + //TODO: Vala complains about the method not existing + /*SimpleAction saveas_action = new SimpleAction ("saveas", null); + set_accels_for_action ("app.saveas", {"s"}); + add_action (saveas); + saveas_action.activate.connect (() => { + this.get_active_window ().on_save_as (); + });*/ SimpleAction quit_action = new SimpleAction ("quit", null); set_accels_for_action ("app.quit", {"q"}); add_action (quit_action); quit_action.activate.connect (() => { foreach (var window in this.get_windows ()) { - window.close (); + window.close_request (); } this.quit (); }); From 6011dbc5d30fd5588a98bee04ae75ab8b1b058e0 Mon Sep 17 00:00:00 2001 From: teamcons Date: Wed, 11 Jun 2025 21:20:41 +0200 Subject: [PATCH 13/17] Linter --- src/Window.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Window.vala b/src/Window.vala index 6189f48..7b17847 100644 --- a/src/Window.vala +++ b/src/Window.vala @@ -146,7 +146,7 @@ public class AppWindow : Gtk.Window { if ((delete_after) && (oldfile != file)) { oldfile.delete (); } - + } catch (Error err) { warning ("Failed to save file: %s", err.message); } From 1aa32931ebbe99edb7c8fb0040f00665441caa7e Mon Sep 17 00:00:00 2001 From: teamcons Date: Wed, 11 Jun 2025 22:09:20 +0200 Subject: [PATCH 14/17] more agressive checks to prevent data loss --- src/Application.vala | 2 +- src/Window.vala | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Application.vala b/src/Application.vala index d77e0e0..bbc184a 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -116,7 +116,7 @@ public class Application : Gtk.Application { return name; } - public void check_if_datadir () { + public static void check_if_datadir () { debug ("do we have a data directory?"); var data_directory = File.new_for_path (Environment.get_user_data_dir ()); try { diff --git a/src/Window.vala b/src/Window.vala index 7b17847..c3aca95 100644 --- a/src/Window.vala +++ b/src/Window.vala @@ -109,6 +109,10 @@ public class AppWindow : Gtk.Window { } public void save_file (File file = this.file) { + if (Environment.get_user_data_dir () in this.file.get_path ()) { + Application.check_if_datadir(); + } + try { debug ("Attempting to save the buffer to disk.."); DataOutputStream dostream; From f4ade20d8f29e9970f16a246c8b6f16f58748c73 Mon Sep 17 00:00:00 2001 From: teamcons Date: Wed, 11 Jun 2025 22:21:23 +0200 Subject: [PATCH 15/17] LINTERRRR --- src/Window.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Window.vala b/src/Window.vala index c3aca95..e928f2d 100644 --- a/src/Window.vala +++ b/src/Window.vala @@ -110,7 +110,7 @@ public class AppWindow : Gtk.Window { public void save_file (File file = this.file) { if (Environment.get_user_data_dir () in this.file.get_path ()) { - Application.check_if_datadir(); + Application.check_if_datadir (); } try { From 9418b0c52066e265a8d7a839cf42a9701d25e021 Mon Sep 17 00:00:00 2001 From: Stella and Charlie <147658063+teamcons@users.noreply.github.com> Date: Thu, 12 Jun 2025 07:38:35 +0200 Subject: [PATCH 16/17] Update src/Window.vala Co-authored-by: William Kelso --- src/Window.vala | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Window.vala b/src/Window.vala index e928f2d..7441372 100644 --- a/src/Window.vala +++ b/src/Window.vala @@ -142,7 +142,6 @@ public class AppWindow : Gtk.Window { save_dialog.save.begin (this, null, (obj, res) => { try { - file = save_dialog.save.end (res); file_name = file.get_basename (); save_file (file); From 1ed8326531faadd0dde5c758882f69d1c5863b41 Mon Sep 17 00:00:00 2001 From: Stella and Charlie <147658063+teamcons@users.noreply.github.com> Date: Thu, 12 Jun 2025 07:38:47 +0200 Subject: [PATCH 17/17] Update src/Window.vala Co-authored-by: William Kelso --- src/Window.vala | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Window.vala b/src/Window.vala index 7441372..c706767 100644 --- a/src/Window.vala +++ b/src/Window.vala @@ -155,7 +155,6 @@ public class AppWindow : Gtk.Window { } }); - } public void on_buffer_changed () {