From ae5fe2d1ded85e048ae102c4f2fb7a82fa9fad1d Mon Sep 17 00:00:00 2001 From: ppvan Date: Wed, 2 Aug 2023 20:11:59 +0700 Subject: [PATCH 1/6] bound signals to window instead of application --- src/application.vala | 24 ++++++++++---- src/models/schema.vala | 1 + src/models/utils.vala | 12 +++++++ src/services/resource_manager.vala | 5 +-- src/services/signal.vala | 26 +++++++++++++-- src/ui/connection/connection_form.vala | 25 ++++++++++----- src/ui/connection/connection_recent.vala | 41 ++++++++++++------------ src/ui/connection/connection_view.vala | 1 + src/ui/preferences_window.vala | 1 + src/ui/query/query_editor.vala | 1 + src/ui/query/query_results.vala | 2 +- src/ui/query/query_view.vala | 39 ++++++++++------------ src/ui/query/table_data_view.vala | 41 +++++++++++++++--------- src/ui/table/table_cols.vala | 1 + src/ui/table/table_fk.vala | 1 + src/ui/table/table_index.vala | 1 + src/ui/table/table_structure_view.vala | 38 ++++++++++++++-------- src/ui/window.vala | 20 +++++++++--- 18 files changed, 180 insertions(+), 100 deletions(-) diff --git a/src/application.vala b/src/application.vala index a061dc1..c148bde 100644 --- a/src/application.vala +++ b/src/application.vala @@ -28,6 +28,7 @@ namespace Psequel { private PreferencesWindow preference; + private AppSignals app_signals; public Application () { Object (application_id: "me.ppvan.psequel", flags: ApplicationFlags.DEFAULT_FLAGS); @@ -40,16 +41,14 @@ namespace Psequel { { "quit", this.quit } }; this.add_action_entries (action_entries, this); - this.set_accels_for_action ("app.quit", {"q"}); + this.set_accels_for_action ("app.quit", { "q" }); } public override void activate () { base.activate (); - var win = this.active_window; - if (win == null) { - win = new Psequel.Window (this); - } - win.present (); + + var window = new_window (); + window.present (); } public override void startup () { @@ -71,9 +70,10 @@ namespace Psequel { return_if_reached (); } + app_signals = new AppSignals (); + app.app_signals = app_signals; query_service = new QueryService (background); table_list = new ObservableArrayList (); - signals = new AppSignals (); load_user_data (); }; @@ -103,6 +103,7 @@ namespace Psequel { /* register needed types, allow me to ref a template inside a template */ private static void ensure_types () { + typeof (WindowSignals).ensure (); typeof (Psequel.ConnectionView).ensure (); typeof (Psequel.ConnectionSidebar).ensure (); typeof (Psequel.ConnectionForm).ensure (); @@ -149,5 +150,14 @@ namespace Psequel { } this.preference.present (); } + + private Window new_window () { + var signals = new WindowSignals (); + var window = new Window (this); + window.signals = (owned)signals; + app_signals.window_ready (); + + return window; + } } } \ No newline at end of file diff --git a/src/models/schema.vala b/src/models/schema.vala index 9e00f67..8653788 100644 --- a/src/models/schema.vala +++ b/src/models/schema.vala @@ -17,6 +17,7 @@ namespace Psequel { } construct { + debug ("[CONTRUCT] %s", this.name); tablenames = new ObservableArrayList (); viewnames = new ObservableArrayList (); indexes = new ObservableArrayList (); diff --git a/src/models/utils.vala b/src/models/utils.vala index f11e68f..02f2db3 100644 --- a/src/models/utils.vala +++ b/src/models/utils.vala @@ -183,4 +183,16 @@ namespace Psequel { assert_not_reached (); } } + + public Window get_parrent_window (Gtk.Widget widget) { + var window = widget.get_root (); + + if (window is Gtk.Window) { + return (Window) window; + } else { + warning ("Widget %s root is not a window", widget.name); + + assert_not_reached (); + } + } } \ No newline at end of file diff --git a/src/services/resource_manager.vala b/src/services/resource_manager.vala index 3e80007..1f9af37 100644 --- a/src/services/resource_manager.vala +++ b/src/services/resource_manager.vala @@ -6,10 +6,7 @@ namespace Psequel { public class ResourceManager : Object { - /** - * Application specific signals. - */ - public AppSignals signals; + public AppSignals app_signals; /** * Recent connections info in last sessions. diff --git a/src/services/signal.vala b/src/services/signal.vala index 7d37b0c..7f9a091 100644 --- a/src/services/signal.vala +++ b/src/services/signal.vala @@ -1,10 +1,15 @@ namespace Psequel { /** - * Application signals to comnicate between components. + * Window signals to comnicate between components. */ - public class AppSignals { + public class WindowSignals : Object { + /* Target connection in connection list changed */ + public signal void selection_changed (Connection conn); + + /* Request a db connection by click connect context menu */ + public signal void request_database_conn (Connection conn); /** * Emit when the table list changed. */ @@ -22,9 +27,24 @@ namespace Psequel { public signal void request_database (Connection conn); public signal void database_connected (); /** - * Should only init onces by the resource manager. Should be single on but i'm lazy + * Tied to one window and created by window. */ + public WindowSignals () { + Object (); + } + + public int number {get; set;} + } + + /** + * Application signals. + */ + public class AppSignals : Object { + + public signal void window_ready (); + public AppSignals () { + Object (); } } } \ No newline at end of file diff --git a/src/ui/connection/connection_form.vala b/src/ui/connection/connection_form.vala index 1796ceb..bb6baad 100644 --- a/src/ui/connection/connection_form.vala +++ b/src/ui/connection/connection_form.vala @@ -6,7 +6,7 @@ namespace Psequel { BindingGroup binddings; private unowned QueryService query_service; - private unowned AppSignals signals; + private unowned WindowSignals signals; private Connection _conn; public Connection mapped_conn { @@ -26,9 +26,9 @@ namespace Psequel { } construct { + debug ("[CONTRUCT] %s", this.name); // init service query_service = ResourceManager.instance ().query_service; - signals = ResourceManager.instance ().signals; // Create group to maped the entry widget to connection data. this.binddings = new BindingGroup (); @@ -37,13 +37,22 @@ namespace Psequel { } private void setup_signals () { - ConnectionSidebar.signals.selection_changed.connect ((conn) => { - mapped_conn = conn; - }); - ConnectionSidebar.signals.request_database_conn.connect ((conn) => { - mapped_conn = conn; - connect_btn.clicked (); + + // signals can only be connected after the window is ready. + // because widget access window to get signals. + ResourceManager.instance ().app_signals.window_ready.connect (() => { + signals = get_parrent_window (this).signals; + + signals.selection_changed.connect ((conn) => { + mapped_conn = conn; + }); + + signals.request_database_conn.connect ((conn) => { + mapped_conn = conn; + connect_btn.clicked (); + }); }); + } private void set_up_bindings (BindingGroup group) { diff --git a/src/ui/connection/connection_recent.vala b/src/ui/connection/connection_recent.vala index be3c370..12ff112 100644 --- a/src/ui/connection/connection_recent.vala +++ b/src/ui/connection/connection_recent.vala @@ -5,21 +5,6 @@ namespace Psequel { [GtkTemplate (ui = "/me/ppvan/psequel/gtk/connection-recent.ui")] public class ConnectionSidebar : Gtk.Box { - /* Learn from Svelte ~ write store */ - public class InnerSignal { - /* Target connection in connection list changed */ - public signal void selection_changed (Connection conn); - - /* Request a db connection by click connect context menu */ - public signal void request_database_conn (Connection conn); - } - - public static InnerSignal signals; - - static construct { - signals = new InnerSignal (); - } - const ActionEntry[] ACTION_ENTRIES = { { "connect", on_connect_connection }, @@ -28,7 +13,10 @@ namespace Psequel { }; private Application app; - private ObservableArrayList model; + + /* This is null ultil window ready event, which after contruct block */ + private unowned WindowSignals signals; + private unowned ObservableArrayList model; public ConnectionSidebar (ConnectionView parent) { @@ -36,13 +24,28 @@ namespace Psequel { } construct { + debug ("[CONTRUCT] %s", this.name); this.app = ResourceManager.instance ().app; - setup_bindings (); - setup_action (); + this.model = ResourceManager.instance ().recent_connections; + + setup_signals (); + } + + private void setup_signals () { + // signals can only be connected after the window is ready. + // because widget access window to get signals. + ResourceManager.instance ().app_signals.window_ready.connect (() => { + signals = get_parrent_window (this).signals; + this.setup_bindings (); + this.setup_action (); + }); + } private void setup_action () { + debug ("setup_action"); + var action_group = new SimpleActionGroup (); action_group.add_action_entries (ACTION_ENTRIES, this); insert_action_group ("conn", action_group); @@ -51,8 +54,6 @@ namespace Psequel { public void setup_bindings () { debug ("setup bindings"); - this.model = ResourceManager.instance ().recent_connections; - // Auto create a conn and focus it on first install. if (model.size == 0) { model.add (new Connection ()); diff --git a/src/ui/connection/connection_view.vala b/src/ui/connection/connection_view.vala index fb92744..8938fd2 100644 --- a/src/ui/connection/connection_view.vala +++ b/src/ui/connection/connection_view.vala @@ -19,6 +19,7 @@ namespace Psequel { // Connect event. construct { + debug ("[CONTRUCT] %s", this.name); } diff --git a/src/ui/preferences_window.vala b/src/ui/preferences_window.vala index b609f62..1875e31 100644 --- a/src/ui/preferences_window.vala +++ b/src/ui/preferences_window.vala @@ -11,6 +11,7 @@ namespace Psequel { } construct { + debug ("[CONTRUCT] %s", this.name); settings = ResourceManager.instance ().settings; setup_binding (); defaults (); diff --git a/src/ui/query/query_editor.vala b/src/ui/query/query_editor.vala index 88fbb66..599e85b 100644 --- a/src/ui/query/query_editor.vala +++ b/src/ui/query/query_editor.vala @@ -15,6 +15,7 @@ namespace Psequel { } construct { + debug ("[CONTRUCT] %s", this.name); debug ("Contruct view"); query_service = ResourceManager.instance ().query_service; diff --git a/src/ui/query/query_results.vala b/src/ui/query/query_results.vala index 153d6a9..554d287 100644 --- a/src/ui/query/query_results.vala +++ b/src/ui/query/query_results.vala @@ -19,7 +19,7 @@ namespace Psequel { } construct { - + debug ("[CONTRUCT] %s", this.name); stack.visible_child_name = EMPTY; spinner.spinning = false; model = new ObservableArrayList (); diff --git a/src/ui/query/query_view.vala b/src/ui/query/query_view.vala index e59345d..8a9da47 100644 --- a/src/ui/query/query_view.vala +++ b/src/ui/query/query_view.vala @@ -11,14 +11,13 @@ namespace Psequel { public const string QUERY_EDITOR = "query-editor"; private unowned QueryService query_service; - private unowned AppSignals signals; + private unowned WindowSignals signals; private SchemaService schema_service; private ObservableArrayList schemas; private Schema _current_schema; - - private Schema current_schema { + public Schema current_schema { get { return _current_schema; } @@ -40,8 +39,8 @@ namespace Psequel { } construct { + debug ("[CONTRUCT] %s", this.name); query_service = ResourceManager.instance ().query_service; - signals = ResourceManager.instance ().signals; schema_service = new SchemaService (query_service); schemas = new ObservableArrayList (); @@ -50,8 +49,8 @@ namespace Psequel { tbname_filter = new Gtk.StringFilter (exp); vname_filter = new Gtk.StringFilter (exp); + setup_signals (); set_up_schema (); - connect_signals (); } @@ -153,23 +152,19 @@ namespace Psequel { this.schema_dropdown.set_model (schemas); } - private void connect_signals () { - // signals.table_list_changed.connect (() => { - // debug ("Handle table_list_changed."); - // reload_tables.begin (); - // }); + private void setup_signals () { + // signals can only be connected after the window is ready. + // because widget access window to get signals. + ResourceManager.instance ().app_signals.window_ready.connect (() => { + signals = get_parrent_window (this).signals; - // signals.views_list_changed.connect (() => { - // debug ("Handle views_list_changed."); - // reload_views.begin (); - // }); + signals.database_connected.connect (() => { + debug ("Handle database_connected."); + reload_schema.begin (); + }); - signals.database_connected.connect (() => { - debug ("Handle database_connected."); - reload_schema.begin (); + schema_dropdown.notify["selected"].connect (schema_changed); }); - - schema_dropdown.notify["selected"].connect (schema_changed); } [GtkCallback] @@ -234,9 +229,9 @@ namespace Psequel { var vname = current_schema.viewnames[row.get_index ()]; debug ("Emit view_selected"); - // Idle.add_once (() => { - // stack.visible_child_name = TABLE_DATA; - // }); + // Idle.add_once (() => { + // stack.visible_child_name = TABLE_DATA; + // }); signals.view_selected_changed (vname.string); } diff --git a/src/ui/query/table_data_view.vala b/src/ui/query/table_data_view.vala index 69d7604..b0a5277 100644 --- a/src/ui/query/table_data_view.vala +++ b/src/ui/query/table_data_view.vala @@ -4,7 +4,7 @@ namespace Psequel { [GtkTemplate (ui = "/me/ppvan/psequel/gtk/table-data-view.ui")] public class TableData : Gtk.Box { - private AppSignals signals; + private unowned WindowSignals signals; private QueryService query_service; private ObservableArrayList model; @@ -20,13 +20,14 @@ namespace Psequel { } construct { + debug ("[CONTRUCT] %s", this.name); query_service = ResourceManager.instance ().query_service; - signals = ResourceManager.instance ().signals; model = new ObservableArrayList (); var setting = ResourceManager.instance ().settings; setting.bind ("query-limit", this, "query-limit", SettingsBindFlags.DEFAULT); - connect_signal (); + + setup_signals (); } @@ -69,24 +70,32 @@ namespace Psequel { status_label.label = @"Rows $begin - $end"; } - private void connect_signal () { - this.signals.table_selected_changed.connect ((tbname) => { - this.tbname = tbname; - this.filter_entry.set_text (""); - load_data.begin (schema.name, tbname); - }); + private void setup_signals () { - this.signals.view_selected_changed.connect ((vname) => { - this.tbname = vname; - this.filter_entry.set_text (""); - load_data.begin (schema.name, vname); - }); + // signals can only be connected after the window is ready. + // because widget access window to get signals. + ResourceManager.instance ().app_signals.window_ready.connect (() => { + signals = get_parrent_window (this).signals; - this.signals.schema_changed.connect ((schema) => { - this.schema = schema; + signals.table_selected_changed.connect ((tbname) => { + this.tbname = tbname; + this.filter_entry.set_text (""); + load_data.begin (schema.name, tbname); + }); + + signals.view_selected_changed.connect ((vname) => { + this.tbname = vname; + this.filter_entry.set_text (""); + load_data.begin (schema.name, vname); + }); + + signals.schema_changed.connect ((schema) => { + this.schema = schema; + }); }); } + [GtkCallback] private void filter_query (Gtk.Button btn) { var where_clause = filter_entry.get_text (); diff --git a/src/ui/table/table_cols.vala b/src/ui/table/table_cols.vala index 8464ae2..7c391b2 100644 --- a/src/ui/table/table_cols.vala +++ b/src/ui/table/table_cols.vala @@ -45,6 +45,7 @@ namespace Psequel { } construct { + debug ("[CONTRUCT] %s", this.name); setup_name_col (); setup_datatype_col (); setup_nullable_col (); diff --git a/src/ui/table/table_fk.vala b/src/ui/table/table_fk.vala index 879f9a2..cbe2279 100644 --- a/src/ui/table/table_fk.vala +++ b/src/ui/table/table_fk.vala @@ -44,6 +44,7 @@ namespace Psequel { } construct { + debug ("[CONTRUCT] %s", this.name); setup_name_col (); setup_table_columns_col (); setup_fk_tbname_col (); diff --git a/src/ui/table/table_index.vala b/src/ui/table/table_index.vala index 0de9be3..bfa57ec 100644 --- a/src/ui/table/table_index.vala +++ b/src/ui/table/table_index.vala @@ -44,6 +44,7 @@ namespace Psequel { } construct { + debug ("[CONTRUCT] %s", this.name); setup_name_col (); setup_indexcolumns_col (); setup_indextype_col (); diff --git a/src/ui/table/table_structure_view.vala b/src/ui/table/table_structure_view.vala index 6ebbd89..affbda3 100644 --- a/src/ui/table/table_structure_view.vala +++ b/src/ui/table/table_structure_view.vala @@ -3,7 +3,7 @@ namespace Psequel { [GtkTemplate (ui = "/me/ppvan/psequel/gtk/table-structure-view.ui")] public class TableStructure : Gtk.Box { - private AppSignals signals; + private unowned WindowSignals signals; private Schema _cur_schema; @@ -30,24 +30,34 @@ namespace Psequel { } construct { - signals = ResourceManager.instance ().signals; + debug ("[CONTRUCT] %s", this.name); + setup_signals (); + } + private void setup_signals () { - signals.schema_changed.connect ((schema) => { - debug ("%s", schema.name); - cur_schema = schema; + // signals can only be connected after the window is ready. + // because widget access window to get signals. + ResourceManager.instance ().app_signals.window_ready.connect (() => { + signals = get_parrent_window (this).signals; - columns.table = " "; - indexes.table = " "; - foreign_keys.table = " "; + signals.schema_changed.connect ((schema) => { + debug ("%s", schema.name); + cur_schema = schema; + + columns.table = " "; + indexes.table = " "; + foreign_keys.table = " "; + }); + + signals.table_selected_changed.connect ((tbname) => { + debug ("Handle table_selected_changed: %s", tbname); + columns.table = tbname; + indexes.table = tbname; + foreign_keys.table = tbname; + }); }); - signals.table_selected_changed.connect ((tbname) => { - debug ("Handle table_selected_changed: %s", tbname); - columns.table = tbname; - indexes.table = tbname; - foreign_keys.table = tbname; - }); } diff --git a/src/ui/window.vala b/src/ui/window.vala index b97ef87..589c597 100644 --- a/src/ui/window.vala +++ b/src/ui/window.vala @@ -25,13 +25,15 @@ namespace Psequel { [GtkTemplate (ui = "/me/ppvan/psequel/gtk/window.ui")] public class Window : Adw.ApplicationWindow { - private AppSignals signals; + public WindowSignals signals {get; set; default = null;} public Window (Application app) { Object (application: app); } construct { + debug ("[CONTRUCT] %s", this.name); + with (ResourceManager.instance ()) { settings.bind ("window-width", this, "default-width", SettingsBindFlags.DEFAULT); @@ -39,10 +41,16 @@ namespace Psequel { "default-height", SettingsBindFlags.DEFAULT); } - this.signals = ResourceManager.instance ().signals; + setup_signals (); + } - signals.database_connected.connect (() => { - navigate_to (Views.QUERY); + private void setup_signals () { + // signals can only be connected after the window is ready. + // because widget access window to get signals. + ResourceManager.instance ().app_signals.window_ready.connect (() => { + signals.database_connected.connect (() => { + navigate_to (Views.QUERY); + }); }); } @@ -50,6 +58,9 @@ namespace Psequel { * Navigate to the stack view. */ public void navigate_to (string view_name) { + + debug ("OK"); + var child = stack.get_child_by_name (view_name); if (child == null) { @@ -58,7 +69,6 @@ namespace Psequel { debug ("navigate_to %s", view_name); stack.visible_child = child; } - } public void add_toast (Adw.Toast toast) { From c30ada98d315ea1e89b116cd12c6c6cba2a1060b Mon Sep 17 00:00:00 2001 From: ppvan Date: Wed, 2 Aug 2023 21:26:08 +0700 Subject: [PATCH 2/6] isolate query service --- src/application.vala | 4 +++- src/models/schema.vala | 1 - src/services/query_service.vala | 1 - src/ui/connection/connection_form.vala | 7 ++++--- src/ui/query/query_editor.vala | 8 +++++++- src/ui/query/query_view.vala | 16 ++++++++++------ src/ui/query/table_data_view.vala | 3 ++- src/ui/window.vala | 1 + 8 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/application.vala b/src/application.vala index c148bde..0406acc 100644 --- a/src/application.vala +++ b/src/application.vala @@ -72,7 +72,7 @@ namespace Psequel { app_signals = new AppSignals (); app.app_signals = app_signals; - query_service = new QueryService (background); + // query_service = new QueryService (background); table_list = new ObservableArrayList (); load_user_data (); @@ -154,7 +154,9 @@ namespace Psequel { private Window new_window () { var signals = new WindowSignals (); var window = new Window (this); + var query_service = new QueryService (ResourceManager.instance ().background); window.signals = (owned)signals; + window.query_service = (owned)query_service; app_signals.window_ready (); return window; diff --git a/src/models/schema.vala b/src/models/schema.vala index 8653788..9e00f67 100644 --- a/src/models/schema.vala +++ b/src/models/schema.vala @@ -17,7 +17,6 @@ namespace Psequel { } construct { - debug ("[CONTRUCT] %s", this.name); tablenames = new ObservableArrayList (); viewnames = new ObservableArrayList (); indexes = new ObservableArrayList (); diff --git a/src/services/query_service.vala b/src/services/query_service.vala index 95cb59f..ff4cc9c 100644 --- a/src/services/query_service.vala +++ b/src/services/query_service.vala @@ -121,7 +121,6 @@ namespace Psequel { public async Relation exec_query_params (string query, Variant[] params) throws PsequelError { - debug (params[0].get_string ()); var result = yield exec_query_params_internal (query, params); diff --git a/src/ui/connection/connection_form.vala b/src/ui/connection/connection_form.vala index bb6baad..b5fcca6 100644 --- a/src/ui/connection/connection_form.vala +++ b/src/ui/connection/connection_form.vala @@ -27,8 +27,6 @@ namespace Psequel { construct { debug ("[CONTRUCT] %s", this.name); - // init service - query_service = ResourceManager.instance ().query_service; // Create group to maped the entry widget to connection data. this.binddings = new BindingGroup (); @@ -41,7 +39,8 @@ namespace Psequel { // signals can only be connected after the window is ready. // because widget access window to get signals. ResourceManager.instance ().app_signals.window_ready.connect (() => { - signals = get_parrent_window (this).signals; + var window = get_parrent_window (this); + signals = window.signals; signals.selection_changed.connect ((conn) => { mapped_conn = conn; @@ -51,6 +50,8 @@ namespace Psequel { mapped_conn = conn; connect_btn.clicked (); }); + + query_service = window.query_service; }); } diff --git a/src/ui/query/query_editor.vala b/src/ui/query/query_editor.vala index 599e85b..c74daf1 100644 --- a/src/ui/query/query_editor.vala +++ b/src/ui/query/query_editor.vala @@ -18,11 +18,17 @@ namespace Psequel { debug ("[CONTRUCT] %s", this.name); debug ("Contruct view"); - query_service = ResourceManager.instance ().query_service; lang_manager = LanguageManager.get_default (); style_manager = StyleSchemeManager.get_default (); default_setttings (); + setup_signals (); + } + + private void setup_signals () { + ResourceManager.instance ().app_signals.window_ready.connect (() => { + query_service = get_parrent_window (this).query_service; + }); } diff --git a/src/ui/query/query_view.vala b/src/ui/query/query_view.vala index 8a9da47..998f53b 100644 --- a/src/ui/query/query_view.vala +++ b/src/ui/query/query_view.vala @@ -40,10 +40,6 @@ namespace Psequel { construct { debug ("[CONTRUCT] %s", this.name); - query_service = ResourceManager.instance ().query_service; - - schema_service = new SchemaService (query_service); - schemas = new ObservableArrayList (); var exp = new Gtk.PropertyExpression (typeof (Gtk.StringObject), null, "string"); tbname_filter = new Gtk.StringFilter (exp); @@ -70,8 +66,8 @@ namespace Psequel { var schema_list = yield schema_service.schema_list (); // Clear last item. - schema_dropdown.model = null; + schemas.clear (); for (int i = 0; i < schema_list.length; i++) { var cur_schema = yield schema_service.load_schema (schema_list[i]); @@ -156,7 +152,9 @@ namespace Psequel { // signals can only be connected after the window is ready. // because widget access window to get signals. ResourceManager.instance ().app_signals.window_ready.connect (() => { - signals = get_parrent_window (this).signals; + var window = get_parrent_window (this); + + signals = window.signals; signals.database_connected.connect (() => { debug ("Handle database_connected."); @@ -164,6 +162,12 @@ namespace Psequel { }); schema_dropdown.notify["selected"].connect (schema_changed); + + query_service = window.query_service; + debug ("Query: %p", query_service); + + schema_service = new SchemaService (query_service); + schemas = new ObservableArrayList (); }); } diff --git a/src/ui/query/table_data_view.vala b/src/ui/query/table_data_view.vala index b0a5277..b8e8b74 100644 --- a/src/ui/query/table_data_view.vala +++ b/src/ui/query/table_data_view.vala @@ -21,7 +21,6 @@ namespace Psequel { construct { debug ("[CONTRUCT] %s", this.name); - query_service = ResourceManager.instance ().query_service; model = new ObservableArrayList (); var setting = ResourceManager.instance ().settings; @@ -92,6 +91,8 @@ namespace Psequel { signals.schema_changed.connect ((schema) => { this.schema = schema; }); + + query_service = get_parrent_window (this).query_service; }); } diff --git a/src/ui/window.vala b/src/ui/window.vala index 589c597..235229d 100644 --- a/src/ui/window.vala +++ b/src/ui/window.vala @@ -26,6 +26,7 @@ namespace Psequel { public class Window : Adw.ApplicationWindow { public WindowSignals signals {get; set; default = null;} + public QueryService query_service {get; set; default = null;} public Window (Application app) { Object (application: app); From dfac3710989855bfd1e0324facffebca0645d126 Mon Sep 17 00:00:00 2001 From: ppvan Date: Wed, 2 Aug 2023 22:08:56 +0700 Subject: [PATCH 3/6] new window action --- res/gtk/connection-form.blp | 528 +++++++++++++------------ res/gtk/query-view.blp | 6 + src/application.vala | 6 + src/ui/connection/connection_form.vala | 2 +- 4 files changed, 282 insertions(+), 260 deletions(-) diff --git a/res/gtk/connection-form.blp b/res/gtk/connection-form.blp index 309687f..c1f8efc 100644 --- a/res/gtk/connection-form.blp +++ b/res/gtk/connection-form.blp @@ -1,301 +1,311 @@ using Gtk 4.0; using Adw 1; -template $PsequelConnectionForm : Gtk.Box { +template $PsequelConnectionForm : Adw.Bin { - orientation: vertical; - hexpand: true; - vexpand: true; + child: WindowHandle { + Box { + orientation: vertical; + hexpand: true; + vexpand: true; + Adw.HeaderBar header { + styles ["flat"] - - Adw.HeaderBar header { - styles ["flat"] - - [title] - Label { - label: ""; - } - - // Dupplicate primary_menu in query-view.blp. - // Update both if you change something - [end] - MenuButton { - icon-name: "open-menu-symbolic"; - menu-model: primary_menu; - } - } - - Adw.Clamp { - valign: center; - maximum-size: 800; - Box { - orientation: vertical; - styles ["connection-form", "frame"] - // vexpand: true; - spacing: 4; - - Label { - margin-top: 20; - margin-bottom: 40; - styles ["title-0"] - - label: "Connect with Psequel"; - } - - Box { - spacing: 8; - + [title] Label { - label: "URL:"; - } - - Entry url_entry { - placeholder-text: "postgres://..."; - hexpand: true; - activate => $on_entry_activated(); - changed => $on_url_entry_changed(); - } + label: ""; } - Label err_label { - styles ["secondary"] - height-request: 48; - valign: start; - label: " "; + // Dupplicate primary_menu in query-view.blp. + // Update both if you change something + [end] + MenuButton { + icon-name: "open-menu-symbolic"; + menu-model: primary_menu; } - - CenterBox { - margin-top: 0; - margin-bottom: 24; - [start] - Box { - orientation: vertical; - hexpand: true; - valign: center; - margin-start: 8; - margin-end: 8; - Separator { - - } - } - [center] - Label { - styles ["title-3"] - label: "OR"; - } - [end] + } + + Adw.Clamp { + valign: start; + hexpand: true; + vexpand: true; + maximum-size: 800; Box { orientation: vertical; - hexpand: true; - valign: center; - margin-start: 8; - margin-end: 8; - Separator { - - } - } - } - - Grid { - - hexpand: true; - vexpand: true; - row-homogeneous: true; - row-spacing: 8; - column-spacing: 8; - margin-start: 4; - margin-end: 4; - - Label { - halign: end; - label: "Name:"; - - layout { - row: 0; - column: 0; - column-span: 3; - } - } - - Label { - halign: end; - label: "Host:"; - - layout { - row: 1; - column: 0; - column-span: 3; - } - } - - Label { - halign: end; - label: "User:"; - - layout { - row: 2; - column: 0; - column-span: 3; - } - } - - Label { - halign: end; - label: "Password:"; - - layout { - row: 3; - column: 0; - column-span: 3; - } - } - - Label { - halign: end; - label: "Database:"; + styles ["connection-form"] + // vexpand: true; + spacing: 4; - layout { - row: 4; - column: 0; - column-span: 3; + Label { + margin-top: 20; + margin-bottom: 40; + styles ["title-0"] + + label: "Connect with Psequel"; } - } - - Entry name_entry { - placeholder-text: "Connection name"; - hexpand: true; - activate => $on_entry_activated(); - layout { - row: 0; - column: 3; - column-span: 7; - } - } - - Entry host_entry { - placeholder-text: "localhost"; - activate => $on_entry_activated(); + Box { + spacing: 8; - layout { - row: 1; - column: 3; - column-span: 5; - } - } - - Label { - label: "Port"; - halign: end; - layout { - row: 1; - column: 8; + Label { + label: "URL:"; + } + + Entry url_entry { + placeholder-text: "postgres://..."; + hexpand: true; + activate => $on_entry_activated(); + changed => $on_url_entry_changed(); + } } - } - - Entry port_entry { - placeholder-text: "5432"; - activate => $on_entry_activated(); - - layout { - row: 1; - column: 9; - column-span: 1; + + Label err_label { + styles ["secondary"] + height-request: 48; + valign: start; + label: " "; } - } - - Entry user_entry { - placeholder-text: "postgres"; - activate => $on_entry_activated(); - layout { - row: 2; - column: 3; - column-span: 7; + CenterBox { + margin-top: 0; + margin-bottom: 24; + [start] + Box { + orientation: vertical; + hexpand: true; + valign: center; + margin-start: 8; + margin-end: 8; + Separator { + + } + } + [center] + Label { + styles ["title-3"] + label: "OR"; + } + [end] + Box { + orientation: vertical; + hexpand: true; + valign: center; + margin-start: 8; + margin-end: 8; + Separator { + + } + } } - } - - PasswordEntry password_entry { - placeholder-text: ""; - show-peek-icon: true; - activate => $on_entry_activated(); - layout { - row: 3; - column: 3; - column-span: 7; - } - } - + Grid { - Entry database_entry { - placeholder-text: "postgres"; - activate => $on_entry_activated(); + hexpand: true; + vexpand: true; + row-homogeneous: true; + row-spacing: 8; + column-spacing: 8; + margin-start: 4; + margin-end: 4; - layout { - row: 4; - column: 3; - column-span: 7; - } - } - - Label { - label: "SSL:"; - halign: end; - layout { - row: 5; - column: 0; - column-span: 3; - } + Label { + halign: end; + label: "Name:"; + + layout { + row: 0; + column: 0; + column-span: 3; + } + } + + Label { + halign: end; + label: "Host:"; + + layout { + row: 1; + column: 0; + column-span: 3; + } + } + + Label { + halign: end; + label: "User:"; + + layout { + row: 2; + column: 0; + column-span: 3; + } + } + + Label { + halign: end; + label: "Password:"; + + layout { + row: 3; + column: 0; + column-span: 3; + } + } + + Label { + halign: end; + label: "Database:"; + + layout { + row: 4; + column: 0; + column-span: 3; + } + } + + Entry name_entry { + placeholder-text: "Connection name"; + hexpand: true; + activate => $on_entry_activated(); + + layout { + row: 0; + column: 3; + column-span: 7; + } + } + + Entry host_entry { + placeholder-text: "localhost"; + activate => $on_entry_activated(); + + layout { + row: 1; + column: 3; + column-span: 5; + } + } + + Label { + label: "Port"; + halign: end; + layout { + row: 1; + column: 8; + } + } + + Entry port_entry { + placeholder-text: "5432"; + activate => $on_entry_activated(); + + layout { + row: 1; + column: 9; + column-span: 1; + } + } + + Entry user_entry { + placeholder-text: "postgres"; + activate => $on_entry_activated(); + + layout { + row: 2; + column: 3; + column-span: 7; + } + } + + PasswordEntry password_entry { + placeholder-text: ""; + show-peek-icon: true; + activate => $on_entry_activated(); + + layout { + row: 3; + column: 3; + column-span: 7; + } + } + + + Entry database_entry { + placeholder-text: "postgres"; + activate => $on_entry_activated(); + + layout { + row: 4; + column: 3; + column-span: 7; + } + } + + Label { + label: "SSL:"; + halign: end; + layout { + row: 5; + column: 0; + column-span: 3; + } + } + + Box { + orientation: horizontal; + Box { + valign: center; + orientation: vertical; + Switch ssl_switch {} + } + layout { + row: 5; + column: 3; + } + } } Box { - orientation: horizontal; - Box { - valign: center; - orientation: vertical; - Switch ssl_switch {} - } - layout { - row: 5; - column: 3; + + margin-top: 20; + margin-bottom: 10; + + Label status_label { + label: ""; + halign: start; + hexpand: true; } - } - } - - Box { - margin-top: 20; - margin-bottom: 10; - - Label status_label { - label: ""; - halign: start; - hexpand: true; - } + Box { - Box { + spacing: 8; - spacing: 8; + Spinner spinner { + + } - Spinner spinner { - + Button connect_btn { + styles ["suggested-action"] + label: "Connect"; + clicked => $on_connect_clicked(); + } + } } - Button connect_btn { - styles ["suggested-action"] - label: "Connect"; - clicked => $on_connect_clicked(); - } } } - } - } + }; } menu primary_menu { section { + + item { + label: _("_New Window"); + action: "app.new-window"; + } + item { label: _("_Preferences"); action: "app.preferences"; diff --git a/res/gtk/query-view.blp b/res/gtk/query-view.blp index 37a64de..896e3d5 100644 --- a/res/gtk/query-view.blp +++ b/res/gtk/query-view.blp @@ -270,6 +270,12 @@ template $PsequelQueryView : Adw.Bin { menu primary_menu { section { + + item { + label: _("_New Window"); + action: "app.new-window"; + } + item { label: _("_Preferences"); action: "app.preferences"; diff --git a/src/application.vala b/src/application.vala index 0406acc..9936505 100644 --- a/src/application.vala +++ b/src/application.vala @@ -38,6 +38,7 @@ namespace Psequel { ActionEntry[] action_entries = { { "about", this.on_about_action }, { "preferences", this.on_preferences_action }, + { "new-window", this.on_new_window }, { "quit", this.quit } }; this.add_action_entries (action_entries, this); @@ -139,6 +140,11 @@ namespace Psequel { about.present (); } + private void on_new_window () { + var window = new_window (); + window.present (); + } + private void on_preferences_action () { if (this.preference == null) { diff --git a/src/ui/connection/connection_form.vala b/src/ui/connection/connection_form.vala index b5fcca6..1adc7ed 100644 --- a/src/ui/connection/connection_form.vala +++ b/src/ui/connection/connection_form.vala @@ -1,7 +1,7 @@ namespace Psequel { [GtkTemplate (ui = "/me/ppvan/psequel/gtk/connection-form.ui")] - public class ConnectionForm : Gtk.Box { + public class ConnectionForm : Adw.Bin { BindingGroup binddings; From d1cd46b8422e1a75872020a23b253fb50d2c3732 Mon Sep 17 00:00:00 2001 From: ppvan Date: Wed, 2 Aug 2023 22:23:16 +0700 Subject: [PATCH 4/6] simplify some UI --- res/gtk/connection-form.blp | 14 +++++++++++++- res/gtk/connection-recent.blp | 21 --------------------- src/application.vala | 1 + src/ui/connection/connection_recent.vala | 18 ++++++++---------- 4 files changed, 22 insertions(+), 32 deletions(-) diff --git a/res/gtk/connection-form.blp b/res/gtk/connection-form.blp index c1f8efc..120df77 100644 --- a/res/gtk/connection-form.blp +++ b/res/gtk/connection-form.blp @@ -300,12 +300,24 @@ template $PsequelConnectionForm : Adw.Bin { menu primary_menu { section { - item { label: _("_New Window"); action: "app.new-window"; } + } + section { + item { + label: _("_Import Connections"); + action: "app.new-window"; + } + item { + label: _("_Export Connections"); + action: "app.new-window"; + } + } + + section { item { label: _("_Preferences"); action: "app.preferences"; diff --git a/res/gtk/connection-recent.blp b/res/gtk/connection-recent.blp index 5d86e82..70312ad 100644 --- a/res/gtk/connection-recent.blp +++ b/res/gtk/connection-recent.blp @@ -20,21 +20,7 @@ template $PsequelConnectionSidebar : Gtk.Box { spacing: 4; hexpand: true; halign: end; - - Button { - styles ["flat", "big-icon", "linked"] - icon-name: "document-export-symbolic"; - tooltip-text: "Import Connection"; - clicked => $on_import_connection(); - } - Button { - styles ["flat", "big-icon", "linked"] - icon-name: "document-import-symbolic"; - tooltip-text: "Export Connection"; - clicked => $on_export_connection(); - } - Button { tooltip-text: "Add new connection"; @@ -42,13 +28,6 @@ template $PsequelConnectionSidebar : Gtk.Box { icon-name: "plus-large-symbolic"; clicked => $on_add_connection(); } - - Button { - tooltip-text: "Remove selected connection"; - styles ["flat"] - icon-name: "minus-large-symbolic"; - clicked => $on_remove_btn_clicked(); - } } } diff --git a/src/application.vala b/src/application.vala index 9936505..563fa8f 100644 --- a/src/application.vala +++ b/src/application.vala @@ -145,6 +145,7 @@ namespace Psequel { window.present (); } + private void on_preferences_action () { if (this.preference == null) { diff --git a/src/ui/connection/connection_recent.vala b/src/ui/connection/connection_recent.vala index 12ff112..3e31587 100644 --- a/src/ui/connection/connection_recent.vala +++ b/src/ui/connection/connection_recent.vala @@ -10,6 +10,10 @@ namespace Psequel { { "connect", on_connect_connection }, { "dupplicate", on_dupplicate_connection }, { "delete", on_remove_connection }, + + { "import", on_import_connection }, + { "export", on_export_connection }, + }; private Application app; @@ -98,12 +102,6 @@ namespace Psequel { conn_list.select_row (last_row); } - // On remove, remove selected connection and select pos - 1. - [GtkCallback] - public void on_remove_btn_clicked (Gtk.Button btn) { - remove_connection (); - } - private Gtk.ListBoxRow row_factory (Object item) { if (item is Connection) { @@ -116,14 +114,14 @@ namespace Psequel { } } - [GtkCallback] - private void on_import_connection (Gtk.Button btn) { + + private void on_import_connection () { debug ("Importting connections"); open_file_dialog.begin ("Import Connections"); } - [GtkCallback] - private void on_export_connection (Gtk.Button btn) { + + private void on_export_connection () { debug ("Exporting connections"); save_file_dialog.begin ("Export Connections"); } From a257833a0f75cf6bfcfe72fab34aa14c8290cab8 Mon Sep 17 00:00:00 2001 From: ppvan Date: Wed, 2 Aug 2023 22:24:33 +0700 Subject: [PATCH 5/6] fix action nmaes --- res/gtk/connection-form.blp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/gtk/connection-form.blp b/res/gtk/connection-form.blp index 120df77..dc0617b 100644 --- a/res/gtk/connection-form.blp +++ b/res/gtk/connection-form.blp @@ -308,12 +308,12 @@ menu primary_menu { section { item { label: _("_Import Connections"); - action: "app.new-window"; + action: "conn.import"; } item { label: _("_Export Connections"); - action: "app.new-window"; + action: "conn.export"; } } From e9d8c45be207aa200dec2b8a5e88ce0b4b5d6a4a Mon Sep 17 00:00:00 2001 From: ppvan Date: Wed, 2 Aug 2023 22:52:48 +0700 Subject: [PATCH 6/6] fix import export action is disable --- res/gtk/connection-form.blp | 4 ++-- src/ui/connection/connection_recent.vala | 22 ++++++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/res/gtk/connection-form.blp b/res/gtk/connection-form.blp index dc0617b..3bab371 100644 --- a/res/gtk/connection-form.blp +++ b/res/gtk/connection-form.blp @@ -308,12 +308,12 @@ menu primary_menu { section { item { label: _("_Import Connections"); - action: "conn.import"; + action: "app.import"; } item { label: _("_Export Connections"); - action: "conn.export"; + action: "app.export"; } } diff --git a/src/ui/connection/connection_recent.vala b/src/ui/connection/connection_recent.vala index 3e31587..dd67018 100644 --- a/src/ui/connection/connection_recent.vala +++ b/src/ui/connection/connection_recent.vala @@ -10,10 +10,13 @@ namespace Psequel { { "connect", on_connect_connection }, { "dupplicate", on_dupplicate_connection }, { "delete", on_remove_connection }, + }; + // Import and export require access to this.model but also have to visible in app menu. + // So, it's on application action maps + const ActionEntry[] APP_ACTIONS = { { "import", on_import_connection }, { "export", on_export_connection }, - }; private Application app; @@ -44,7 +47,6 @@ namespace Psequel { this.setup_bindings (); this.setup_action (); }); - } private void setup_action () { @@ -52,7 +54,9 @@ namespace Psequel { var action_group = new SimpleActionGroup (); action_group.add_action_entries (ACTION_ENTRIES, this); - insert_action_group ("conn", action_group); + this.insert_action_group ("conn", action_group); + + app.add_action_entries (APP_ACTIONS, this); } public void setup_bindings () { @@ -84,7 +88,7 @@ namespace Psequel { return; } - // Emit connection changed for any one subcribe to it. + // Emit connection changed for any one subcribe to it. signals.selection_changed (conn_row.conn_data); debug ("mapped widget binding to another row"); @@ -114,13 +118,11 @@ namespace Psequel { } } - private void on_import_connection () { debug ("Importting connections"); open_file_dialog.begin ("Import Connections"); } - private void on_export_connection () { debug ("Exporting connections"); save_file_dialog.begin ("Export Connections"); @@ -184,6 +186,12 @@ namespace Psequel { private async void open_file_dialog (string title = "Open File") { var filter = new Gtk.FileFilter (); filter.add_mime_type ("application/json"); + + var window = (Window) app.active_window; + + debug (this.name); + + var file_dialog = new Gtk.FileDialog () { modal = true, initial_folder = File.new_for_path (Environment.get_home_dir ()), @@ -193,7 +201,6 @@ namespace Psequel { }; uint8[] contents; - var window = (Window) app.active_window; try { var file = yield file_dialog.open (window, null); @@ -289,7 +296,6 @@ namespace Psequel { model.insert (dupp, pos + 1); } - private void request_connect_database () { var selected = conn_list.get_selected_row (); // Selection mode must be browse (only 1 selection)