From 2a34eeca69ab010988719436e737093f911cf773 Mon Sep 17 00:00:00 2001 From: teamcons Date: Wed, 25 Feb 2026 14:25:47 +0100 Subject: [PATCH 01/32] Prepare for next release --- data/Application.css | 5 +++-- data/inscriptions.metainfo.xml.in | 14 ++++++++++++-- meson.build | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/data/Application.css b/data/Application.css index 0d25913..4ea9118 100644 --- a/data/Application.css +++ b/data/Application.css @@ -20,10 +20,11 @@ /* Picked: #2c3944d9 Base from wpkelso: #33434eff - -@define-color accent_color #33434eff; */ +@define-color accent_color #33434e; + + /* Used in the OrientationsBox for the preview icon */ .rotated * { -gtk-icon-transform: rotate(90deg); diff --git a/data/inscriptions.metainfo.xml.in b/data/inscriptions.metainfo.xml.in index 541bf13..475bb7c 100644 --- a/data/inscriptions.metainfo.xml.in +++ b/data/inscriptions.metainfo.xml.in @@ -49,8 +49,8 @@ https://github.com/elly-code/inscriptions - #95a3ab - #0e141f + #3557082 + #33434e @@ -79,6 +79,16 @@ + + +

Touchups and enhancements

+
    +
  • Minor design changes. Lets do refined shit.
  • +
  • Updated and extended screenshots
  • +
  • Some work into cleaner code
  • +
+
+

🚀 1.0.0 Initial release!

diff --git a/meson.build b/meson.build index 261f8e4..bf67c34 100644 --- a/meson.build +++ b/meson.build @@ -2,7 +2,7 @@ project( 'io.github.elly_code.inscriptions', 'vala', 'c', - version: '1.0.0' + version: '1.0.1' ) #================================ From d307017d3219b33b33b7675e30b06fe9dff59846 Mon Sep 17 00:00:00 2001 From: teamcons Date: Wed, 25 Feb 2026 15:15:50 +0100 Subject: [PATCH 02/32] Extend StatusCode and let it handle explanations --- po/POTFILES | 1 + src/Enums/HighlightColor.vala | 3 + src/Enums/StatusCode.vala | 128 ++++++++++++++++++++++++++++++++-- src/Views/ErrorView.vala | 93 ++---------------------- 4 files changed, 130 insertions(+), 95 deletions(-) diff --git a/po/POTFILES b/po/POTFILES index 0c8f812..17e6b60 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -2,6 +2,7 @@ src/Windows/MainWindow.vala src/Views/TranslationView.vala src/Widgets/HeaderBar.vala src/Views/ErrorView.vala +src/Enums/StatusCode.vala src/Widgets/ErrorBonusBox.vala src/Views/LogView.vala src/Widgets/PopoverWidgets/ApiEntry.vala diff --git a/src/Enums/HighlightColor.vala b/src/Enums/HighlightColor.vala index ccfc04a..1e1d6ca 100644 --- a/src/Enums/HighlightColor.vala +++ b/src/Enums/HighlightColor.vala @@ -3,6 +3,9 @@ * SPDX-FileCopyrightText: 2025 Stella & Charlie (teamcons.carrd.co) */ +// I like aligning the equals +//vala-lint=skip-file + /** * Used in the custom TextView, alternates background color between sentences. */ diff --git a/src/Enums/StatusCode.vala b/src/Enums/StatusCode.vala index 0a2d4c5..eeb7062 100644 --- a/src/Enums/StatusCode.vala +++ b/src/Enums/StatusCode.vala @@ -3,15 +3,131 @@ * SPDX-FileCopyrightText: 2025 Stella & Charlie (teamcons.carrd.co) */ +// I like aligning the equals +//vala-lint=skip-file + /** * libsoup.Status does not have all error codes, so we extend handling in ErrorView/ErrorBonuxBox with these custom ones. * Custom codes we can use safely for at least 0 to 10. * Specific return codes to DeepL, we use their Int representation. */ public enum Inscriptions.StatusCode { - NO_KEY = 0, - NO_INTERNET = 1, - QUOTA = 456, - TOO_MANY_REQUESTS = 429, - SSL_HANDSHAKE_ERROR = 525; -} \ No newline at end of file + + // Custom + NO_KEY = 0, + NO_INTERNET = 1, + UNKNOWN = 2, + + // 200 + OK = Soup.Status.OK, + + // 400 + BAD_REQUEST = Soup.Status.BAD_REQUEST, + FORBIDDEN = Soup.Status.FORBIDDEN, + REQUEST_TIMEOUT = Soup.Status.REQUEST_TIMEOUT, + TOO_MANY_REQUESTS = 429, + QUOTA = 456, + + // 500 + INTERNAL_SERVER_ERROR = Soup.Status.INTERNAL_SERVER_ERROR, + GATEWAY_TIMEOUT = Soup.Status.GATEWAY_TIMEOUT, + SSL_HANDSHAKE_ERROR = 525 + ; + + /** + * Utility function to make use of the various error codes, and return comprehensive explanations. + * It is here better to take the status than let the backend tell us, so we conserve the code for unknown errors. + * Yes, some refers to Soup.Status making the declaration above redundant, but i feel it may be cleaner to keep them in case we need a more native approach. + */ + public static void status_to_details (uint status, + out string explanation_title, out string explanation_text, out string icon_name, out bool report_link) { + + // Set some defaults + icon_name = "dialog-error"; + report_link = false; + + switch (status) { + //Custom status codes feel super evil + //TRANSLATORS: The following texts show up respectively, as a title, and error message, when translating has gone wrong. This needs to be as little technical as possible + case StatusCode.NO_KEY: + explanation_title = _("Hello, World!"); + explanation_text = _("You need a DeepL API key to translate text\nIt can be either DeepL Free or Pro"); + icon_name = "dialog-password"; + return; + + case StatusCode.NO_INTERNET: + explanation_title = _("No Internet"); + icon_name = "network-offline-symbolic"; + + if (Environment.get_variable ("XDG_CURRENT_DESKTOP") == "Pantheon") { + ///TRANSLATORS: This is twice the same text, but the first one has links for elementary OS + explanation_text = _("Please verify you are connected to the internet, and that this app has permission to access it").printf (Granite.SettingsUri.NETWORK, Granite.SettingsUri.PERMISSIONS); + } else { + explanation_text = _("Please verify you are connected to the internet, and that this app has permission to access it"); + } + return; + + case Soup.Status.OK: + explanation_title = _("Everything works great :)"); + explanation_text = _("If you see this and are not me, then it means i forgor to disable this error"); + icon_name = "process-completed"; + report_link = true; + return; + + case Soup.Status.BAD_REQUEST: + explanation_title = _("Bad request"); + explanation_text = _("The app sent a wrong translation request to DeepL\nPlease report this to the app's developer with as much details as you can"); + icon_name = "dialog-warning"; + return; + + case Soup.Status.FORBIDDEN: + explanation_title = _("Forbidden"); + explanation_text = _("Your API key is invalid. Make sure it is the correct one!"); + icon_name = "dialog-error"; + return; + + case StatusCode.TOO_MANY_REQUESTS: + explanation_title = _("Too many requests"); + explanation_text = _("Please wait before retrying. This error should not be possible to happen for this app..."); + icon_name = "dialog-warning"; + return; + + case StatusCode.QUOTA: + explanation_title = _("Your monthly quota has been exceeded"); + explanation_text = _("If you are a Pro API user, this corresponds to your Cost Control limit"); + icon_name = "dialog-warning"; + return; + + case Soup.Status.INTERNAL_SERVER_ERROR: + explanation_title = _("Internal server error"); + explanation_text = _("Retry in a minute? If you see this several times, check online if there is a DeepL service interruption"); + icon_name = "dialog-information"; + return; + + case StatusCode.SSL_HANDSHAKE_ERROR: + explanation_title = _("SSL Handshake error"); + explanation_text = _("This is an issue DeepL is aware of and this app can do nothing about...\nIf you have the know-show, going through a simple authenticated proxy may work"); + icon_name = "network-error"; + return; + + case Soup.Status.REQUEST_TIMEOUT: + explanation_title = _("Request timeout"); + explanation_text = _("No answer has been received. Either DeepL or your connection are having issues"); + icon_name = "network-error"; + return; + + case Soup.Status.GATEWAY_TIMEOUT: + explanation_title = _("Gateway timeout"); + explanation_text = _("No answer has been received. Either DeepL or your connection are having issues"); + icon_name = "network-error"; + return; + + default: + explanation_title = _("Unknown error"); + explanation_text = _("Status code %s, please report this to this app's developer").printf(status.to_string ()); + icon_name = "dialog-question"; + report_link = true; + return; + } + } +} diff --git a/src/Views/ErrorView.vala b/src/Views/ErrorView.vala index 302ca13..af6738e 100644 --- a/src/Views/ErrorView.vala +++ b/src/Views/ErrorView.vala @@ -13,8 +13,8 @@ public class Inscriptions.ErrorView : Granite.Bin { public uint status { get; construct; } public string message { get; construct; } - - string icon_name = "dialog-error"; + + string icon_name; string explanation_title; string explanation_text; bool report_link; @@ -38,7 +38,8 @@ public class Inscriptions.ErrorView : Granite.Bin { margin_bottom = MARGIN_MENU_BIGGER, }; - status_to_message (status); + Inscriptions.StatusCode.status_to_details (status, + out explanation_title, out explanation_text, out icon_name, out report_link); var title = new Granite.Placeholder (explanation_title) { description = explanation_text, @@ -92,92 +93,6 @@ public class Inscriptions.ErrorView : Granite.Bin { } - private void status_to_message (uint status) { - switch (status) { - //Custom status codes feel super evil - //TRANSLATORS: The following texts show up respectively, as a title, and error message, when translating has gone wrong. This needs to be as little technical as possible - case StatusCode.NO_KEY: - explanation_title = _("Hello, World!"); - explanation_text = _("You need a DeepL API key to translate text\nIt can be either DeepL Free or Pro"); - icon_name = "dialog-password"; - return; - - case StatusCode.NO_INTERNET: - explanation_title = _("No Internet"); - icon_name = "network-offline-symbolic"; - - if (Environment.get_variable ("XDG_CURRENT_DESKTOP") == "Pantheon") { - ///TRANSLATORS: This is twice the same text, but the first one has links for elementary OS - explanation_text = _("Please verify you are connected to the internet, and that this app has permission to access it").printf (Granite.SettingsUri.NETWORK, Granite.SettingsUri.PERMISSIONS); - } else { - explanation_text = _("Please verify you are connected to the internet, and that this app has permission to access it"); - } - - return; - - case Soup.Status.OK: - explanation_title = _("Everything works great :)"); - explanation_text = _("If you see this and are not me, then it means i forgor to disable this error"); - icon_name = "process-completed"; - return; - - case Soup.Status.BAD_REQUEST: - explanation_title = _("Bad request"); - explanation_text = _("The app sent a wrong translation request to DeepL\nPlease report this to the app's developer with as much details as you can"); - icon_name = "dialog-warning"; - return; - - case Soup.Status.FORBIDDEN: - explanation_title = _("Forbidden"); - explanation_text = _("Your API key is invalid. Make sure it is the correct one!"); - icon_name = "dialog-error"; - return; - - case StatusCode.TOO_MANY_REQUESTS: - explanation_title = _("Too many requests"); - explanation_text = _("Please wait before retrying. This error should not be possible to happen for this app..."); - icon_name = "dialog-warning"; - return; - - case StatusCode.QUOTA: - explanation_title = _("Your monthly quota has been exceeded"); - explanation_text = _("If you are a Pro API user, this corresponds to your Cost Control limit"); - icon_name = "dialog-warning"; - return; - - case Soup.Status.INTERNAL_SERVER_ERROR: - explanation_title = _("Internal server error"); - explanation_text = _("Retry in a minute? If you see this several times, check online if there is a DeepL service interruption"); - icon_name = "dialog-information"; - return; - - case StatusCode.SSL_HANDSHAKE_ERROR: - explanation_title = _("SSL Handshake error"); - explanation_text = _("This is an issue DeepL is aware of and this app can do nothing about...\nIf you have the know-show, going through a simple authenticated proxy may work"); - icon_name = "network-error"; - return; - - case Soup.Status.REQUEST_TIMEOUT: - explanation_title = _("Request timeout"); - explanation_text = _("No answer has been received. Either DeepL or your connection are having issues"); - icon_name = "network-error"; - return; - - case Soup.Status.GATEWAY_TIMEOUT: - explanation_title = _("Gateway timeout"); - explanation_text = _("No answer has been received. Either DeepL or your connection are having issues"); - icon_name = "network-error"; - return; - - default: - explanation_title = _("Unknown error"); - explanation_text = _("Status code %s, please report this to this app's developer").printf(status.to_string ()); - icon_name = "dialog-question"; - report_link = true; - return; - } - } - private void on_validated () { Timeout.add_once (WAIT_BEFORE_MAIN, () => { return_to_main (); From b6c3b69cdce2b4f2667dceb78fe13b3a1d9346a5 Mon Sep 17 00:00:00 2001 From: teamcons Date: Wed, 25 Feb 2026 18:25:23 +0100 Subject: [PATCH 03/32] refresh codestyle for dropdown model --- src/Objects/DDModel.vala | 33 ++++++++++++++++--------- src/Objects/Lang.vala | 5 ++-- src/Widgets/LanguageItem.vala | 46 +++++++++++++++++++++++++++++++++++ src/meson.build | 1 + 4 files changed, 71 insertions(+), 14 deletions(-) create mode 100644 src/Widgets/LanguageItem.vala diff --git a/src/Objects/DDModel.vala b/src/Objects/DDModel.vala index 3024767..93179fc 100644 --- a/src/Objects/DDModel.vala +++ b/src/Objects/DDModel.vala @@ -12,20 +12,29 @@ public class Inscriptions.DDModel : Object { public GLib.ListStore model {get; set;} public Gtk.SignalListItemFactory factory {get; set;} - public DDModel() { + public DDModel () { model = new GLib.ListStore(typeof(Lang)); factory = new Gtk.SignalListItemFactory(); - factory.setup.connect ((f,o) => { - Gtk.ListItem list_item = (Gtk.ListItem)o; - var label=new Gtk.Label(""); - list_item.set_child(label); - }); - factory.bind.connect ((f,o) => { - Gtk.ListItem list_item = (Gtk.ListItem)o; - var language = list_item.get_item () as Lang; - var label = list_item.get_child() as Gtk.Label; - label.set_text(language.name); - }); + + factory.setup.connect (on_factory_setup); + factory.bind.connect (on_factory_bind); + } + + private void on_factory_setup (Gtk.SignalListItemFactory f, Object o) { + var list_item = (Gtk.ListItem)o; + var item = new Inscriptions.LanguageItem (list_item.position, ""); + + list_item.child = item; + list_item.focusable = true; + } + + private void on_factory_bind (Gtk.SignalListItemFactory f, Object o) { + var list_item = (Gtk.ListItem)o; + var item_language = list_item.get_item () as Lang; + var item = list_item.get_child() as Inscriptions.LanguageItem; + + //print ("position: " + list_item.position.to_string ()); + item.label = item_language.name; } public void model_append(Lang l) { diff --git a/src/Objects/Lang.vala b/src/Objects/Lang.vala index 36bcbfa..c22c68c 100644 --- a/src/Objects/Lang.vala +++ b/src/Objects/Lang.vala @@ -12,15 +12,16 @@ public class Inscriptions.Lang : Object { public string code {get; construct;} public string name {get; construct;} public string both {get; construct;} + public bool enabled {get; set; default = false;} public Lang (string code, string name) { - Object( code: code, + Object (code: code, name: name); } // "Both" serves to evaluate both name and code in a single expression construct { - both = name + "|" + code; + both = "%s|%s".printf(name, code); } public bool efunc(Lang a, Lang b) { diff --git a/src/Widgets/LanguageItem.vala b/src/Widgets/LanguageItem.vala new file mode 100644 index 0000000..9e23598 --- /dev/null +++ b/src/Widgets/LanguageItem.vala @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: GPL-3.0-or-later + * SPDX-FileCopyrightText: 2025 Stella & Charlie (teamcons.carrd.co) + */ + +/** + * Used by DDModel to display Lang items in a Pane Dropdown + */ +public class Inscriptions.LanguageItem : Gtk.Box { + + public uint position {get; construct;} + public bool selected {get; set; default = false;} + public string label {get; set; default = "";} + + Gtk.Label label_widget; + Gtk.Image selected_emblem; + + public LanguageItem (uint position, string label) { + Object ( + position: position, + label: label, + orientation: Gtk.Orientation.HORIZONTAL, + spacing: Inscriptions.SPACING_TOOLBAR_HEADER, + halign: Gtk.Align.CENTER, + hexpand: true + ); + } + + construct { + label_widget = new Gtk.Label (label); + selected_emblem = new Gtk.Image.from_icon_name ("emblem-default-symbolic") { + visible = selected + }; + + append (label_widget); + append (selected_emblem); + + bind_property ("label", + label_widget, "label", + GLib.BindingFlags.DEFAULT); + + bind_property ("selected", + selected_emblem, "visible", + GLib.BindingFlags.DEFAULT); + } +} diff --git a/src/meson.build b/src/meson.build index 8d8ba29..880ee6d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -19,6 +19,7 @@ sources = files ( 'Widgets' / 'Panes' / 'SourcePane.vala', 'Widgets' / 'Panes' / 'TargetPane.vala', + 'Widgets' / 'LanguageItem.vala', 'Widgets' / 'LogToolbar.vala', 'Widgets' / 'ErrorBonusBox.vala', 'Widgets' / 'TextView.vala', From 623fd534e1e3d230b4f7da5ae035409dcb328dde Mon Sep 17 00:00:00 2001 From: teamcons Date: Thu, 26 Feb 2026 22:20:51 +0100 Subject: [PATCH 04/32] Display which item is already selected --- data/Application.css | 5 +++ src/Objects/DDModel.vala | 66 ++++++++++++++++++++++++++++------- src/Widgets/LanguageItem.vala | 38 ++++++++++++-------- src/Widgets/Panes/Pane.vala | 15 +++++--- 4 files changed, 91 insertions(+), 33 deletions(-) diff --git a/data/Application.css b/data/Application.css index 4ea9118..fe1c4d1 100644 --- a/data/Application.css +++ b/data/Application.css @@ -51,4 +51,9 @@ Base from wpkelso: #33434eff /* Pretend the log textview is a console */ .console { background-color: #002B36; +} + +/* Used for labels in the popover */ +.bold { + font-weight: bold; } \ No newline at end of file diff --git a/src/Objects/DDModel.vala b/src/Objects/DDModel.vala index 93179fc..2c91e68 100644 --- a/src/Objects/DDModel.vala +++ b/src/Objects/DDModel.vala @@ -6,38 +6,78 @@ /** * DDModel, to manage lists of Lang objects (Languages), notably for the dropdown of Pane - * Thank you stronnag! + * In human, this is to have a custom dropdown for language selection */ public class Inscriptions.DDModel : Object { public GLib.ListStore model {get; set;} - public Gtk.SignalListItemFactory factory {get; set;} + public Gtk.SignalListItemFactory factory_header {get; set;} + public Gtk.SignalListItemFactory factory_list {get; set;} + + // Signal emitted by factory_header.bind when a language is selected, which factory_list.bind listens to + public signal void selection_changed (string language_code_selected); public DDModel () { + // The Langs will populate this thing model = new GLib.ListStore(typeof(Lang)); - factory = new Gtk.SignalListItemFactory(); - factory.setup.connect (on_factory_setup); - factory.bind.connect (on_factory_bind); + factory_header = new Gtk.SignalListItemFactory(); + factory_list = new Gtk.SignalListItemFactory(); + + // This one does simple labels for each language, to be shown by the dropdown + factory_header.setup.connect (on_factory_header_setup); + factory_header.bind.connect (on_factory_header_bind); + + // This one generates a custom widget for each element in the popup list + factory_list.setup.connect (on_factory_list_setup); + factory_list.bind.connect (on_factory_list_bind); + } + + // ---------------------------------------- + /* DROPDOWN VISIBLE LABEL */ + private void on_factory_header_setup (Gtk.SignalListItemFactory f, Object o) { + var list_item = (Gtk.ListItem)o; + list_item.child = new Gtk.Label (""); + list_item.focusable = true; + } + + private void on_factory_header_bind (Gtk.SignalListItemFactory f, Object o) { + var list_item = (Gtk.ListItem)o; + var item_language = list_item.get_item () as Lang; + var item = list_item.get_child () as Gtk.Label; + item.label = item_language.name; + + // Tell everyone language changed + selection_changed (item_language.code); + //print ("switched to: %s %s\n".printf (item_language.name, item_language.code)); } - private void on_factory_setup (Gtk.SignalListItemFactory f, Object o) { + // ---------------------------------------- + /* DROPDOWN POPUP LIST */ + private void on_factory_list_setup (Gtk.SignalListItemFactory f, Object o) { var list_item = (Gtk.ListItem)o; - var item = new Inscriptions.LanguageItem (list_item.position, ""); + var list_item_child = new Inscriptions.LanguageItem ("", ""); - list_item.child = item; + list_item.child = list_item_child; list_item.focusable = true; } - private void on_factory_bind (Gtk.SignalListItemFactory f, Object o) { + private void on_factory_list_bind (Gtk.SignalListItemFactory f, Object o) { var list_item = (Gtk.ListItem)o; var item_language = list_item.get_item () as Lang; - var item = list_item.get_child() as Inscriptions.LanguageItem; - //print ("position: " + list_item.position.to_string ()); - item.label = item_language.name; + var list_item_child = list_item.get_child() as Inscriptions.LanguageItem; + list_item_child.language_label = item_language.name; + list_item_child.language_code = item_language.code; + + // Listen to language change, let every item sort its shit + selection_changed.connect (list_item_child.on_position_changed); + //print ("binding: %s\n".printf (item_language.name)); } - public void model_append(Lang l) { + + // ---------------------------------------- + /* LIST MANAGEMENT */ + public void model_append (Lang l) { model.append (l); } diff --git a/src/Widgets/LanguageItem.vala b/src/Widgets/LanguageItem.vala index 9e23598..e2a9ace 100644 --- a/src/Widgets/LanguageItem.vala +++ b/src/Widgets/LanguageItem.vala @@ -8,39 +8,47 @@ */ public class Inscriptions.LanguageItem : Gtk.Box { - public uint position {get; construct;} - public bool selected {get; set; default = false;} - public string label {get; set; default = "";} + public string language_label {get; set;} + public string language_code {get; set;} Gtk.Label label_widget; Gtk.Image selected_emblem; - public LanguageItem (uint position, string label) { + public LanguageItem (string language_label, string language_code) { Object ( - position: position, - label: label, + language_label: language_label, + language_code: language_code, orientation: Gtk.Orientation.HORIZONTAL, - spacing: Inscriptions.SPACING_TOOLBAR_HEADER, + spacing: Inscriptions.SPACING_TOOLBAR_MINI, halign: Gtk.Align.CENTER, hexpand: true ); } construct { - label_widget = new Gtk.Label (label); + label_widget = new Gtk.Label (language_label); selected_emblem = new Gtk.Image.from_icon_name ("emblem-default-symbolic") { - visible = selected + visible = false }; - append (label_widget); append (selected_emblem); + append (label_widget); - bind_property ("label", + bind_property ("language-label", label_widget, "label", - GLib.BindingFlags.DEFAULT); + GLib.BindingFlags.DEFAULT | GLib.BindingFlags.SYNC_CREATE); + } + + public void on_position_changed (string language_code_selected) { + print ("checking %s against %s".printf (language_code_selected, language_code)); + + if (language_code_selected == language_code) { + label_widget.add_css_class ("bold"); + selected_emblem.visible = true; - bind_property ("selected", - selected_emblem, "visible", - GLib.BindingFlags.DEFAULT); + } else { + label_widget.remove_css_class ("bold"); + selected_emblem.visible = false; + } } } diff --git a/src/Widgets/Panes/Pane.vala b/src/Widgets/Panes/Pane.vala index 05e7f45..69d5d0d 100644 --- a/src/Widgets/Panes/Pane.vala +++ b/src/Widgets/Panes/Pane.vala @@ -47,13 +47,14 @@ public class Inscriptions.Pane : Gtk.Box { /* ---------------- DROPDOWN ---------------- */ dropdown = new Gtk.DropDown (model.model, expression) { - factory = model.factory, + factory = model.factory_header, + list_factory = model.factory_list, enable_search = true, - search_match_mode= Gtk.StringFilterMatchMode.SUBSTRING + search_match_mode= Gtk.StringFilterMatchMode.SUBSTRING, + show_arrow = false }; dropdown.notify["selected-item"].connect(on_selected_language); - /* ---------------- VIEW ---------------- */ textview = new Inscriptions.TextView (); textview.set_wrap_mode (Gtk.WrapMode.WORD_CHAR); @@ -85,7 +86,6 @@ public class Inscriptions.Pane : Gtk.Box { child = actionbar }; - /* ---------------- STACK ---------------- */ main_view = new Gtk.Box (VERTICAL, 0); @@ -97,7 +97,12 @@ public class Inscriptions.Pane : Gtk.Box { }; stack.add_child (main_view); - append (dropdown); + + var handle_dd = new Gtk.WindowHandle () { + child = dropdown + }; + + append (handle_dd); append (stack); } From 7f28477939cf068291fb98d9b1d9b64fe2932a37 Mon Sep 17 00:00:00 2001 From: teamcons Date: Thu, 26 Feb 2026 22:54:43 +0100 Subject: [PATCH 05/32] nicer checked element --- src/Widgets/LanguageItem.vala | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Widgets/LanguageItem.vala b/src/Widgets/LanguageItem.vala index e2a9ace..5083f83 100644 --- a/src/Widgets/LanguageItem.vala +++ b/src/Widgets/LanguageItem.vala @@ -26,11 +26,16 @@ public class Inscriptions.LanguageItem : Gtk.Box { } construct { - label_widget = new Gtk.Label (language_label); selected_emblem = new Gtk.Image.from_icon_name ("emblem-default-symbolic") { - visible = false + visible = false, + halign = Gtk.Align.START }; + label_widget = new Gtk.Label (language_label) { + halign = Gtk.Align.CENTER + }; + + append (selected_emblem); append (label_widget); From e2ba44b069d74adbeba34ca15827e25d7d4cb9ca Mon Sep 17 00:00:00 2001 From: teamcons Date: Thu, 26 Feb 2026 23:18:20 +0100 Subject: [PATCH 06/32] refine presentation and avoid double language --- src/Constants.vala | 6 +++--- src/Widgets/LanguageItem.vala | 16 ++++++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Constants.vala b/src/Constants.vala index a238eca..8fe1515 100644 --- a/src/Constants.vala +++ b/src/Constants.vala @@ -94,15 +94,15 @@ namespace Inscriptions { public Lang[] TargetLang () { return { new Lang ("system",_("System language")), - new Lang ("AR",_("Arabic")), new Lang ("BG",_("Bulgarian")), new Lang ("CS",_("Czech")), new Lang ("DA",_("Danish")), new Lang ("DE",_("German")), new Lang ("EL",_("Greek")), - new Lang ("EN",_("English (GB)")), - new Lang ("EN",_("English (US)")), + new Lang ("EN-GB",_("English (GB)")), + new Lang ("EN-US",_("English (US)")), + new Lang ("EO",_("Spanish (All)")), new Lang ("ES",_("Spanish (All)")), new Lang ("ES-419",_("Spanish (Latin American)")), new Lang ("ET",_("Estonian")), diff --git a/src/Widgets/LanguageItem.vala b/src/Widgets/LanguageItem.vala index 5083f83..5cec409 100644 --- a/src/Widgets/LanguageItem.vala +++ b/src/Widgets/LanguageItem.vala @@ -19,8 +19,8 @@ public class Inscriptions.LanguageItem : Gtk.Box { language_label: language_label, language_code: language_code, orientation: Gtk.Orientation.HORIZONTAL, - spacing: Inscriptions.SPACING_TOOLBAR_MINI, - halign: Gtk.Align.CENTER, + spacing: 0, + halign: Gtk.Align.FILL, hexpand: true ); } @@ -32,12 +32,17 @@ public class Inscriptions.LanguageItem : Gtk.Box { }; label_widget = new Gtk.Label (language_label) { - halign = Gtk.Align.CENTER + halign = Gtk.Align.CENTER, + hexpand = true, + xalign = 0.5f }; + var overlay = new Gtk.Overlay () { + child = label_widget + }; + overlay.add_overlay (selected_emblem); - append (selected_emblem); - append (label_widget); + append (overlay); bind_property ("language-label", label_widget, "label", @@ -45,7 +50,6 @@ public class Inscriptions.LanguageItem : Gtk.Box { } public void on_position_changed (string language_code_selected) { - print ("checking %s against %s".printf (language_code_selected, language_code)); if (language_code_selected == language_code) { label_widget.add_css_class ("bold"); From e24977b36689ac6ea0d8efa8ac62352e40dcd2f6 Mon Sep 17 00:00:00 2001 From: teamcons Date: Thu, 26 Feb 2026 23:42:18 +0100 Subject: [PATCH 07/32] sensitive clear button --- src/Widgets/Panes/SourcePane.vala | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Widgets/Panes/SourcePane.vala b/src/Widgets/Panes/SourcePane.vala index c6a8fa4..f851996 100644 --- a/src/Widgets/Panes/SourcePane.vala +++ b/src/Widgets/Panes/SourcePane.vala @@ -28,7 +28,7 @@ public class Inscriptions.SourcePane : Inscriptions.Pane { var options_button = new Gtk.MenuButton () { child = options_button_box, tooltip_text = _("Change options for the translation"), - margin_end = 6 + margin_end = MARGIN_MENU_STANDARD }; options_button.add_css_class (Granite.STYLE_CLASS_FLAT); options_button.add_css_class ("flat_menu_button"); @@ -39,22 +39,23 @@ public class Inscriptions.SourcePane : Inscriptions.Pane { actionbar.pack_start (options_button); - var clear = new Gtk.Button.from_icon_name ("edit-clear-all-symbolic") { + var clear_button = new Gtk.Button.from_icon_name ("edit-clear-all-symbolic") { action_name = TranslationView.ACTION_PREFIX + TranslationView.ACTION_CLEAR_TEXT, tooltip_markup = Granite.markup_accel_tooltip ( {"L"}, _("Clear text") ), - margin_start = MARGIN_MENU_HALF + margin_start = MARGIN_MENU_HALF, + sensitive = (text != "") }; - var paste = new Gtk.Button.from_icon_name ("edit-paste-symbolic") { + var paste_button = new Gtk.Button.from_icon_name ("edit-paste-symbolic") { tooltip_text = _("Paste from clipboard"), - margin_start = 3 + margin_start = MARGIN_MENU_HALF }; - actionbar.pack_end (clear); - actionbar.pack_end (paste); + actionbar.pack_end (clear_button); + actionbar.pack_end (paste_button); var open_button = new Gtk.Button.from_icon_name ("document-open-symbolic") { action_name = TranslationView.ACTION_PREFIX + TranslationView.ACTION_LOAD_TEXT, @@ -73,8 +74,12 @@ public class Inscriptions.SourcePane : Inscriptions.Pane { GLib.SettingsBindFlags.DEFAULT ); - paste.clicked.connect (paste_from_clipboard); + paste_button.clicked.connect (paste_from_clipboard); language_changed.connect (on_language_changed); + + textview.buffer.changed.connect (() => { + clear_button.sensitive = (text != ""); + }); } private void on_language_changed (string code) { @@ -100,7 +105,6 @@ public class Inscriptions.SourcePane : Inscriptions.Pane { } public void action_load_text () { - var all_files_filter = new Gtk.FileFilter () { name = _("All files"), }; From 028bc16a89de3996881ba1ac324c4e87f579b313 Mon Sep 17 00:00:00 2001 From: teamcons Date: Fri, 27 Feb 2026 00:00:34 +0100 Subject: [PATCH 08/32] cancellable actions --- src/Widgets/Panes/Pane.vala | 2 ++ src/Widgets/Panes/SourcePane.vala | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Widgets/Panes/Pane.vala b/src/Widgets/Panes/Pane.vala index 69d5d0d..43b1071 100644 --- a/src/Widgets/Panes/Pane.vala +++ b/src/Widgets/Panes/Pane.vala @@ -130,7 +130,9 @@ public class Inscriptions.Pane : Gtk.Box { } public void clear () { + textview.buffer.begin_user_action (); this.textview.buffer.text = ""; + textview.buffer.end_user_action (); } public void message (string text) { diff --git a/src/Widgets/Panes/SourcePane.vala b/src/Widgets/Panes/SourcePane.vala index f851996..34bf183 100644 --- a/src/Widgets/Panes/SourcePane.vala +++ b/src/Widgets/Panes/SourcePane.vala @@ -134,7 +134,9 @@ public class Inscriptions.SourcePane : Inscriptions.Pane { var content = ""; FileUtils.get_contents (file.get_path (), out content); + textview.buffer.begin_user_action (); this.text = content; + textview.buffer.end_user_action (); } catch (Error err) { warning ("Failed to select file to open: %s", err.message); From e7e63f00417da7b0f9d68d56b0f25ab9ebd7c647 Mon Sep 17 00:00:00 2001 From: teamcons Date: Fri, 27 Feb 2026 00:27:06 +0100 Subject: [PATCH 09/32] add undo to toasts --- src/Views/TranslationView.vala | 2 +- src/Widgets/Panes/Pane.vala | 27 ++++++++++++++++++++++++--- src/Widgets/Panes/SourcePane.vala | 11 +++++------ 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/Views/TranslationView.vala b/src/Views/TranslationView.vala index a2a7084..13f5d7a 100644 --- a/src/Views/TranslationView.vala +++ b/src/Views/TranslationView.vala @@ -216,7 +216,7 @@ public class Inscriptions.TranslationView : Gtk.Box { source_pane.clear (); target_pane.clear (); target_pane.show_placeholder (); - source_pane.message (_("Cleared")); + source_pane.message (_("Cleared"), true); } public void action_load_text () { diff --git a/src/Widgets/Panes/Pane.vala b/src/Widgets/Panes/Pane.vala index 43b1071..e620de6 100644 --- a/src/Widgets/Panes/Pane.vala +++ b/src/Widgets/Panes/Pane.vala @@ -104,6 +104,10 @@ public class Inscriptions.Pane : Gtk.Box { append (handle_dd); append (stack); + + toast.default_action.connect (() => { + textview.buffer.undo (); + }); } public void on_selected_language () { @@ -129,14 +133,31 @@ public class Inscriptions.Pane : Gtk.Box { return selected.name; } - public void clear () { + // Respectful of Undo + public void replace_text (string new_text) { + + Gtk.TextIter start, end; + textview.buffer.get_bounds (out start, out end); + textview.buffer.begin_user_action (); - this.textview.buffer.text = ""; + this.textview.buffer.delete (ref start, ref end); + this.textview.buffer.insert (ref start, new_text, new_text.length); textview.buffer.end_user_action (); + + textview.grab_focus (); } - public void message (string text) { + public void clear () { + replace_text (""); + } + + public void message (string text, bool? undo = false) { toast.title = text; + + if (undo) { + toast.set_default_action (_("Undo")); + } + toast.send_notification (); } } diff --git a/src/Widgets/Panes/SourcePane.vala b/src/Widgets/Panes/SourcePane.vala index 34bf183..7930be6 100644 --- a/src/Widgets/Panes/SourcePane.vala +++ b/src/Widgets/Panes/SourcePane.vala @@ -46,7 +46,7 @@ public class Inscriptions.SourcePane : Inscriptions.Pane { _("Clear text") ), margin_start = MARGIN_MENU_HALF, - sensitive = (text != "") + sensitive = false }; var paste_button = new Gtk.Button.from_icon_name ("edit-paste-symbolic") { @@ -95,8 +95,8 @@ public class Inscriptions.SourcePane : Inscriptions.Pane { try { var pasted_text = clipboard.read_text_async.end (res); - textview.buffer.text = pasted_text; - message (_("Pasted")); + replace_text (pasted_text); + message (_("Pasted"), true); } catch (Error e) { print ("Cannot access clipboard: " + e.message); @@ -134,9 +134,8 @@ public class Inscriptions.SourcePane : Inscriptions.Pane { var content = ""; FileUtils.get_contents (file.get_path (), out content); - textview.buffer.begin_user_action (); - this.text = content; - textview.buffer.end_user_action (); + replace_text (content); + message (_("Loaded from file"), true); } catch (Error err) { warning ("Failed to select file to open: %s", err.message); From 63487e09b871cf5c1001948af62583789c9f033c Mon Sep 17 00:00:00 2001 From: teamcons Date: Sat, 28 Feb 2026 12:23:51 +0100 Subject: [PATCH 10/32] introduce initial zooming support (very initial) --- data/Application.css | 20 ++++- src/Enums/ZoomLevel.vala | 86 +++++++++++++++++++++ src/Enums/ZoomType.vala | 30 ++++++++ src/Services/ZoomController.vala | 119 ++++++++++++++++++++++++++++++ src/Widgets/TextView.vala | 2 +- src/Widgets/ZoomableTextView.vala | 29 ++++++++ src/meson.build | 6 ++ 7 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 src/Enums/ZoomLevel.vala create mode 100644 src/Enums/ZoomType.vala create mode 100644 src/Services/ZoomController.vala create mode 100644 src/Widgets/ZoomableTextView.vala diff --git a/data/Application.css b/data/Application.css index fe1c4d1..e808d57 100644 --- a/data/Application.css +++ b/data/Application.css @@ -56,4 +56,22 @@ Base from wpkelso: #33434eff /* Used for labels in the popover */ .bold { font-weight: bold; -} \ No newline at end of file +} + + +/* Font zooms */ +.s20 {font-size: 20%;} +.s40 {font-size: 40%;} +.s60 {font-size: 60%;} +.s80 {font-size: 80%;} +.s100 {font-size: 100%;} +.s120 {font-size: 120%;} +.s140 {font-size: 140%;} +.s160 {font-size: 160%;} +.s180 {font-size: 180%;} +.s200 {font-size: 200%;} +.s220 {font-size: 220%;} +.s240 {font-size: 240%;} +.s260 {font-size: 260%;} +.s280 {font-size: 280%;} +.s300 {font-size: 300%;} \ No newline at end of file diff --git a/src/Enums/ZoomLevel.vala b/src/Enums/ZoomLevel.vala new file mode 100644 index 0000000..b277a6b --- /dev/null +++ b/src/Enums/ZoomLevel.vala @@ -0,0 +1,86 @@ +/* + * SPDX-License-Identifier: GPL-3.0-or-later + * SPDX-FileCopyrightText: 2017-2024 Lains + * 2025 Contributions from the ellie_Commons community (github.com/ellie-commons/) + * 2025-2026 Stella & Charlie (teamcons.carrd.co) + */ + +/*************************************************/ +/** +* A register of all possible zoom values we have +*/ +public enum Inscriptions.ZoomLevel { + ANTSIZED, + MUCHSMALLER, + SMALLER, + SMALL, + NORMAL, + BIG, + BIGGER, + MUCHBIGGER, + MUCHMUCHBIGGER, + HUGE, + SUPERHUGE, + MEGAHUGE, + ULTRAHUGE, + MASSIVE, + URPARENT; + + /*************************************************/ + /** + * Returns an Int representation we can use to display and store the value + */ + public int to_int () { + switch (this) { + case ANTSIZED: return 20; + case MUCHSMALLER: return 40; + case SMALLER: return 60; + case SMALL: return 80; + case NORMAL: return 100; + case BIG: return 120; + case BIGGER: return 140; + case MUCHBIGGER: return 160; + case MUCHMUCHBIGGER: return 180; + case HUGE: return 200; + case SUPERHUGE: return 220; + case MEGAHUGE: return 240; + case ULTRAHUGE: return 260; + case MASSIVE: return 280; + case URPARENT: return 300; + default: return 100; + } + } + + /*************************************************/ + /** + * CSS name is s + size. CSS classes cannot start name with number + */ + public string to_css_class () { + return "s" + this.to_int ().to_string (); + } + + /*************************************************/ + /** + * We cannot save Enums in JSON, so this recovers the enum from stored int + */ + public static ZoomLevel from_int (int wtf_is_this) { + switch (wtf_is_this) { + case 20: return ANTSIZED; + case 40: return MUCHSMALLER; + case 60: return SMALLER; + case 80: return SMALL; + case 100: return NORMAL; + case 120: return BIG; + case 140: return BIGGER; + case 160: return MUCHBIGGER; + case 180: return MUCHMUCHBIGGER; + case 200: return HUGE; + case 220: return SUPERHUGE; + case 240: return MEGAHUGE; + case 260: return ULTRAHUGE; + case 280: return MASSIVE; + case 300: return URPARENT; + default: return NORMAL; + } + } +} diff --git a/src/Enums/ZoomType.vala b/src/Enums/ZoomType.vala new file mode 100644 index 0000000..bbdc38f --- /dev/null +++ b/src/Enums/ZoomType.vala @@ -0,0 +1,30 @@ +/* + * SPDX-License-Identifier: GPL-3.0-or-later + * SPDX-FileCopyrightText: 2017-2024 Lains + * 2025 Contributions from the ellie_Commons community (github.com/ellie-commons/) + * 2025-2026 Stella & Charlie (teamcons.carrd.co) + */ + + /*************************************************/ +/** +* Used in a signal to tell windows in which way to change zoom +*/ + public enum Inscriptions.ZoomType { + ZOOM_OUT, + DEFAULT_ZOOM, + ZOOM_IN, + NONE; + + public static ZoomType from_delta (double delta) { + + if (delta == 0) {return NONE;} + + if (delta > 0) + { + return ZOOM_OUT; + + } else { + return ZOOM_IN; + } + } +} \ No newline at end of file diff --git a/src/Services/ZoomController.vala b/src/Services/ZoomController.vala new file mode 100644 index 0000000..d55dd0e --- /dev/null +++ b/src/Services/ZoomController.vala @@ -0,0 +1,119 @@ +/* + * SPDX-License-Identifier: GPL-3.0-or-later + * SPDX-FileCopyrightText: 2017-2024 Lains + * 2025 Contributions from the ellie_Commons community (github.com/ellie-commons/) + * 2025-2026 Stella & Charlie (teamcons.carrd.co) + */ + +/*************************************************/ +/** +* Responsible to apply zoom appropriately to a window. +* Mainly, this abstracts zoom into an int and swap CSS classes +* As a treat it includes also the plumbing for ctrl+scroll zooming +*/ +public class Inscriptions.ZoomController : Object { + + private static bool is_control_key_pressed = false; + private weak Gtk.Widget widget; + + const int ZOOM_MAX = 300; + const int DEFAULT_ZOOM = 100; + const int ZOOM_MIN = 20; + + + // Avoid setting this unless it is to restore a specific value, do_set_zoom does not check input + private int _old_zoom = DEFAULT_ZOOM; + public int zoom { + get {return _old_zoom;} + set {do_set_zoom (value);} + } + + public ZoomController (Gtk.Widget widget) { + this.widget = widget; + do_set_zoom (DEFAULT_ZOOM); + } + + /** + * Handler. Wraps a zoom enum into the correct function- + */ + public void zoom_changed (ZoomType zoomtype) { + print ("Zoom changed!"); + switch (zoomtype) { + case ZoomType.ZOOM_IN: zoom_in (); return; // vala-lint=double-spaces + case ZoomType.DEFAULT_ZOOM: zoom_default (); return; // vala-lint=double-spaces + case ZoomType.ZOOM_OUT: zoom_out (); return; // vala-lint=double-spaces + default: return; // vala-lint=double-spaces + } + } + + /** + * Wrapper to check an increase doesnt go above limit + */ + public void zoom_in () { + if ((_old_zoom + 20) <= ZOOM_MAX) { + zoom = _old_zoom + 20; + } else { + Gdk.Display.get_default ().beep (); + } + } + + public void zoom_default () { + if (_old_zoom != DEFAULT_ZOOM ) { + zoom = DEFAULT_ZOOM; + } else { + Gdk.Display.get_default ().beep (); + } + } + + /** + * Wrapper to check an increase doesnt go below limit + */ + public void zoom_out () { + if ((_old_zoom - 20) >= ZOOM_MIN) { + zoom = _old_zoom - 20; + } else { + Gdk.Display.get_default ().beep (); + } + } + + /** + * Switch zoom classes, then reflect in the UI and tell the application + */ + private void do_set_zoom (int new_zoom) { + print ("Setting zoom: " + zoom.to_string ()); + + // Switches the classes that control font size + widget.remove_css_class (ZoomLevel.from_int ( _old_zoom).to_css_class ()); + _old_zoom = new_zoom; + widget.add_css_class (ZoomLevel.from_int ( new_zoom).to_css_class ()); + } + + public bool on_key_press_event (uint keyval, uint keycode, Gdk.ModifierType state) { + if (keyval == Gdk.Key.Control_L || keyval == Gdk.Key.Control_R) { + print ("Press!"); + is_control_key_pressed = true; + } + + return Gdk.EVENT_PROPAGATE; + } + + public void on_key_release_event (uint keyval, uint keycode, Gdk.ModifierType state) { + if (keyval == Gdk.Key.Control_L || keyval == Gdk.Key.Control_R) { + print ("Release!"); + is_control_key_pressed = false; + } + } + + public bool on_scroll (double dx, double dy) { + print ("Scroll + Ctrl!"); + + if (!is_control_key_pressed) { + return Gdk.EVENT_PROPAGATE; + } + + zoom_changed (ZoomType.from_delta (dy)); + print ("Go! Zoooommmmm"); + + return Gdk.EVENT_PROPAGATE; + } +} diff --git a/src/Widgets/TextView.vala b/src/Widgets/TextView.vala index ffc7fbe..11b1dde 100644 --- a/src/Widgets/TextView.vala +++ b/src/Widgets/TextView.vala @@ -7,7 +7,7 @@ * A base object that is then subclassed into a SourcePane and a TargetPane. * It takes a DDModel to fill the dropdown with languages */ -public class Inscriptions.TextView : Gtk.TextView { +public class Inscriptions.TextView : Inscriptions.ZoomableTextView { static Gtk.Settings gtk_settings = Gtk.Settings.get_default (); HighlightColor[] all_colors = HighlightColor.all (); diff --git a/src/Widgets/ZoomableTextView.vala b/src/Widgets/ZoomableTextView.vala new file mode 100644 index 0000000..224cd4d --- /dev/null +++ b/src/Widgets/ZoomableTextView.vala @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: GPL-3.0-or-later + * SPDX-FileCopyrightText: 2025 Stella & Charlie (teamcons.carrd.co) + */ + +/** + * A base object that is then subclassed into a SourcePane and a TargetPane. + * It takes a DDModel to fill the dropdown with languages + */ +public class Inscriptions.ZoomableTextView : Gtk.TextView { + private ZoomController zoom_controller; + + construct { + zoom_controller = new ZoomController ((Gtk.Widget)this); + + var keypress_controller = new Gtk.EventControllerKey (); + var scroll_controller = new Gtk.EventControllerScroll (VERTICAL) { + propagation_phase = Gtk.PropagationPhase.CAPTURE + }; + + add_controller (keypress_controller); + add_controller (scroll_controller); + + // We need this for Ctr + Scroll. We delegate everything to zoomcontroller + keypress_controller.key_pressed.connect (zoom_controller.on_key_press_event); + keypress_controller.key_released.connect (zoom_controller.on_key_release_event); + scroll_controller.scroll.connect (zoom_controller.on_scroll); + } +} diff --git a/src/meson.build b/src/meson.build index 880ee6d..c8f3c0d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -34,6 +34,12 @@ sources = files ( 'Widgets' / 'PopoverWidgets' / 'ApiEntry.vala', 'Widgets' / 'PopoverWidgets' / 'ApiLevel.vala', + 'Enums' / 'ZoomType.vala', + 'Enums' / 'ZoomLevel.vala', + 'Services' / 'ZoomController.vala', + 'Widgets' / 'ZoomableTextView.vala', + + 'Views' / 'TranslationView.vala', 'Views' / 'ErrorView.vala', 'Views' / 'LogView.vala', From 39de32c02cc71491ad742b10f56518cd946cc87b Mon Sep 17 00:00:00 2001 From: teamcons Date: Sat, 28 Feb 2026 13:18:31 +0100 Subject: [PATCH 11/32] Use a different approach for editing the UI and shit --- src/Enums/StatusCode.vala | 10 +++- src/Views/ErrorView.vala | 9 ++- src/Widgets/ErrorBonusBox.vala | 22 ++++++- src/Widgets/HeaderBar.vala | 2 +- src/Widgets/Panes/TargetPane.vala | 4 +- src/Widgets/Popovers/SettingsPopover.vala | 71 +++++++---------------- 6 files changed, 59 insertions(+), 59 deletions(-) diff --git a/src/Enums/StatusCode.vala b/src/Enums/StatusCode.vala index eeb7062..c02f968 100644 --- a/src/Enums/StatusCode.vala +++ b/src/Enums/StatusCode.vala @@ -16,7 +16,8 @@ public enum Inscriptions.StatusCode { // Custom NO_KEY = 0, NO_INTERNET = 1, - UNKNOWN = 2, + EDIT_KEY = 2, + UNKNOWN = 3, // 200 OK = Soup.Status.OK, @@ -67,6 +68,13 @@ public enum Inscriptions.StatusCode { } return; + case StatusCode.EDIT_KEY: + explanation_title = _("Edit API Key"); + explanation_text = _("Yo"); + icon_name = "dialog-password"; + return; + + case Soup.Status.OK: explanation_title = _("Everything works great :)"); explanation_text = _("If you see this and are not me, then it means i forgor to disable this error"); diff --git a/src/Views/ErrorView.vala b/src/Views/ErrorView.vala index af6738e..1e734da 100644 --- a/src/Views/ErrorView.vala +++ b/src/Views/ErrorView.vala @@ -11,6 +11,8 @@ public class Inscriptions.ErrorView : Granite.Bin { const uint WAIT_BEFORE_MAIN = 1500; //In milliseconds + ErrorBonusBox bonusbox; + public uint status { get; construct; } public string message { get; construct; } @@ -50,7 +52,8 @@ public class Inscriptions.ErrorView : Granite.Bin { box.append (title); // WEIRD: We get errors about TRUE being out of range for a gboolean and the value defaulting if we leave a default - box.append (new ErrorBonusBox (status, report_link)); + bonusbox = new ErrorBonusBox (status, report_link); + box.append (bonusbox); var retry_button = new Inscriptions.RetryButton () { halign = Gtk.Align.END @@ -81,7 +84,7 @@ public class Inscriptions.ErrorView : Granite.Bin { margin_top = 12 }; - if (status != StatusCode.NO_KEY) { + if (status != StatusCode.NO_KEY || status != StatusCode.EDIT_KEY) { box.append (expander); } @@ -90,10 +93,10 @@ public class Inscriptions.ErrorView : Granite.Bin { }; child = handle; - } private void on_validated () { + bonusbox.usage_revealer.reveal_child = true; Timeout.add_once (WAIT_BEFORE_MAIN, () => { return_to_main (); }); diff --git a/src/Widgets/ErrorBonusBox.vala b/src/Widgets/ErrorBonusBox.vala index 765bc62..764e101 100644 --- a/src/Widgets/ErrorBonusBox.vala +++ b/src/Widgets/ErrorBonusBox.vala @@ -14,6 +14,8 @@ public class Inscriptions.ErrorBonusBox : Gtk.Box { public uint status { get; construct; } public bool if_report { get; construct; } + public Gtk.Revealer usage_revealer; + public ErrorBonusBox (uint status, bool if_report) { Object (status: status, if_report: if_report); @@ -26,7 +28,9 @@ public class Inscriptions.ErrorBonusBox : Gtk.Box { margin_bottom = MARGIN_MENU_STANDARD; // In the event the API is the issue, ask user - if (status == Soup.Status.FORBIDDEN || status == StatusCode.NO_KEY) { + StatusCode[] api_edit_list = {StatusCode.NO_KEY, StatusCode.FORBIDDEN, StatusCode.EDIT_KEY}; + + if (status in api_edit_list) { var api_entry = new Inscriptions.ApiEntry (); @@ -35,7 +39,16 @@ public class Inscriptions.ErrorBonusBox : Gtk.Box { halign = Gtk.Align.START }; - if (status == StatusCode.NO_KEY) { + var api_level = new Inscriptions.ApiLevel (); + usage_revealer = new Gtk.Revealer () { + transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN, + transition_duration = 500, + child = api_level, + reveal_child = (status != StatusCode.NO_KEY) + }; + + + if (status == StatusCode.NO_KEY || status == StatusCode.EDIT_KEY) { var explanation = new Gtk.Label (_("An API Key is like a password given by DeepL\nIt allows you to access services from applications such as this one\nIt looks like this: fr5617a-4875-4763-9119-564tjdvg89:fx")) { wrap_mode = Pango.WrapMode.WORD_CHAR, halign = Gtk.Align.START @@ -47,6 +60,11 @@ public class Inscriptions.ErrorBonusBox : Gtk.Box { append (api_entry); append (link); + append (usage_revealer); + + + + }; diff --git a/src/Widgets/HeaderBar.vala b/src/Widgets/HeaderBar.vala index 7159fc0..771ec22 100644 --- a/src/Widgets/HeaderBar.vala +++ b/src/Widgets/HeaderBar.vala @@ -116,7 +116,7 @@ public class Inscriptions.HeaderBar : Granite.Bin { var toolbar = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 5); toolbar.append (switchlang_button); - toolbar.append (toggle_highlight); + //toolbar.append (toggle_highlight); toolbar_revealer = new Gtk.Revealer () { child = toolbar, diff --git a/src/Widgets/Panes/TargetPane.vala b/src/Widgets/Panes/TargetPane.vala index 52228af..c1830ec 100644 --- a/src/Widgets/Panes/TargetPane.vala +++ b/src/Widgets/Panes/TargetPane.vala @@ -44,7 +44,7 @@ public class Inscriptions.TargetPane : Inscriptions.Pane { }; placeholder_box.append (placeholder); - placeholder_box.append (placeholder_switcher); + //placeholder_box.append (placeholder_switcher); placeholder_handle = new Gtk.WindowHandle () { child = placeholder_box @@ -71,7 +71,7 @@ public class Inscriptions.TargetPane : Inscriptions.Pane { tooltip_text = _("Switch between click to translate // translate %.2fs after typing has stopped").printf (DEBOUNCE_IN_S) }; - actionbar.pack_start (auto_switcher); + //actionbar.pack_start (auto_switcher); /* -------- TOOLBAR -------- */ var copy = new Gtk.Button.from_icon_name ("edit-copy-symbolic") { diff --git a/src/Widgets/Popovers/SettingsPopover.vala b/src/Widgets/Popovers/SettingsPopover.vala index b978458..a32970c 100644 --- a/src/Widgets/Popovers/SettingsPopover.vala +++ b/src/Widgets/Popovers/SettingsPopover.vala @@ -19,48 +19,28 @@ public class Inscriptions.SettingsPopover : Gtk.Popover { margin_bottom = MARGIN_MENU_STANDARD }; - //TRANSLATORS: The two following texts are for a switch button that does not show up in the UI - //The functionality is disabled. You can safely ignore this for the time being + /* -------------------- SEPARATOR -------------------- */ + var auto_switch = new Granite.SwitchModelButton (_("Translate automatically")) { description = _("The translation will start %.2f seconds after typing has stopped".printf (DEBOUNCE_IN_S)), hexpand = true, margin_top = MARGIN_MENU_HALF }; - /* -------------------- SEPARATOR -------------------- */ - var cb = new Gtk.CenterBox () { - margin_end = MARGIN_MENU_BIG - }; - - var api_label = new Gtk.Label (_("DeepL API Key")) { - halign = Gtk.Align.START, - margin_start = MARGIN_MENU_BIG, + var highlight_switch = new Granite.SwitchModelButton (_("Highlight source and target sentences")) { + description = _("Each line will be highlighted a different color to help compare both texts (Ctrl+H)"), + hexpand = true, margin_top = MARGIN_MENU_HALF }; - api_label.add_css_class (Granite.STYLE_CLASS_H4_LABEL); - cb.start_widget = api_label; - - var hint = new Gtk.Button.from_icon_name ("help-contents") { - tooltip_text = _("You can get an API key here") - }; - cb.end_widget = hint; - api_entry = new Inscriptions.ApiEntry () { - margin_start = MARGIN_MENU_BIG, - margin_end = MARGIN_MENU_BIG - }; - - var api_level = new Inscriptions.ApiLevel () { - margin_start = MARGIN_MENU_BIG, - margin_end = MARGIN_MENU_BIG, - margin_top = MARGIN_MENU_HALF + var edit_key_button = new Gtk.Button.with_label (_("Change API Key")) { + tooltip_text = _("Use a different API key of your choosing"), + hexpand = true, + margin_top = MARGIN_MENU_HALF, + halign = Gtk.Align.START }; + edit_key_button.add_css_class (Granite.STYLE_CLASS_FLAT); - usage_revealer = new Gtk.Revealer () { - transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN, - transition_duration = 500, - child = api_level - }; /* -------------------- SEPARATOR -------------------- */ @@ -72,36 +52,27 @@ public class Inscriptions.SettingsPopover : Gtk.Popover { }; box.append (new OrientationBox ()); - //box.append (auto_switch); box.append (new Gtk.Separator (HORIZONTAL)); - box.append (cb); - box.append (api_entry); - box.append (usage_revealer); + box.append (auto_switch); + box.append (highlight_switch); + box.append (edit_key_button); box.append (new Gtk.Separator (HORIZONTAL)); box.append (support_button); child = box; /* -------------------- CONNECTS AND BINDS -------------------- */ - hint.clicked.connect (open_webpage); - api_entry.api_entry.changed.connect (relevant_levelbar); - relevant_levelbar (); - Application.settings.bind ("auto-translate", + Application.settings.bind (KEY_AUTO_TRANSLATE, auto_switch, "active", SettingsBindFlags.DEFAULT); - } - - private void relevant_levelbar () { - usage_revealer.reveal_child = (api_entry.api_entry.text != ""); - } + Application.settings.bind (KEY_HIGHLIGHT, + highlight_switch, "active", + SettingsBindFlags.DEFAULT); - private void open_webpage () { - try { - AppInfo.launch_default_for_uri (LINK, null); - } catch (Error e) { - warning ("%s\n", e.message); - } + edit_key_button.clicked.connect (() => { + Application.backend.answer_received (StatusCode.EDIT_KEY, _("Requested by user")); + }); } } From eeb223347144dbdb37e7ffff6d0eec4fbe2f3809 Mon Sep 17 00:00:00 2001 From: teamcons Date: Sat, 28 Feb 2026 13:19:53 +0100 Subject: [PATCH 12/32] undo draggable dd --- src/Widgets/Panes/Pane.vala | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Widgets/Panes/Pane.vala b/src/Widgets/Panes/Pane.vala index e620de6..b46348f 100644 --- a/src/Widgets/Panes/Pane.vala +++ b/src/Widgets/Panes/Pane.vala @@ -97,12 +97,7 @@ public class Inscriptions.Pane : Gtk.Box { }; stack.add_child (main_view); - - var handle_dd = new Gtk.WindowHandle () { - child = dropdown - }; - - append (handle_dd); + append (dropdown); append (stack); toast.default_action.connect (() => { From 4da5af2741d473dacd476edc68e492d7ac589d5a Mon Sep 17 00:00:00 2001 From: teamcons Date: Sat, 28 Feb 2026 13:47:00 +0100 Subject: [PATCH 13/32] More zoom for your zoom --- data/Application.css | 7 ++++++- src/Services/ZoomController.vala | 2 +- src/Widgets/Popovers/SettingsPopover.vala | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/data/Application.css b/data/Application.css index e808d57..c83b408 100644 --- a/data/Application.css +++ b/data/Application.css @@ -74,4 +74,9 @@ Base from wpkelso: #33434eff .s240 {font-size: 240%;} .s260 {font-size: 260%;} .s280 {font-size: 280%;} -.s300 {font-size: 300%;} \ No newline at end of file +.s300 {font-size: 300%;} +.s320 {font-size: 320%;} +.s340 {font-size: 340%;} +.s360 {font-size: 360%;} +.s380 {font-size: 380%;} +.s400 {font-size: 400%;} diff --git a/src/Services/ZoomController.vala b/src/Services/ZoomController.vala index d55dd0e..a131702 100644 --- a/src/Services/ZoomController.vala +++ b/src/Services/ZoomController.vala @@ -16,7 +16,7 @@ public class Inscriptions.ZoomController : Object { private static bool is_control_key_pressed = false; private weak Gtk.Widget widget; - const int ZOOM_MAX = 300; + const int ZOOM_MAX = 400; const int DEFAULT_ZOOM = 100; const int ZOOM_MIN = 20; diff --git a/src/Widgets/Popovers/SettingsPopover.vala b/src/Widgets/Popovers/SettingsPopover.vala index a32970c..70a00b4 100644 --- a/src/Widgets/Popovers/SettingsPopover.vala +++ b/src/Widgets/Popovers/SettingsPopover.vala @@ -56,6 +56,7 @@ public class Inscriptions.SettingsPopover : Gtk.Popover { box.append (auto_switch); box.append (highlight_switch); box.append (edit_key_button); + box.append (new ApiLevel ()); box.append (new Gtk.Separator (HORIZONTAL)); box.append (support_button); From 1eea656ee77020925a3c99c36b31ea79e79fbd80 Mon Sep 17 00:00:00 2001 From: teamcons Date: Sat, 28 Feb 2026 13:54:30 +0100 Subject: [PATCH 14/32] margins for the api level --- src/Widgets/Popovers/SettingsPopover.vala | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Widgets/Popovers/SettingsPopover.vala b/src/Widgets/Popovers/SettingsPopover.vala index 70a00b4..b0a2285 100644 --- a/src/Widgets/Popovers/SettingsPopover.vala +++ b/src/Widgets/Popovers/SettingsPopover.vala @@ -51,12 +51,18 @@ public class Inscriptions.SettingsPopover : Gtk.Popover { margin_start = MARGIN_MENU_BIG }; + var api_level = new ApiLevel () { + margin_top = MARGIN_MENU_HALF, + margin_start = MARGIN_MENU_BIG, + margin_end = MARGIN_MENU_BIG + }; + box.append (new OrientationBox ()); box.append (new Gtk.Separator (HORIZONTAL)); box.append (auto_switch); box.append (highlight_switch); box.append (edit_key_button); - box.append (new ApiLevel ()); + box.append (api_level); box.append (new Gtk.Separator (HORIZONTAL)); box.append (support_button); From 5b174a20627a43f331403de66485dee0b8e6dc74 Mon Sep 17 00:00:00 2001 From: teamcons Date: Sat, 28 Feb 2026 14:18:41 +0100 Subject: [PATCH 15/32] Refine UI and fix zoom --- src/Services/ZoomController.vala | 6 +++--- src/Widgets/ErrorBonusBox.vala | 4 ++-- src/Widgets/PopoverWidgets/ApiLevel.vala | 17 ++++++++++++++++- src/Widgets/Popovers/SettingsPopover.vala | 20 +++----------------- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/Services/ZoomController.vala b/src/Services/ZoomController.vala index a131702..2dd2fe7 100644 --- a/src/Services/ZoomController.vala +++ b/src/Services/ZoomController.vala @@ -16,7 +16,7 @@ public class Inscriptions.ZoomController : Object { private static bool is_control_key_pressed = false; private weak Gtk.Widget widget; - const int ZOOM_MAX = 400; + const int ZOOM_MAX = 300; const int DEFAULT_ZOOM = 100; const int ZOOM_MIN = 20; @@ -105,14 +105,14 @@ public class Inscriptions.ZoomController : Object { } public bool on_scroll (double dx, double dy) { - print ("Scroll + Ctrl!"); + //print ("Scroll + Ctrl!"); if (!is_control_key_pressed) { return Gdk.EVENT_PROPAGATE; } zoom_changed (ZoomType.from_delta (dy)); - print ("Go! Zoooommmmm"); + //print ("Go! Zoooommmmm"); return Gdk.EVENT_PROPAGATE; } diff --git a/src/Widgets/ErrorBonusBox.vala b/src/Widgets/ErrorBonusBox.vala index 764e101..5f6ca0c 100644 --- a/src/Widgets/ErrorBonusBox.vala +++ b/src/Widgets/ErrorBonusBox.vala @@ -48,7 +48,7 @@ public class Inscriptions.ErrorBonusBox : Gtk.Box { }; - if (status == StatusCode.NO_KEY || status == StatusCode.EDIT_KEY) { + if (status == StatusCode.NO_KEY || status == StatusCode.FORBIDDEN) { var explanation = new Gtk.Label (_("An API Key is like a password given by DeepL\nIt allows you to access services from applications such as this one\nIt looks like this: fr5617a-4875-4763-9119-564tjdvg89:fx")) { wrap_mode = Pango.WrapMode.WORD_CHAR, halign = Gtk.Align.START @@ -60,7 +60,7 @@ public class Inscriptions.ErrorBonusBox : Gtk.Box { append (api_entry); append (link); - append (usage_revealer); + //append (usage_revealer); diff --git a/src/Widgets/PopoverWidgets/ApiLevel.vala b/src/Widgets/PopoverWidgets/ApiLevel.vala index df2e12c..aa5446f 100644 --- a/src/Widgets/PopoverWidgets/ApiLevel.vala +++ b/src/Widgets/PopoverWidgets/ApiLevel.vala @@ -33,13 +33,28 @@ public class Inscriptions.ApiLevel : Gtk.Box { loading = new Gtk.Spinner (); refresher.add_named (loading, "loading"); + var minibox = new Gtk.Box (Gtk.Orientation.HORIZONTAL, Inscriptions.SPACING_TOOLBAR_MINI) { + valign = Gtk.Align.CENTER + }; + + var edit_key_button = new Gtk.Button.from_icon_name ("dialog-password") { + tooltip_text = _("Use a different API key of your choosing"), + }; + edit_key_button.add_css_class (Granite.STYLE_CLASS_FLAT); + edit_key_button.clicked.connect (() => { + Application.backend.answer_received (StatusCode.EDIT_KEY, _("Requested by user")); + }); + var hint = new Gtk.Button.from_icon_name ("view-refresh") { tooltip_text = _("Update API usage") }; refresher.add_named (hint, "hint"); refresher.visible_child_name = "hint"; - cb.end_widget = refresher; + + minibox.append (edit_key_button); + minibox.append (refresher); + cb.end_widget = minibox; append (cb); diff --git a/src/Widgets/Popovers/SettingsPopover.vala b/src/Widgets/Popovers/SettingsPopover.vala index b0a2285..7d9989b 100644 --- a/src/Widgets/Popovers/SettingsPopover.vala +++ b/src/Widgets/Popovers/SettingsPopover.vala @@ -23,24 +23,14 @@ public class Inscriptions.SettingsPopover : Gtk.Popover { var auto_switch = new Granite.SwitchModelButton (_("Translate automatically")) { description = _("The translation will start %.2f seconds after typing has stopped".printf (DEBOUNCE_IN_S)), - hexpand = true, - margin_top = MARGIN_MENU_HALF + hexpand = true }; var highlight_switch = new Granite.SwitchModelButton (_("Highlight source and target sentences")) { description = _("Each line will be highlighted a different color to help compare both texts (Ctrl+H)"), - hexpand = true, - margin_top = MARGIN_MENU_HALF + hexpand = true }; - var edit_key_button = new Gtk.Button.with_label (_("Change API Key")) { - tooltip_text = _("Use a different API key of your choosing"), - hexpand = true, - margin_top = MARGIN_MENU_HALF, - halign = Gtk.Align.START - }; - edit_key_button.add_css_class (Granite.STYLE_CLASS_FLAT); - /* -------------------- SEPARATOR -------------------- */ @@ -61,7 +51,7 @@ public class Inscriptions.SettingsPopover : Gtk.Popover { box.append (new Gtk.Separator (HORIZONTAL)); box.append (auto_switch); box.append (highlight_switch); - box.append (edit_key_button); + //box.append (edit_key_button); box.append (api_level); box.append (new Gtk.Separator (HORIZONTAL)); box.append (support_button); @@ -77,9 +67,5 @@ public class Inscriptions.SettingsPopover : Gtk.Popover { Application.settings.bind (KEY_HIGHLIGHT, highlight_switch, "active", SettingsBindFlags.DEFAULT); - - edit_key_button.clicked.connect (() => { - Application.backend.answer_received (StatusCode.EDIT_KEY, _("Requested by user")); - }); } } From a93c4e1398686fca5f5ce9355aa7c76ff8eb8971 Mon Sep 17 00:00:00 2001 From: teamcons Date: Sat, 28 Feb 2026 14:33:06 +0100 Subject: [PATCH 16/32] do not use a stack for the spinner/refresh combo --- src/Widgets/LanguageItem.vala | 1 + src/Widgets/PopoverWidgets/ApiLevel.vala | 45 +++++++++++++----------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/Widgets/LanguageItem.vala b/src/Widgets/LanguageItem.vala index 5cec409..b99c74c 100644 --- a/src/Widgets/LanguageItem.vala +++ b/src/Widgets/LanguageItem.vala @@ -30,6 +30,7 @@ public class Inscriptions.LanguageItem : Gtk.Box { visible = false, halign = Gtk.Align.START }; + selected_emblem.add_css_class (Granite.STYLE_CLASS_FLAT); label_widget = new Gtk.Label (language_label) { halign = Gtk.Align.CENTER, diff --git a/src/Widgets/PopoverWidgets/ApiLevel.vala b/src/Widgets/PopoverWidgets/ApiLevel.vala index aa5446f..f3e0911 100644 --- a/src/Widgets/PopoverWidgets/ApiLevel.vala +++ b/src/Widgets/PopoverWidgets/ApiLevel.vala @@ -10,8 +10,8 @@ public class Inscriptions.ApiLevel : Gtk.Box { Gtk.LevelBar api_usage; - Gtk.Spinner loading; - Gtk.Stack refresher; + Gtk.Spinner spinner; + Gtk.Button refresh_button; construct { orientation = Gtk.Orientation.VERTICAL; @@ -28,13 +28,14 @@ public class Inscriptions.ApiLevel : Gtk.Box { api_usage_label.add_css_class (Granite.STYLE_CLASS_H4_LABEL); cb.start_widget = api_usage_label; - refresher = new Gtk.Stack (); + spinner = new Gtk.Spinner () { + spinning = false, + visible = false + }; - loading = new Gtk.Spinner (); - refresher.add_named (loading, "loading"); - var minibox = new Gtk.Box (Gtk.Orientation.HORIZONTAL, Inscriptions.SPACING_TOOLBAR_MINI) { - valign = Gtk.Align.CENTER + refresh_button = new Gtk.Button.from_icon_name ("view-refresh") { + tooltip_text = _("Update API usage") }; var edit_key_button = new Gtk.Button.from_icon_name ("dialog-password") { @@ -45,15 +46,15 @@ public class Inscriptions.ApiLevel : Gtk.Box { Application.backend.answer_received (StatusCode.EDIT_KEY, _("Requested by user")); }); - var hint = new Gtk.Button.from_icon_name ("view-refresh") { - tooltip_text = _("Update API usage") - }; - refresher.add_named (hint, "hint"); - refresher.visible_child_name = "hint"; + var minibox = new Gtk.Box (Gtk.Orientation.HORIZONTAL, Inscriptions.SPACING_TOOLBAR_MINI) { + valign = Gtk.Align.CENTER + }; minibox.append (edit_key_button); - minibox.append (refresher); + minibox.append (spinner); + minibox.append (refresh_button); + cb.end_widget = minibox; append (cb); @@ -63,10 +64,18 @@ public class Inscriptions.ApiLevel : Gtk.Box { api_usage.min_value = 0; append (api_usage); + spinner.bind_property ("spinning", + refresh_button, "visible", + GLib.BindingFlags.INVERT_BOOLEAN | GLib.BindingFlags.SYNC_CREATE); + + spinner.bind_property ("spinning", + spinner, "visible", + GLib.BindingFlags.DEFAULT | GLib.BindingFlags.SYNC_CREATE); + Application.settings.bind ("current-usage", api_usage, "value", SettingsBindFlags.DEFAULT); Application.settings.bind ("max-usage", api_usage, "max-value", SettingsBindFlags.DEFAULT); - hint.clicked.connect (on_refresh); + refresh_button.clicked.connect (on_refresh); Application.backend.answer_received.connect (updated_usage); Application.backend.usage_retrieved.connect (updated_usage); updated_usage (); @@ -96,15 +105,11 @@ public class Inscriptions.ApiLevel : Gtk.Box { Application.settings.get_int ("current-usage").to_string (), Application.settings.get_int ("max-usage").to_string ()); - if (refresher.visible_child_name == "loading") { - refresher.visible_child_name = "hint"; - loading.spinning = false; - } + spinner.spinning = false; } private void on_refresh () { - loading.spinning = true; - refresher.visible_child_name = "loading"; + spinner.spinning = true; Application.backend.check_usage (); } } From 8fba77b2663105be6c87cce3d1019bae897430cb Mon Sep 17 00:00:00 2001 From: teamcons Date: Sun, 1 Mar 2026 23:59:30 +0100 Subject: [PATCH 17/32] allow having a devel version --- meson.build | 21 ++++++++++++++++++++- meson_options.txt | 1 + src/Windows/MainWindow.vala | 3 +++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 meson_options.txt diff --git a/meson.build b/meson.build index bf67c34..75226c8 100644 --- a/meson.build +++ b/meson.build @@ -12,9 +12,28 @@ i18n = import('i18n') # Set our translation domain add_global_arguments('-DGETTEXT_PACKAGE="@0@"'.format (meson.project_name()), language:'c') +vala_flags = [] + + +if get_option('development') + app_id = app_id + 'io.github.elly_code.inscriptions.Devel' + name_prefix = '(Nightly) ' + vcs_tag = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip() + version_suffix = '-@0@'.format (vcs_tag) + + vala_flags += ['--define', 'DEVEL'] + +else + app_id = 'io.github.elly_code.inscriptions' + name_prefix = '' + version_suffix = '' +endif + + + windows_build = build_machine.system() == 'windows' -vala_flags = [] + # Windows needs icons, special arguments, and skip libportal if windows_build vala_flags += ['--define', 'WINDOWS'] diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..57ae49d --- /dev/null +++ b/meson_options.txt @@ -0,0 +1 @@ +option('development', type: 'boolean', value: false, description: 'If this is a development build') \ No newline at end of file diff --git a/src/Windows/MainWindow.vala b/src/Windows/MainWindow.vala index 56d9659..093f762 100644 --- a/src/Windows/MainWindow.vala +++ b/src/Windows/MainWindow.vala @@ -25,6 +25,9 @@ public class Inscriptions.MainWindow : Gtk.ApplicationWindow { default_width = Application.settings.get_int (KEY_WINDOW_WIDTH); maximized = Application.settings.get_boolean (KEY_WINDOW_MAXIMIZED); +#if DEVEL + add_css_class ("devel"); +#endif /* ---------------- HEADERBAR ---------------- */ From 749bf6c85582f7a267a43a038203d48532fc8883 Mon Sep 17 00:00:00 2001 From: teamcons Date: Sun, 1 Mar 2026 23:59:46 +0100 Subject: [PATCH 18/32] allow having a devel version --- data/Application.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/data/Application.css b/data/Application.css index c83b408..c48c958 100644 --- a/data/Application.css +++ b/data/Application.css @@ -80,3 +80,9 @@ Base from wpkelso: #33434eff .s360 {font-size: 360%;} .s380 {font-size: 380%;} .s400 {font-size: 400%;} + +window.devel { + border-style: solid; + border-width: 3px; + border-color: red; +} \ No newline at end of file From e4f26dbad99a4887d6db55c8e4e804ff1eec7bf2 Mon Sep 17 00:00:00 2001 From: teamcons Date: Mon, 2 Mar 2026 00:29:48 +0100 Subject: [PATCH 19/32] nicer looking warning color --- data/Application.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/Application.css b/data/Application.css index c48c958..5dbed3e 100644 --- a/data/Application.css +++ b/data/Application.css @@ -58,7 +58,6 @@ Base from wpkelso: #33434eff font-weight: bold; } - /* Font zooms */ .s20 {font-size: 20%;} .s40 {font-size: 40%;} @@ -81,8 +80,9 @@ Base from wpkelso: #33434eff .s380 {font-size: 380%;} .s400 {font-size: 400%;} +/* Devel builds get these. Libadwaita has that too, but we do not use it. */ window.devel { border-style: solid; border-width: 3px; - border-color: red; + border-color: @warning_color; } \ No newline at end of file From 415d2048fb977dd4ea2a26d0289146ebecfbcfbe Mon Sep 17 00:00:00 2001 From: teamcons Date: Mon, 2 Mar 2026 00:37:30 +0100 Subject: [PATCH 20/32] Set more for devel --- meson.build | 1 - src/Config.vala.in | 3 ++- src/Constants.vala | 7 ++++++- src/Widgets/HeaderBar.vala | 5 +++++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/meson.build b/meson.build index 75226c8..7d82310 100644 --- a/meson.build +++ b/meson.build @@ -20,7 +20,6 @@ if get_option('development') name_prefix = '(Nightly) ' vcs_tag = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip() version_suffix = '-@0@'.format (vcs_tag) - vala_flags += ['--define', 'DEVEL'] else diff --git a/src/Config.vala.in b/src/Config.vala.in index a3c7bd4..2f445fb 100644 --- a/src/Config.vala.in +++ b/src/Config.vala.in @@ -1,2 +1,3 @@ public const string GETTEXT_PACKAGE = @GETTEXT_PACKAGE@; -public const string LOCALEDIR = @LOCALEDIR@; \ No newline at end of file +public const string LOCALEDIR = @LOCALEDIR@; +public const string APP_ID = @app_id@; \ No newline at end of file diff --git a/src/Constants.vala b/src/Constants.vala index 8fe1515..d1672e5 100644 --- a/src/Constants.vala +++ b/src/Constants.vala @@ -6,7 +6,12 @@ namespace Inscriptions { // Alkrjnlgjrt - public const string RDNN = "io.github.elly_code.inscriptions"; +#if DEVEL + public const string RDNN = "io.github.elly_code.inscriptions.Devel"; +#else + public const string RDNN = "io.github.elly_code.inscriptions"; +#endif + public const string DONATE_LINK = "https://ko-fi.com/teamcons/tip"; public const string LINK = "https://www.deepl.com/your-account/keys"; public const int DEBOUNCE_INTERVAL = 1250; // ms diff --git a/src/Widgets/HeaderBar.vala b/src/Widgets/HeaderBar.vala index 771ec22..c816bfa 100644 --- a/src/Widgets/HeaderBar.vala +++ b/src/Widgets/HeaderBar.vala @@ -66,6 +66,11 @@ public class Inscriptions.HeaderBar : Granite.Bin { app.set_accels_for_action (ACTION_PREFIX + ACTION_TOGGLE_MESSAGES, {"m"}); title_label = new Gtk.Label (_("Inscriptions")); +#if DEVEL + // This appears besides the name only in development version + title_label = title_label + _(" (Devel)"); +#endif + title_label.add_css_class (Granite.STYLE_CLASS_TITLE_LABEL); title_switcher = new Gtk.StackSwitcher () { From 0cbf1d0aeddd43fc2925599761ed4055859813e7 Mon Sep 17 00:00:00 2001 From: teamcons Date: Mon, 2 Mar 2026 01:03:21 +0100 Subject: [PATCH 21/32] fix a slight mistake and add a devel manifest --- io.github.elly_code.inscriptions.devel.yml | 40 ++++++++++++++++++++++ meson.build | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 io.github.elly_code.inscriptions.devel.yml diff --git a/io.github.elly_code.inscriptions.devel.yml b/io.github.elly_code.inscriptions.devel.yml new file mode 100644 index 0000000..cc41062 --- /dev/null +++ b/io.github.elly_code.inscriptions.devel.yml @@ -0,0 +1,40 @@ +id: io.github.elly_code.inscriptions.Devel +# elementary SDK is not available on Flathub, so use the elementary BaseApp instead +base: io.elementary.BaseApp +base-version: 'circe-25.08' +runtime: org.gnome.Platform +runtime-version: '49' +sdk: org.gnome.Sdk +command: io.github.elly_code.inscriptions + +tags: devel +desktop-file-name-prefix: "(devel)" + +finish-args: + - '--share=ipc' + - '--device=dri' + - '--socket=fallback-x11' + - '--socket=wayland' + # Required for communication with DeepL API + - '--share=network' + +cleanup: + - '/include' + - '/lib/pkgconfig' + - '/man' + - '/share/doc' + - '/share/gtk-doc' + - '/share/man' + - '/share/pkgconfig' + - '/share/installed-tests' + - '*.la' + - '*.a' + +modules: + - name: inscriptions + buildsystem: meson + config-opts: + - -Ddevelopment=true + sources: + - type: dir + path: . \ No newline at end of file diff --git a/meson.build b/meson.build index 7d82310..f9daf06 100644 --- a/meson.build +++ b/meson.build @@ -16,7 +16,7 @@ vala_flags = [] if get_option('development') - app_id = app_id + 'io.github.elly_code.inscriptions.Devel' + app_id = 'io.github.elly_code.inscriptions.Devel' name_prefix = '(Nightly) ' vcs_tag = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip() version_suffix = '-@0@'.format (vcs_tag) From 412345745f3e065c379390ff61ff53d75b2de0b4 Mon Sep 17 00:00:00 2001 From: teamcons Date: Mon, 2 Mar 2026 21:02:56 +0100 Subject: [PATCH 22/32] Allow building a devel version aside from the standard one --- ....desktop.in => inscriptions.desktop.in.in} | 6 +- ...schema.xml => inscriptions.gschema.xml.in} | 2 +- ...xml.in => inscriptions.metainfo.xml.in.in} | 6 +- data/meson.build | 82 +++++++++++++++---- io.github.elly_code.inscriptions.devel.yml | 8 +- meson.build | 15 +++- src/Config.vala.in | 4 +- src/Constants.vala | 2 +- src/Widgets/HeaderBar.vala | 2 +- src/meson.build | 2 +- 10 files changed, 92 insertions(+), 37 deletions(-) rename data/{inscriptions.desktop.in => inscriptions.desktop.in.in} (77%) rename data/{inscriptions.gschema.xml => inscriptions.gschema.xml.in} (97%) rename data/{inscriptions.metainfo.xml.in => inscriptions.metainfo.xml.in.in} (95%) diff --git a/data/inscriptions.desktop.in b/data/inscriptions.desktop.in.in similarity index 77% rename from data/inscriptions.desktop.in rename to data/inscriptions.desktop.in.in index 775fb60..50295dc 100644 --- a/data/inscriptions.desktop.in +++ b/data/inscriptions.desktop.in.in @@ -2,11 +2,11 @@ Version=1.0 Type=Application -Name=Inscriptions +Name=@APP_NAME@ GenericName=Text translator Comment=Translate text elegantly -Icon=io.github.elly_code.inscriptions -Exec=io.github.elly_code.inscriptions %U +Icon=@APP_ID@ +Exec=@APP_ID@ %U Categories=Office;Education;GTK; Keywords=text;translate;translation;translator;deepl;NMT;lang;localize;l10n;i18n;localization;internationalization; diff --git a/data/inscriptions.gschema.xml b/data/inscriptions.gschema.xml.in similarity index 97% rename from data/inscriptions.gschema.xml rename to data/inscriptions.gschema.xml.in index 828c18c..d0763a1 100644 --- a/data/inscriptions.gschema.xml +++ b/data/inscriptions.gschema.xml.in @@ -8,7 +8,7 @@ - + 320 Most recent window height diff --git a/data/inscriptions.metainfo.xml.in b/data/inscriptions.metainfo.xml.in.in similarity index 95% rename from data/inscriptions.metainfo.xml.in rename to data/inscriptions.metainfo.xml.in.in index 475bb7c..e6a1667 100644 --- a/data/inscriptions.metainfo.xml.in +++ b/data/inscriptions.metainfo.xml.in.in @@ -1,8 +1,8 @@ - io.github.elly_code.inscriptions - io.github.elly_code.inscriptions.desktop - io.github.elly_code.inscriptions + @APP_ID@ + @APP_ID@.desktop + @GETTEXT_PACKAGE@ CC-BY-4.0 GPL-3.0-or-later diff --git a/data/meson.build b/data/meson.build index 4b2638b..2c23e6a 100644 --- a/data/meson.build +++ b/data/meson.build @@ -1,9 +1,4 @@ -install_data( - 'inscriptions.gschema.xml', - install_dir: get_option('datadir') / 'glib-2.0' / 'schemas', - rename: meson.project_name() + '.gschema.xml' -) # metainfo confuses windows, and icons are if not windows_build @@ -14,32 +9,83 @@ if not windows_build install_data( 'icons' / 'hicolor' / i + '.png', install_dir: get_option('datadir') / 'icons' / 'hicolor' / i + 'x' + i / 'apps', - rename: meson.project_name() + '.png' + rename: app_id + '.png' ) install_data( 'icons' / 'hicolor@2' / i + '@2.png', install_dir: get_option('datadir') / 'icons' / 'hicolor' / i + 'x' + i + '@2' / 'apps', - rename: meson.project_name() + '.png' + rename: app_id + '.png' ) endforeach + # Inject some variables into the desktop file before merging in the translations + desktop_conf = configuration_data() + desktop_conf.set('APP_NAME', app_name) + desktop_conf.set('APP_ID', app_id) + desktop_file_in = configure_file( + input: 'inscriptions.desktop.in.in', + output: '@0@.desktop.in'.format(app_id), + configuration: desktop_conf, + ) + desktop_file = i18n.merge_file( + input: desktop_file_in, + output: '@0@.desktop'.format(app_id), + po_dir: meson.project_source_root() / 'po', + type: 'desktop', + install: true, + install_dir: get_option('datadir') / 'applications', + ) - i18n.merge_file( - input: 'inscriptions.desktop.in', - output: meson.project_name() + '.desktop', - po_dir: meson.project_source_root() / 'po', - type: 'desktop', - install: true, - install_dir: get_option('datadir') / 'applications' + + # Inject some variables into the metainfo file before merging in the translations + appstream_conf = configuration_data() + appstream_conf.set('APP_ID', app_id) + appstream_conf.set('GETTEXT_PACKAGE', meson.project_name()) + appstream_file_in = configure_file( + input: 'inscriptions.metainfo.xml.in.in', + output: '@0@.metainfo.xml.in'.format(app_id), + configuration: appstream_conf, ) - i18n.merge_file( - input: 'inscriptions.metainfo.xml.in', - output: meson.project_name() + '.metainfo.xml', + appstream_file = i18n.merge_file( + input: appstream_file_in, + output: '@0@.metainfo.xml'.format(app_id), po_dir: meson.project_source_root() / 'po', install: true, - install_dir: get_option('datadir') / 'metainfo' + install_dir: get_option('datadir') / 'metainfo', + ) + + gschema_conf = configuration_data() + gschema_conf.set('APP_ID', app_id) + gschema_file = configure_file( + input: 'inscriptions.gschema.xml.in', + output: '@0@.gschema.xml'.format(app_id), + configuration: gschema_conf, + ) + + install_data( + gschema_file, + install_dir: get_option('datadir') / 'glib-2.0' / 'schemas', + ) + + + # Test definitions + desktop_utils = find_program('desktop-file-validate', required: false) + if desktop_utils.found() + test('Validate desktop file', desktop_utils, args: [desktop_file]) + endif + + appstreamcli = find_program('appstreamcli', required: false, disabler: true) + test('Validate appstream file', + appstreamcli, + args: ['validate', '--no-net', '--explain', appstream_file], + ) + + compile_schemas = find_program('glib-compile-schemas', required: false, disabler: true) + test('Validate schema file', + compile_schemas, + args: ['--strict', '--dry-run', meson.current_source_dir()], ) endif \ No newline at end of file diff --git a/io.github.elly_code.inscriptions.devel.yml b/io.github.elly_code.inscriptions.devel.yml index cc41062..bbfb00c 100644 --- a/io.github.elly_code.inscriptions.devel.yml +++ b/io.github.elly_code.inscriptions.devel.yml @@ -1,14 +1,14 @@ -id: io.github.elly_code.inscriptions.Devel +id: io.github.elly_code.inscriptions.devel # elementary SDK is not available on Flathub, so use the elementary BaseApp instead base: io.elementary.BaseApp base-version: 'circe-25.08' runtime: org.gnome.Platform runtime-version: '49' sdk: org.gnome.Sdk -command: io.github.elly_code.inscriptions +command: io.github.elly_code.inscriptions.devel -tags: devel -desktop-file-name-prefix: "(devel)" +tags: ['devel'] +desktop-file-name-prefix: '(devel)' finish-args: - '--share=ipc' diff --git a/meson.build b/meson.build index f9daf06..b938528 100644 --- a/meson.build +++ b/meson.build @@ -2,9 +2,13 @@ project( 'io.github.elly_code.inscriptions', 'vala', 'c', - version: '1.0.1' + version: '1.1.0' ) +app_name = 'Inscriptions' +app_id = meson.project_name() +app_version = meson.project_version() + #================================ # Include Gnome and the translations module gnome = import('gnome') @@ -16,14 +20,13 @@ vala_flags = [] if get_option('development') - app_id = 'io.github.elly_code.inscriptions.Devel' - name_prefix = '(Nightly) ' + app_id += '.devel' + name_prefix = '(devel) ' vcs_tag = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip() version_suffix = '-@0@'.format (vcs_tag) vala_flags += ['--define', 'DEVEL'] else - app_id = 'io.github.elly_code.inscriptions' name_prefix = '' version_suffix = '' endif @@ -46,6 +49,10 @@ config_data = configuration_data() config_data.set('version', meson.project_version()) config_data.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir')) config_data.set_quoted('GETTEXT_PACKAGE', meson.project_name()) +config_data.set_quoted('APP_NAME', app_name) +config_data.set_quoted('APP_ID', app_id) +config_data.set_quoted('APP_VERSION', app_version) + config_file = configure_file( input: 'src/Config.vala.in', output: '@BASENAME@', diff --git a/src/Config.vala.in b/src/Config.vala.in index 2f445fb..5390828 100644 --- a/src/Config.vala.in +++ b/src/Config.vala.in @@ -1,3 +1,5 @@ public const string GETTEXT_PACKAGE = @GETTEXT_PACKAGE@; public const string LOCALEDIR = @LOCALEDIR@; -public const string APP_ID = @app_id@; \ No newline at end of file +public const string APP_NAME = @APP_NAME@; +public const string APP_ID = @APP_ID@; +public const string APP_VERSION = @APP_VERSION@; \ No newline at end of file diff --git a/src/Constants.vala b/src/Constants.vala index d1672e5..868a376 100644 --- a/src/Constants.vala +++ b/src/Constants.vala @@ -7,7 +7,7 @@ namespace Inscriptions { // Alkrjnlgjrt #if DEVEL - public const string RDNN = "io.github.elly_code.inscriptions.Devel"; + public const string RDNN = "io.github.elly_code.inscriptions.devel"; #else public const string RDNN = "io.github.elly_code.inscriptions"; #endif diff --git a/src/Widgets/HeaderBar.vala b/src/Widgets/HeaderBar.vala index c816bfa..44435f0 100644 --- a/src/Widgets/HeaderBar.vala +++ b/src/Widgets/HeaderBar.vala @@ -68,7 +68,7 @@ public class Inscriptions.HeaderBar : Granite.Bin { title_label = new Gtk.Label (_("Inscriptions")); #if DEVEL // This appears besides the name only in development version - title_label = title_label + _(" (Devel)"); + title_label.label += _(" (devel)"); #endif title_label.add_css_class (Granite.STYLE_CLASS_TITLE_LABEL); diff --git a/src/meson.build b/src/meson.build index c8f3c0d..bb2893f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -50,7 +50,7 @@ sources = files ( # Create a new executable, list the files we want to compile, and install executable( - meson.project_name (), + app_id, config_file, gresource, sources, From c20ad25e516349885130e238df3385c3b7de856f Mon Sep 17 00:00:00 2001 From: teamcons Date: Mon, 2 Mar 2026 21:06:20 +0100 Subject: [PATCH 23/32] oops i forgot this one --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index b938528..23c7ffc 100644 --- a/meson.build +++ b/meson.build @@ -15,7 +15,7 @@ gnome = import('gnome') i18n = import('i18n') # Set our translation domain -add_global_arguments('-DGETTEXT_PACKAGE="@0@"'.format (meson.project_name()), language:'c') +add_global_arguments('-DGETTEXT_PACKAGE="@0@"'.format (app_id), language:'c') vala_flags = [] From 7696222bfd2a2ded24b1b71cb8228b1b160502a5 Mon Sep 17 00:00:00 2001 From: teamcons Date: Mon, 2 Mar 2026 21:06:54 +0100 Subject: [PATCH 24/32] heads up in manifest --- io.github.elly_code.inscriptions.devel.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/io.github.elly_code.inscriptions.devel.yml b/io.github.elly_code.inscriptions.devel.yml index bbfb00c..548af31 100644 --- a/io.github.elly_code.inscriptions.devel.yml +++ b/io.github.elly_code.inscriptions.devel.yml @@ -1,3 +1,6 @@ +# +# This is danger +# id: io.github.elly_code.inscriptions.devel # elementary SDK is not available on Flathub, so use the elementary BaseApp instead base: io.elementary.BaseApp From 7857e2cd81759d3b1ad50dd68e27e3e5d3f0e66e Mon Sep 17 00:00:00 2001 From: teamcons Date: Mon, 2 Mar 2026 21:08:28 +0100 Subject: [PATCH 25/32] avoid losing gettext --- meson.build | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/meson.build b/meson.build index 23c7ffc..ee8b781 100644 --- a/meson.build +++ b/meson.build @@ -14,8 +14,7 @@ app_version = meson.project_version() gnome = import('gnome') i18n = import('i18n') -# Set our translation domain -add_global_arguments('-DGETTEXT_PACKAGE="@0@"'.format (app_id), language:'c') + vala_flags = [] @@ -31,12 +30,11 @@ else version_suffix = '' endif - - -windows_build = build_machine.system() == 'windows' - +# Set our translation domain +add_global_arguments('-DGETTEXT_PACKAGE="@0@"'.format (app_id), language:'c') # Windows needs icons, special arguments, and skip libportal +windows_build = build_machine.system() == 'windows' if windows_build vala_flags += ['--define', 'WINDOWS'] endif From 369b0270e5b5cf842c6441e1a6206d1c1867fac7 Mon Sep 17 00:00:00 2001 From: teamcons Date: Mon, 2 Mar 2026 21:16:47 +0100 Subject: [PATCH 26/32] correct another miss --- meson.build | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/meson.build b/meson.build index ee8b781..85dc04a 100644 --- a/meson.build +++ b/meson.build @@ -16,8 +16,6 @@ i18n = import('i18n') vala_flags = [] - - if get_option('development') app_id += '.devel' name_prefix = '(devel) ' @@ -46,7 +44,7 @@ add_project_arguments(vala_flags, language: 'vala') config_data = configuration_data() config_data.set('version', meson.project_version()) config_data.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir')) -config_data.set_quoted('GETTEXT_PACKAGE', meson.project_name()) +config_data.set_quoted('GETTEXT_PACKAGE', app_id) config_data.set_quoted('APP_NAME', app_name) config_data.set_quoted('APP_ID', app_id) config_data.set_quoted('APP_VERSION', app_version) From a9f40b1a8ce394a4fe78ef4c15f686d0a1e9dda9 Mon Sep 17 00:00:00 2001 From: teamcons Date: Mon, 2 Mar 2026 21:27:04 +0100 Subject: [PATCH 27/32] Include gschema for the windows build (oooops!) --- data/meson.build | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/data/meson.build b/data/meson.build index 2c23e6a..d1fc1f8 100644 --- a/data/meson.build +++ b/data/meson.build @@ -56,18 +56,6 @@ if not windows_build install_dir: get_option('datadir') / 'metainfo', ) - gschema_conf = configuration_data() - gschema_conf.set('APP_ID', app_id) - gschema_file = configure_file( - input: 'inscriptions.gschema.xml.in', - output: '@0@.gschema.xml'.format(app_id), - configuration: gschema_conf, - ) - - install_data( - gschema_file, - install_dir: get_option('datadir') / 'glib-2.0' / 'schemas', - ) # Test definitions @@ -81,11 +69,24 @@ if not windows_build appstreamcli, args: ['validate', '--no-net', '--explain', appstream_file], ) +endif + + + gschema_conf = configuration_data() + gschema_conf.set('APP_ID', app_id) + gschema_file = configure_file( + input: 'inscriptions.gschema.xml.in', + output: '@0@.gschema.xml'.format(app_id), + configuration: gschema_conf, + ) + + install_data( + gschema_file, + install_dir: get_option('datadir') / 'glib-2.0' / 'schemas', + ) compile_schemas = find_program('glib-compile-schemas', required: false, disabler: true) test('Validate schema file', compile_schemas, args: ['--strict', '--dry-run', meson.current_source_dir()], ) - -endif \ No newline at end of file From 0bfaddd5eb1499bb60b1024b20a824587db46505 Mon Sep 17 00:00:00 2001 From: teamcons Date: Mon, 2 Mar 2026 21:32:01 +0100 Subject: [PATCH 28/32] include app name --- data/inscriptions.metainfo.xml.in.in | 2 +- data/meson.build | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/data/inscriptions.metainfo.xml.in.in b/data/inscriptions.metainfo.xml.in.in index e6a1667..f514ff3 100644 --- a/data/inscriptions.metainfo.xml.in.in +++ b/data/inscriptions.metainfo.xml.in.in @@ -9,7 +9,7 @@ io.github.elly_code.inscriptions - Inscriptions + @APP_NAME@ Translate text elegantly

A fast, pretty, and ready translation app using DeepL free and paid API

diff --git a/data/meson.build b/data/meson.build index d1fc1f8..6973fef 100644 --- a/data/meson.build +++ b/data/meson.build @@ -40,6 +40,7 @@ if not windows_build # Inject some variables into the metainfo file before merging in the translations appstream_conf = configuration_data() + appstream_conf.set('APP_NAME', app_name) appstream_conf.set('APP_ID', app_id) appstream_conf.set('GETTEXT_PACKAGE', meson.project_name()) appstream_file_in = configure_file( From 0feaf94c8d6aaffb274feea07557fc5a2bee9cec Mon Sep 17 00:00:00 2001 From: teamcons Date: Mon, 2 Mar 2026 21:36:04 +0100 Subject: [PATCH 29/32] proper gettext --- data/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/meson.build b/data/meson.build index 6973fef..31f08f1 100644 --- a/data/meson.build +++ b/data/meson.build @@ -42,7 +42,7 @@ if not windows_build appstream_conf = configuration_data() appstream_conf.set('APP_NAME', app_name) appstream_conf.set('APP_ID', app_id) - appstream_conf.set('GETTEXT_PACKAGE', meson.project_name()) + appstream_conf.set('GETTEXT_PACKAGE', app_id) appstream_file_in = configure_file( input: 'inscriptions.metainfo.xml.in.in', output: '@0@.metainfo.xml.in'.format(app_id), From 78d39fcc427eae117cbfb96a0fd82c51102ce704 Mon Sep 17 00:00:00 2001 From: teamcons Date: Mon, 2 Mar 2026 21:51:41 +0100 Subject: [PATCH 30/32] make sure we do not lose PO files in the devel --- po/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/po/meson.build b/po/meson.build index d148a69..4d77e2e 100644 --- a/po/meson.build +++ b/po/meson.build @@ -1,4 +1,4 @@ -i18n.gettext(meson.project_name(), +i18n.gettext(app_id, args: '--directory=' + meson.project_source_root(), preset: 'glib' ) From c222930e5674f7f9567eda280f12870376eed7ec Mon Sep 17 00:00:00 2001 From: teamcons Date: Tue, 3 Mar 2026 12:57:30 +0100 Subject: [PATCH 31/32] Refine dev builds and add a dev icon --- data/icons/dev.svg | 354 +++++++++++++++++++++ data/meson.build | 85 ++--- io.github.elly_code.inscriptions.devel.yml | 2 +- meson.build | 7 +- src/Widgets/HeaderBar.vala | 6 +- 5 files changed, 406 insertions(+), 48 deletions(-) create mode 100644 data/icons/dev.svg diff --git a/data/icons/dev.svg b/data/icons/dev.svg new file mode 100644 index 0000000..a4fd030 --- /dev/null +++ b/data/icons/dev.svg @@ -0,0 +1,354 @@ + +image/svg+xml diff --git a/data/meson.build b/data/meson.build index 31f08f1..77a4c82 100644 --- a/data/meson.build +++ b/data/meson.build @@ -1,22 +1,54 @@ +gschema_conf = configuration_data() +gschema_conf.set('APP_ID', app_id) +gschema_file = configure_file( + input: 'inscriptions.gschema.xml.in', + output: '@0@.gschema.xml'.format(app_id), + configuration: gschema_conf, +) + +install_data( + gschema_file, + install_dir: get_option('datadir') / 'glib-2.0' / 'schemas', +) + +compile_schemas = find_program('glib-compile-schemas', required: false, disabler: true) +test('Validate schema file', +compile_schemas, +args: ['--strict', '--dry-run', meson.current_source_dir()], +) + # metainfo confuses windows, and icons are if not windows_build - icon_sizes = ['16', '32', '48', '64', '128'] - - foreach i : icon_sizes - install_data( - 'icons' / 'hicolor' / i + '.png', - install_dir: get_option('datadir') / 'icons' / 'hicolor' / i + 'x' + i / 'apps', - rename: app_id + '.png' - ) - install_data( - 'icons' / 'hicolor@2' / i + '@2.png', - install_dir: get_option('datadir') / 'icons' / 'hicolor' / i + 'x' + i + '@2' / 'apps', - rename: app_id + '.png' - ) - endforeach + # Install the standard icons in standard build + if not get_option('development') + + icon_sizes = ['16', '32', '48', '64', '128'] + + foreach i : icon_sizes + install_data( + 'icons' / 'hicolor' / i + '.png', + install_dir: get_option('datadir') / 'icons' / 'hicolor' / i + 'x' + i / 'apps', + rename: app_id + '.png' + ) + install_data( + 'icons' / 'hicolor@2' / i + '@2.png', + install_dir: get_option('datadir') / 'icons' / 'hicolor' / i + 'x' + i + '@2' / 'apps', + rename: app_id + '.png' + ) + endforeach + + # Install the dev icon in development builds + else + install_data( + 'icons' / 'dev.svg', + install_dir: get_option('datadir') / 'icons' / 'hicolor' / 'scalable' / 'apps', + rename: app_id + '.svg' + ) + endif + # Inject some variables into the desktop file before merging in the translations desktop_conf = configuration_data() @@ -40,9 +72,8 @@ if not windows_build # Inject some variables into the metainfo file before merging in the translations appstream_conf = configuration_data() - appstream_conf.set('APP_NAME', app_name) appstream_conf.set('APP_ID', app_id) - appstream_conf.set('GETTEXT_PACKAGE', app_id) + appstream_conf.set('GETTEXT_PACKAGE', meson.project_name()) appstream_file_in = configure_file( input: 'inscriptions.metainfo.xml.in.in', output: '@0@.metainfo.xml.in'.format(app_id), @@ -57,8 +88,6 @@ if not windows_build install_dir: get_option('datadir') / 'metainfo', ) - - # Test definitions desktop_utils = find_program('desktop-file-validate', required: false) if desktop_utils.found() @@ -70,24 +99,6 @@ if not windows_build appstreamcli, args: ['validate', '--no-net', '--explain', appstream_file], ) -endif - - - gschema_conf = configuration_data() - gschema_conf.set('APP_ID', app_id) - gschema_file = configure_file( - input: 'inscriptions.gschema.xml.in', - output: '@0@.gschema.xml'.format(app_id), - configuration: gschema_conf, - ) - install_data( - gschema_file, - install_dir: get_option('datadir') / 'glib-2.0' / 'schemas', - ) - compile_schemas = find_program('glib-compile-schemas', required: false, disabler: true) - test('Validate schema file', - compile_schemas, - args: ['--strict', '--dry-run', meson.current_source_dir()], - ) +endif \ No newline at end of file diff --git a/io.github.elly_code.inscriptions.devel.yml b/io.github.elly_code.inscriptions.devel.yml index 548af31..c8721c1 100644 --- a/io.github.elly_code.inscriptions.devel.yml +++ b/io.github.elly_code.inscriptions.devel.yml @@ -11,7 +11,7 @@ sdk: org.gnome.Sdk command: io.github.elly_code.inscriptions.devel tags: ['devel'] -desktop-file-name-prefix: '(devel)' +desktop-file-name-suffix: ' (Developpment)' finish-args: - '--share=ipc' diff --git a/meson.build b/meson.build index 85dc04a..68a2586 100644 --- a/meson.build +++ b/meson.build @@ -18,14 +18,11 @@ i18n = import('i18n') vala_flags = [] if get_option('development') app_id += '.devel' - name_prefix = '(devel) ' + app_name += ' (devel)' vcs_tag = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip() - version_suffix = '-@0@'.format (vcs_tag) + app_version += '-@0@'.format (vcs_tag) vala_flags += ['--define', 'DEVEL'] -else - name_prefix = '' - version_suffix = '' endif # Set our translation domain diff --git a/src/Widgets/HeaderBar.vala b/src/Widgets/HeaderBar.vala index 44435f0..f0f94c8 100644 --- a/src/Widgets/HeaderBar.vala +++ b/src/Widgets/HeaderBar.vala @@ -65,11 +65,7 @@ public class Inscriptions.HeaderBar : Granite.Bin { app.set_accels_for_action (ACTION_PREFIX + ACTION_MENU, {"m"}); app.set_accels_for_action (ACTION_PREFIX + ACTION_TOGGLE_MESSAGES, {"m"}); - title_label = new Gtk.Label (_("Inscriptions")); -#if DEVEL - // This appears besides the name only in development version - title_label.label += _(" (devel)"); -#endif + title_label = new Gtk.Label (APP_NAME); title_label.add_css_class (Granite.STYLE_CLASS_TITLE_LABEL); From 12cf3b250f6788979dee09b46470f93c0a7b2cd0 Mon Sep 17 00:00:00 2001 From: teamcons Date: Tue, 3 Mar 2026 15:03:37 +0100 Subject: [PATCH 32/32] refine devel --- data/icons/dev.svg | 8 ++++---- data/inscriptions.gschema.xml.in | 4 ++-- io.github.elly_code.inscriptions.devel.yml | 2 +- meson.build | 1 - src/Widgets/HeaderBar.vala | 4 +++- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/data/icons/dev.svg b/data/icons/dev.svg index a4fd030..2411099 100644 --- a/data/icons/dev.svg +++ b/data/icons/dev.svg @@ -27,9 +27,9 @@ inkscape:window-height="940" id="namedview46" showgrid="false" - inkscape:zoom="5.5684659" - inkscape:cx="30.080098" - inkscape:cy="4.9385235" + inkscape:zoom="11.136932" + inkscape:cx="21.505025" + inkscape:cy="38.116423" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" @@ -269,7 +269,7 @@ height="53" width="53" rx="5" /> - + @@ -49,7 +49,7 @@ context for translations Passed as context parameter to the DeepL API
- + 'default' Level of formality For supported languages, how format the output should be diff --git a/io.github.elly_code.inscriptions.devel.yml b/io.github.elly_code.inscriptions.devel.yml index c8721c1..214ca50 100644 --- a/io.github.elly_code.inscriptions.devel.yml +++ b/io.github.elly_code.inscriptions.devel.yml @@ -11,7 +11,7 @@ sdk: org.gnome.Sdk command: io.github.elly_code.inscriptions.devel tags: ['devel'] -desktop-file-name-suffix: ' (Developpment)' +desktop-file-name-suffix: ' (Development)' finish-args: - '--share=ipc' diff --git a/meson.build b/meson.build index 68a2586..97c53e9 100644 --- a/meson.build +++ b/meson.build @@ -18,7 +18,6 @@ i18n = import('i18n') vala_flags = [] if get_option('development') app_id += '.devel' - app_name += ' (devel)' vcs_tag = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip() app_version += '-@0@'.format (vcs_tag) vala_flags += ['--define', 'DEVEL'] diff --git a/src/Widgets/HeaderBar.vala b/src/Widgets/HeaderBar.vala index f0f94c8..d995917 100644 --- a/src/Widgets/HeaderBar.vala +++ b/src/Widgets/HeaderBar.vala @@ -66,7 +66,9 @@ public class Inscriptions.HeaderBar : Granite.Bin { app.set_accels_for_action (ACTION_PREFIX + ACTION_TOGGLE_MESSAGES, {"m"}); title_label = new Gtk.Label (APP_NAME); - +#if DEVEL + title_label.label += _(" (Devel)"); +#endif title_label.add_css_class (Granite.STYLE_CLASS_TITLE_LABEL); title_switcher = new Gtk.StackSwitcher () {