diff --git a/data/gresource.xml b/data/gresource.xml index e9437575..474d6406 100644 --- a/data/gresource.xml +++ b/data/gresource.xml @@ -1,6 +1,9 @@ + plug.css + + icons/32/google.svg icons/32/google.svg icons/48/google.svg @@ -10,10 +13,14 @@ icons/32/mail.svg icons/48/mail.svg icons/48/mail.svg + icons/64/mail.svg + icons/64/mail.svg icons/32/tasks.svg icons/32/tasks.svg icons/48/tasks.svg icons/48/tasks.svg + icons/64/tasks.svg + icons/64/tasks.svg diff --git a/data/icons/64/mail.svg b/data/icons/64/mail.svg new file mode 100644 index 00000000..51ca0c57 --- /dev/null +++ b/data/icons/64/mail.svg @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/icons/64/tasks.svg b/data/icons/64/tasks.svg new file mode 100644 index 00000000..ee29c743 --- /dev/null +++ b/data/icons/64/tasks.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/data/plug.css b/data/plug.css new file mode 100644 index 00000000..d09ad49c --- /dev/null +++ b/data/plug.css @@ -0,0 +1,28 @@ +.dialog.paged navigation-view-page { + padding: 1em; +} + +.dialog.paged .action-area { + border-spacing: 0.5em; +} + +.dialog.paged .action-area button.text-button { + min-width: 7em; +} + +.dialog.paged navigation-view-page.oa-finalize > box.vertical { + margin-top: 2em; + border-spacing: 2em; +} + +.dialog.paged navigation-view-page.oa-finalize > box > box.vertical { + border-spacing: 0.5em; +} + +.dialog.paged navigation-view-page.oa-finalize image.large-icons { + -gtk-icon-size: 64px; +} + +.dialog.paged navigation-view-page.oa-finalize image.normal-icons { + -gtk-icon-size: 32px; +} diff --git a/po/POTFILES b/po/POTFILES index 9a2b99ba..2ecb7821 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -2,8 +2,8 @@ src/AccountsModel.vala src/Dialogs/CaldavDialog.vala src/Dialogs/Imap/ImapDialog.vala src/Dialogs/Imap/ImapLoginPage.vala -src/Dialogs/Imap/ImapSavePage.vala src/MainView.vala src/Plug.vala src/Widgets/AccountMenuItem.vala +src/Widgets/FinalizePage.vala src/Widgets/ValidationMessage.vala diff --git a/src/Dialogs/CaldavDialog.vala b/src/Dialogs/CaldavDialog.vala index 5ac6dfca..7513df45 100644 --- a/src/Dialogs/CaldavDialog.vala +++ b/src/Dialogs/CaldavDialog.vala @@ -23,15 +23,11 @@ public class OnlineAccounts.CaldavDialog : Gtk.Window { private Granite.ValidatedEntry url_entry; private Granite.ValidatedEntry username_entry; private Gtk.Button login_button; - private Gtk.Button save_configuration_back_button; private Gtk.Button save_configuration_button; - private Gtk.Button save_configuration_close_button; private Gtk.Entry display_name_entry; private Gtk.Entry password_entry; private Gtk.ListBox calendars_list; - private Gtk.Stack save_configuration_page_stack; private Adw.NavigationPage calendars_page; - private Adw.NavigationPage save_configuration_page; private Adw.NavigationView navigation_view; private ListStore calendars_store; private ValidationMessage url_message_revealer; @@ -73,32 +69,25 @@ public class OnlineAccounts.CaldavDialog : Gtk.Window { mnemonic_widget = password_entry }; - var login_cancel_button = new Gtk.Button.with_label (_("Cancel")) { - width_request = 86 - }; + var login_cancel_button = new Gtk.Button.with_label (_("Cancel")); login_button = new Gtk.Button.with_label (_("Log In")) { - width_request = 86, sensitive = false }; login_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - var action_area = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6) { + var action_area = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { margin_top = 24, halign = END, valign = END, vexpand = true, homogeneous = true }; + action_area.add_css_class ("action-area"); action_area.append (login_cancel_button); action_area.append (login_button); - var login_box = new Gtk.Box (VERTICAL, 6) { - margin_top = 12, - margin_bottom = 12, - margin_start = 12, - margin_end = 12 - }; + var login_box = new Gtk.Box (VERTICAL, 6); login_box.append (url_label); login_box.append (url_entry); login_box.append (url_message_revealer); @@ -140,30 +129,21 @@ public class OnlineAccounts.CaldavDialog : Gtk.Window { child = calendars_scroll_window }; - var calendar_page_back_button = new Gtk.Button.with_label (_("Back")) { - width_request = 86 - }; + var calendar_page_back_button = new Gtk.Button.with_label (_("Back")); - save_configuration_button = new Gtk.Button.with_label (_("Save")) { - width_request = 86 - }; + save_configuration_button = new Gtk.Button.with_label (_("Save")); save_configuration_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - var calendar_page_action_area = new Gtk.Box (HORIZONTAL, 6) { + var calendar_page_action_area = new Gtk.Box (HORIZONTAL, 0) { margin_top = 24, - spacing = 6, halign = END, homogeneous = true }; + calendar_page_action_area.add_css_class ("action-area"); calendar_page_action_area.append (calendar_page_back_button); calendar_page_action_area.append (save_configuration_button); - var calendars_box = new Gtk.Box (VERTICAL, 6) { - margin_top = 12, - margin_bottom = 12, - margin_start = 12, - margin_end = 12 - }; + var calendars_box = new Gtk.Box (VERTICAL, 6); calendars_box.append (display_name_label); calendars_box.append (display_name_entry); calendars_box.append (calendar_list_frame); @@ -171,60 +151,6 @@ public class OnlineAccounts.CaldavDialog : Gtk.Window { calendars_page = new Adw.NavigationPage (calendars_box, _("Calendars")); - var save_configuration_busy_label = new Gtk.Label (_("Saving the configuration…")); - - var save_configuration_busy_spinner = new Gtk.Spinner (); - save_configuration_busy_spinner.start (); - - var save_configuration_busy_box = new Gtk.Box (HORIZONTAL, 6); - save_configuration_busy_box.append (save_configuration_busy_label); - save_configuration_busy_box.append (save_configuration_busy_spinner); - - var save_configuration_success_view = new Granite.Placeholder (_("All done")) { - description = _("CalDAV account saved."), - icon = new ThemedIcon ("process-completed") - }; - save_configuration_success_view.remove_css_class (Granite.STYLE_CLASS_VIEW); - - save_configuration_back_button = new Gtk.Button.with_label (_("Back")) { - width_request = 86 - }; - - save_configuration_close_button = new Gtk.Button.with_label (_("Close")) { - width_request = 86 - }; - save_configuration_close_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - - var save_configuration_page_action_area = new Gtk.Box (HORIZONTAL, 6) { - margin_top = 24, - halign = END, - homogeneous = true - }; - save_configuration_page_action_area.append (save_configuration_back_button); - save_configuration_page_action_area.append (save_configuration_close_button); - - save_configuration_page_stack = new Gtk.Stack () { - hexpand = true, - vexpand = true, - hhomogeneous = false, - vhomogeneous = false, - halign = Gtk.Align.CENTER, - valign = Gtk.Align.CENTER - }; - save_configuration_page_stack.add_named (save_configuration_busy_box, "busy"); - save_configuration_page_stack.add_named (save_configuration_success_view, "success"); - - var save_configuration_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 12) { - margin_top = 12, - margin_bottom = 12, - margin_start = 12, - margin_end = 12 - }; - save_configuration_box.append (save_configuration_page_stack); - save_configuration_box.append (save_configuration_page_action_area); - - save_configuration_page = new Adw.NavigationPage (save_configuration_box, _("Save Configuration")); - navigation_view = new Adw.NavigationView () { hexpand = true, vexpand = true @@ -240,6 +166,8 @@ public class OnlineAccounts.CaldavDialog : Gtk.Window { modal = true; child = window_handle; titlebar = new Gtk.Grid (); + add_css_class ("dialog"); + add_css_class ("paged"); default_widget = login_button; @@ -261,44 +189,25 @@ public class OnlineAccounts.CaldavDialog : Gtk.Window { }); save_configuration_button.clicked.connect (() => { - navigation_view.push (save_configuration_page); - save_configuration_close_button.sensitive = false; - save_configuration_page_stack.set_visible_child_name ("busy"); + var finalize_page = new FinalizePage (new ThemedIcon ("x-office-calendar"), cancellable); - save_configuration.begin ((obj, res) => { - default_widget = save_configuration_button; - save_configuration_close_button.sensitive = true; + navigation_view.push (finalize_page); + save_configuration.begin ((obj, res) => { try { save_configuration.end (res); - save_configuration_back_button.visible = false; - save_configuration_page_stack.set_visible_child_name ("success"); + finalize_page.show_success (); } catch (Error e) { - var error_view = save_configuration_page_stack.get_child_by_name ("error"); - if (error_view != null) { - save_configuration_page_stack.remove (error_view); - } - error_view = new Granite.Placeholder (_("Could not save configuration")) { - description = e.message, - icon = new ThemedIcon ("dialog-error") - }; - - save_configuration_page_stack.add_named (error_view, "error"); - save_configuration_page_stack.set_visible_child_name ("error"); + finalize_page.show_error (e.message); } }); }); - save_configuration_close_button.clicked.connect (() => { - destroy (); - }); - calendar_page_back_button.clicked.connect (() => { - back_button_clicked (); - }); - - save_configuration_back_button.clicked.connect (() => { - back_button_clicked (); + if (cancellable != null) { + cancellable.cancel (); + } + navigation_view.pop (); }); url_entry.changed.connect (() => { @@ -337,13 +246,6 @@ public class OnlineAccounts.CaldavDialog : Gtk.Window { }); } - private void back_button_clicked () { - if (cancellable != null) { - cancellable.cancel (); - } - navigation_view.pop (); - } - private int sort_func (Gtk.ListBoxRow row1, Gtk.ListBoxRow row2) { var source1 = ((SourceRow) row1).source; var source2 = ((SourceRow) row2).source; diff --git a/src/Dialogs/Imap/ImapDialog.vala b/src/Dialogs/Imap/ImapDialog.vala index 111dd719..77c5c983 100644 --- a/src/Dialogs/Imap/ImapDialog.vala +++ b/src/Dialogs/Imap/ImapDialog.vala @@ -36,7 +36,6 @@ public class OnlineAccounts.ImapDialog : Gtk.Window { private Gtk.SpinButton imap_refresh_interval_spin; private Gtk.SpinButton smtp_port_spin; private ImapLoginPage login_page; - private ImapSavePage save_page; private Adw.NavigationView navigation_view; private uint cancel_timeout_id = 0; @@ -45,7 +44,6 @@ public class OnlineAccounts.ImapDialog : Gtk.Window { construct { login_page = new ImapLoginPage (); - save_page = new ImapSavePage (); var imap_header = new Granite.HeaderLabel ("IMAP"); @@ -217,31 +215,24 @@ public class OnlineAccounts.ImapDialog : Gtk.Window { smtp_sizegroup.add_widget (smtp_encryption_label); smtp_sizegroup.add_widget (smtp_port_label); - var back_button = new Gtk.Button.with_label (_("Back")) { - width_request = 86 - }; + var back_button = new Gtk.Button.with_label (_("Back")); save_button = new Gtk.Button.with_label (_("Log In")) { - width_request = 86, sensitive = false }; save_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - var action_area = new Gtk.Box (HORIZONTAL, 6) { + var action_area = new Gtk.Box (HORIZONTAL, 0) { valign = END, halign = END, homogeneous = true, vexpand = true }; + action_area.add_css_class ("action-area"); action_area.append (back_button); action_area.append (save_button); - var main_box = new Gtk.Box (VERTICAL, 24) { - margin_top = 12, - margin_bottom = 12, - margin_start = 12, - margin_end = 12 - }; + var main_box = new Gtk.Box (VERTICAL, 24); main_box.append (imap_server_grid); main_box.append (smtp_server_grid); main_box.append (action_area); @@ -263,6 +254,8 @@ public class OnlineAccounts.ImapDialog : Gtk.Window { modal = true; child = window_handle; titlebar = new Gtk.Grid (); + add_css_class ("dialog"); + add_css_class ("paged"); default_widget = login_page.next_button; @@ -280,8 +273,6 @@ public class OnlineAccounts.ImapDialog : Gtk.Window { default_widget = login_page.next_button; }); - save_page.close.connect (destroy); - back_button.clicked.connect (() => navigation_view.pop ()); smtp_no_credentials.notify["active"].connect (() => { @@ -358,16 +349,18 @@ public class OnlineAccounts.ImapDialog : Gtk.Window { } cancellable = new GLib.Cancellable (); - navigation_view.push (save_page); - save_page.show_busy (cancellable); + var finalize_page = new FinalizePage (new ThemedIcon ("onlineaccounts-mail"), cancellable); + + navigation_view.push (finalize_page); save_configuration.begin ((obj, res) => { try { save_configuration.end (res); - save_page.show_success (); - + finalize_page.show_success (); } catch (Error e) { - save_page.show_error (e); + finalize_page.show_error (e.message); + } finally { + cancellable = null; } }); }); diff --git a/src/Dialogs/Imap/ImapLoginPage.vala b/src/Dialogs/Imap/ImapLoginPage.vala index b998cd8b..24cfd49d 100644 --- a/src/Dialogs/Imap/ImapLoginPage.vala +++ b/src/Dialogs/Imap/ImapLoginPage.vala @@ -84,32 +84,25 @@ public class OnlineAccounts.ImapLoginPage : Adw.NavigationPage { secondary_text = _("Pick a name like “Work” or “Personal” for the account.") }; - var cancel_button = new Gtk.Button.with_label (_("Cancel")) { - width_request = 86 - }; + var cancel_button = new Gtk.Button.with_label (_("Cancel")); next_button = new Gtk.Button.with_label (_("Next")) { - width_request = 86, sensitive = false }; next_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - var action_area = new Gtk.Box (HORIZONTAL, 6) { + var action_area = new Gtk.Box (HORIZONTAL, 0) { margin_top = 24, valign = END, halign = END, homogeneous = true, vexpand = true }; + action_area.add_css_class ("action-area"); action_area.append (cancel_button); action_area.append (next_button); - var box = new Gtk.Box (VERTICAL, 6) { - margin_start = 12, - margin_end = 12, - margin_top = 12, - margin_bottom = 12, - }; + var box = new Gtk.Box (VERTICAL, 6); box.append (real_name_label); box.append (real_name_entry); box.append (email_label); diff --git a/src/Dialogs/Imap/ImapSavePage.vala b/src/Dialogs/Imap/ImapSavePage.vala deleted file mode 100644 index 0b83f9bd..00000000 --- a/src/Dialogs/Imap/ImapSavePage.vala +++ /dev/null @@ -1,125 +0,0 @@ -/* -* Copyright 2021 elementary, Inc. (https://elementary.io) -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public -* License as published by the Free Software Foundation; either -* version 3 of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* General Public License for more details. -* -* You should have received a copy of the GNU General Public -* License along with this program; if not, write to the -* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -* Boston, MA 02110-1301 USA -* -*/ - -public class OnlineAccounts.ImapSavePage : Adw.NavigationPage { - public signal void close (); - - private Gtk.Button close_button; - - private Gtk.Stack stack; - private Gtk.Button back_button; - private Granite.Placeholder error_alert_view; - private GLib.Cancellable? cancellable = null; - - construct { - var busy_label = new Gtk.Label (_("Setting up the e-mail account…")); - - var busy_spinner = new Gtk.Spinner (); - busy_spinner.start (); - - var busy_box = new Gtk.Box (HORIZONTAL, 6); - busy_box.append (busy_label); - busy_box.append (busy_spinner); - - error_alert_view = new Granite.Placeholder (_("Could not save the e-mail account")) { - icon = new ThemedIcon ("process-error") - }; - error_alert_view.remove_css_class (Granite.STYLE_CLASS_VIEW); - - var success_alert_view = new Granite.Placeholder (_("Success")) { - description = _("E-mail account saved."), - icon = new ThemedIcon ("process-completed") - }; - success_alert_view.remove_css_class (Granite.STYLE_CLASS_VIEW); - - stack = new Gtk.Stack () { - hexpand = true, - vexpand = true, - hhomogeneous = false, - vhomogeneous = false, - halign = Gtk.Align.CENTER, - valign = Gtk.Align.CENTER - }; - stack.add_named (busy_box, "busy"); - stack.add_named (error_alert_view, "error"); - stack.add_named (success_alert_view, "success"); - - back_button = new Gtk.Button.with_label (_("Back")) { - width_request = 86 - }; - - close_button = new Gtk.Button.with_label (_("Close")) { - width_request = 86 - }; - close_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - - var action_area = new Gtk.Box (HORIZONTAL, 6) { - margin_top = 24, - valign = END, - halign = END, - homogeneous = true, - vexpand = true - }; - action_area.append (back_button); - action_area.append (close_button); - - var box = new Gtk.Box (VERTICAL, 6) { - margin_start = 12, - margin_end = 12, - margin_top = 12, - margin_bottom = 12, - }; - box.append (stack); - box.append (action_area); - - child = box; - - back_button.clicked.connect (() => { - if (cancellable != null) { - cancellable.cancel (); - } - - ((Adw.NavigationView) get_ancestor (typeof (Adw.NavigationView))).pop (); - }); - - close_button.clicked.connect (() => { - if (cancellable != null) { - cancellable.cancel (); - } - close (); - }); - } - - public void show_busy (GLib.Cancellable cancellable) { - this.cancellable = cancellable; - stack.set_visible_child_name ("busy"); - close_button.grab_focus (); - } - - public void show_success () { - stack.set_visible_child_name ("success"); - back_button.visible = false; - } - - public void show_error (Error error) { - error_alert_view.description = error.message; - stack.set_visible_child_name ("error"); - } -} diff --git a/src/Plug.vala b/src/Plug.vala index c855c107..4a5c5c3e 100644 --- a/src/Plug.vala +++ b/src/Plug.vala @@ -36,7 +36,13 @@ public class OnlineAccounts.Plug : Switchboard.Plug { public override Gtk.Widget get_widget () { if (box == null) { - Gtk.IconTheme.get_for_display (Gdk.Display.get_default ()).add_resource_path ("/io/elementary/settings/onlineaccounts"); + var provider = new Gtk.CssProvider (); + provider.load_from_resource ("/io/elementary/settings/onlineaccounts/plug.css"); + Gtk.StyleContext.add_provider_for_display ( + Gdk.Display.get_default (), + provider, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION + ); var headerbar = new Adw.HeaderBar () { show_title = false diff --git a/src/Widgets/FinalizePage.vala b/src/Widgets/FinalizePage.vala new file mode 100644 index 00000000..80fee3ca --- /dev/null +++ b/src/Widgets/FinalizePage.vala @@ -0,0 +1,141 @@ +/* + * Copyright 2025 elementary, Inc. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +/** + * FinalizePage is an {@link Adw.NavigationPage} subclass that shows + * in-progress, success, and error states + */ +public class OnlineAccounts.FinalizePage : Adw.NavigationPage { + public GLib.Cancellable? cancellable { get; construct; } + public GLib.Icon icon { get; construct; } + + private Gtk.Image badge; + private Gtk.Label description_label; + private Gtk.Button back_button; + private Gtk.Button close_button; + + /** + * Constructs a new {@link FinalizePage} + * + * @param icon The {@link GLib.Icon} to represent the type of account + * + * @param cancellable The {@link GLib.Cancellable} to cancel when + * navigating away from this page + */ + public FinalizePage (Icon icon, GLib.Cancellable cancellable) { + Object ( + cancellable: cancellable, + icon: icon + ); + } + + construct { + var image = new Gtk.Image.from_gicon (icon) { + icon_size = LARGE + }; + + badge = new Gtk.Image.from_icon_name ("emblem-synchronized") { + halign = END, + valign = END, + icon_size = NORMAL + }; + + var overlay = new Gtk.Overlay () { + halign = CENTER, + child = image + }; + overlay.add_overlay (badge); + + var title_label = new Gtk.Label ("") { + halign = CENTER, + justify = CENTER, + wrap = true, + max_width_chars = 50, + use_markup = true + }; + title_label.add_css_class (Granite.STYLE_CLASS_H1_LABEL); + + description_label = new Gtk.Label ("") { + halign = CENTER, + justify = CENTER, + wrap = true, + max_width_chars = 50, + use_markup = true + }; + description_label.add_css_class (Granite.STYLE_CLASS_DIM_LABEL); + + var content_box = new Gtk.Box (VERTICAL, 0); + content_box.append (overlay); + content_box.append (title_label); + content_box.append (description_label); + + back_button = new Gtk.Button.with_label (_("Back")); + + close_button = new Gtk.Button.with_label (_("Close")); + close_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); + + var action_area = new Gtk.Box (HORIZONTAL, 0) { + valign = END, + halign = END, + homogeneous = true, + vexpand = true + }; + action_area.add_css_class ("action-area"); + action_area.append (back_button); + action_area.append (close_button); + + var box = new Gtk.Box (VERTICAL, 0); + box.append (content_box); + box.append (action_area); + + child = box; + title = _("Setting up the account…"); + add_css_class ("oa-finalize"); + + bind_property ("title", title_label, "label", SYNC_CREATE); + + back_button.clicked.connect (() => { + ((Adw.NavigationView) get_ancestor (typeof (Adw.NavigationView))).pop (); + }); + + hidden.connect (() => { + if (cancellable != null) { + cancellable.cancel (); + } + }); + + close_button.clicked.connect (() => { + if (cancellable != null) { + cancellable.cancel (); + } + + ((Gtk.Window) get_ancestor (typeof (Gtk.Window))).close (); + }); + } + + /** + * Show a success page when saving an account has succeeded + */ + public void show_success () { + title = _("Ready to go"); + description_label.label = _("Account saved"); + badge.icon_name = "process-completed"; + + ((Gtk.Window) get_ancestor (typeof (Gtk.Window))).default_widget = close_button; + + // Prevent navigating back + back_button.visible = false; + ((Adw.NavigationView) get_ancestor (typeof (Adw.NavigationView))).replace ({this}); + } + + /** + * Show an error message when saving an account has failed + */ + public void show_error (string message) { + title = _("Could not save the account"); + description_label.label = message; + badge.icon_name = "dialog-error"; + } +} diff --git a/src/meson.build b/src/meson.build index 2fd9a0c7..20157fa3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -3,11 +3,11 @@ plug_files = files( 'Dialogs/CaldavDialog.vala', 'Dialogs/Imap/CamelSession.vala', 'Dialogs/Imap/ImapDialog.vala', - 'Dialogs/Imap/ImapSavePage.vala', 'Dialogs/Imap/ImapLoginPage.vala', 'MainView.vala', 'Plug.vala', 'Widgets/AccountMenuItem.vala', + 'Widgets' / 'FinalizePage.vala', 'Widgets/ValidationMessage.vala' )