diff --git a/res/gtk/schema-main.blp b/res/gtk/schema-main.blp index 82cabde..8baa97e 100644 --- a/res/gtk/schema-main.blp +++ b/res/gtk/schema-main.blp @@ -80,8 +80,6 @@ template $PsequelSchemaMain : Gtk.Box { icon-name: "terminal-symbolic"; title: "Query"; child: $PsequelQueryEditor { - query-viewmodel: bind template.query-viewmodel; - query-history-viewmodel: bind template.query-viewmodel as <$PsequelQueryViewModel>.query-history-viewmodel; }; } } diff --git a/res/gtk/schema-view.blp b/res/gtk/schema-view.blp index f90d5f2..e41073b 100644 --- a/res/gtk/schema-view.blp +++ b/res/gtk/schema-view.blp @@ -22,11 +22,6 @@ template $PsequelSchemaView : Adw.Bin { menu: primary_menu; view-mode: bind sidebar.view-mode; - // selected-table: bind sidebar.selected-table; - // selected-view: bind sidebar.selected-view; - table-viewmodel: bind template.schema-viewmodel as <$PsequelSchemaViewModel>.table-viewmodel; - view-viewmodel: bind template.schema-viewmodel as <$PsequelSchemaViewModel>.view-viewmodel; - query-viewmodel: bind template.schema-viewmodel as <$PsequelSchemaViewModel>.query-viewmodel; } } } diff --git a/res/gtk/window.blp b/res/gtk/window.blp index 10f68d1..6cfca66 100644 --- a/res/gtk/window.blp +++ b/res/gtk/window.blp @@ -18,7 +18,6 @@ template $PsequelWindow : Adw.ApplicationWindow { StackPage { name: "connection-view"; child: $PsequelConnectionView { - request-database => $on_connect_db (); }; } diff --git a/src/application.vala b/src/application.vala index cdebfb7..4cf9f9e 100644 --- a/src/application.vala +++ b/src/application.vala @@ -182,24 +182,30 @@ namespace Psequel { } private Container create_viewmodels () { + var container = new Container (); + + // services var sql_service = new SQLService (Application.background); + var schema_service = new SchemaService (sql_service); var repository = new ConnectionRepository (Application.settings); + var navigation = new NavigationService (); - // connection and schemas - var conn_vm = new ConnectionViewModel (repository); - var sche_vm = new SchemaViewModel (sql_service); - + // viewmodels + var conn_vm = new ConnectionViewModel (repository, sql_service, navigation); + var sche_vm = new SchemaViewModel (schema_service); var table_vm = new TableViewModel (sql_service); var view_vm = new ViewViewModel (sql_service); var table_structure_vm = new TableStructureViewModel (sql_service); var view_structure_vm = new ViewStructureViewModel (sql_service); var table_data_vm = new TableDataViewModel (sql_service); var view_data_vm = new ViewDataViewModel (sql_service); + var query_history_vm = new QueryHistoryViewModel (sql_service); + var query_vm = new QueryViewModel (query_history_vm); - var navigation = new NavigationService (); - - var container = new Container (); container.register (sql_service); + container.register (schema_service); + container.register (repository); + container.register (navigation); container.register (conn_vm); container.register (sche_vm); container.register (table_vm); @@ -208,7 +214,11 @@ namespace Psequel { container.register (view_structure_vm); container.register (table_data_vm); container.register (view_data_vm); - container.register (navigation); + container.register (query_history_vm); + container.register (query_vm); + + // events + conn_vm.subcribe (Event.ACTIVE_CONNECTION, sche_vm); sche_vm.subcribe (Event.SCHEMA_CHANGED, table_vm); sche_vm.subcribe (Event.SCHEMA_CHANGED, view_vm); @@ -217,6 +227,7 @@ namespace Psequel { table_vm.subcribe (Event.SELECTED_TABLE_CHANGED, table_structure_vm); table_vm.subcribe (Event.SELECTED_TABLE_CHANGED, table_data_vm); + view_vm.subcribe (Event.SELECTED_VIEW_CHANGED, view_structure_vm); view_vm.subcribe (Event.SELECTED_VIEW_CHANGED, view_data_vm); diff --git a/src/services/SQLCompletionProvider.vala b/src/services/SQLCompletionProvider.vala index fd1d1ff..9de9dd1 100644 --- a/src/services/SQLCompletionProvider.vala +++ b/src/services/SQLCompletionProvider.vala @@ -8,11 +8,12 @@ namespace Psequel { private Gtk.FilterListModel model; private Gtk.StringFilter filter; - public QueryViewModel query_viewmodel { get; set; } + private SchemaViewModel schema_viewmodel; public SQLCompletionProvider () { base (); debug ("SQLCompletionProvider"); + this.schema_viewmodel = autowire (); static_candidates = new List (); for (int i = 0; i < PGListerals.KEYWORDS.length; i++) { @@ -31,21 +32,19 @@ namespace Psequel { static_candidates.append (new Model (PGListerals.RESERVED[i], "RESERVED")); } - /* - Query viewmodel is not set until the query view is created. - */ - dynamic_candidates = new List (); - this.notify["query-viewmodel"].connect (() => { - dynamic_candidates = new List (); - query_viewmodel.current_schema.tables.foreach ((table) => { - dynamic_candidates.append (new Model (table.name, "TABLE")); - }); - query_viewmodel.current_schema.views.foreach ((view) => { - dynamic_candidates.append (new Model (view.name, "VIEW")); - }); - }); + // this.notify["query-viewmodel"].connect (() => { + + // dynamic_candidates = new List (); + // query_viewmodel.current_schema.tables.foreach ((table) => { + // dynamic_candidates.append (new Model (table.name, "TABLE")); + // }); + + // query_viewmodel.current_schema.views.foreach ((view) => { + // dynamic_candidates.append (new Model (view.name, "VIEW")); + // }); + // }); var expression = new Gtk.PropertyExpression (typeof (Model), null, "value"); filter = new Gtk.StringFilter (expression); @@ -102,6 +101,18 @@ namespace Psequel { public async GLib.ListModel populate_async (GtkSource.CompletionContext context, GLib.Cancellable? cancellable) { + /* + Query viewmodel is not set until the query view is created. + */ + dynamic_candidates = new List (); + schema_viewmodel.current_schema.tables.foreach ((table) => { + dynamic_candidates.append (new Model (table.name, "TABLE")); + }); + + schema_viewmodel.current_schema.views.foreach ((view) => { + dynamic_candidates.append (new Model (view.name, "VIEW")); + }); + var candidates = new ObservableList (); candidates.append_all (static_candidates); candidates.append_all (dynamic_candidates); diff --git a/src/ui/Window.vala b/src/ui/Window.vala index 5fd26c4..68d2311 100644 --- a/src/ui/Window.vala +++ b/src/ui/Window.vala @@ -26,7 +26,7 @@ namespace Psequel { public class Window : Adw.ApplicationWindow { public static Container? temp; - public Container containter {get; construct;} + public Container containter { get; construct; } const ActionEntry[] ACTIONS = { { "import", import_connection }, @@ -37,7 +37,7 @@ namespace Psequel { public NavigationService navigation { get; private set; } public ConnectionViewModel connection_viewmodel { get; construct; } - public SchemaViewModel schema_viewmodel { get; construct; } + public QueryViewModel query_viewmodel { get; private set; } public Window (Application app, Container container) { @@ -48,10 +48,10 @@ namespace Psequel { } construct { - this.navigation = containter.find_type (typeof (NavigationService)) as NavigationService; - this.connection_viewmodel = containter.find_type (typeof (ConnectionViewModel)) as ConnectionViewModel; - this.schema_viewmodel = containter.find_type (typeof (SchemaViewModel)) as SchemaViewModel; - + this.navigation = autowire (); + this.connection_viewmodel = autowire (); + this.query_viewmodel = autowire (); + debug ("[CONTRUCT] %s", this.name); Application.settings.bind ("window-width", this, "default-width", SettingsBindFlags.DEFAULT); Application.settings.bind ("window-height", this, "default-height", SettingsBindFlags.DEFAULT); @@ -62,28 +62,13 @@ namespace Psequel { overlay.add_toast (toast); } - [GtkCallback] - public async void on_connect_db (Connection conn) { - debug ("Window connect"); - connection_viewmodel.is_connectting = true; - try { - yield schema_viewmodel.connect_db (conn); - - navigation.navigate (NavigationService.QUERY_VIEW); - } catch (PsequelError err) { - create_dialog ("Connection Error", err.message).present (); - } - - connection_viewmodel.is_connectting = false; - } - // Actions: public void run_query () { - if (schema_viewmodel.query_viewmodel == null) { + if (query_viewmodel == null) { return; } - schema_viewmodel.query_viewmodel.run_selected_query.begin (); + query_viewmodel.run_selected_query.begin (); } public void import_connection () { @@ -156,7 +141,7 @@ namespace Psequel { unowned var conns = connection_viewmodel.export_connections (); var content = ValueConverter.serialize_connection (conns); - var bytes = new Bytes.take (content.data); // Move data to byte so it live when out scope + var bytes = new Bytes.take (content.data); // Move data to byte so it live when out scope var window = (Window) get_parrent_window (this); try { diff --git a/src/ui/connection/ConnectionSidebar.vala b/src/ui/connection/ConnectionSidebar.vala index b9899a6..6a2c0ae 100644 --- a/src/ui/connection/ConnectionSidebar.vala +++ b/src/ui/connection/ConnectionSidebar.vala @@ -33,7 +33,6 @@ namespace Psequel { selection_model.bind_property ("selected", this, "selected-connection", DEFAULT | BIDIRECTIONAL, from_selected, to_selected); - } // On add, create new connection and select it. @@ -90,8 +89,8 @@ namespace Psequel { [GtkChild] private unowned Gtk.SingleSelection selection_model; - // [GtkChild] - // private unowned Gtk.ListView listview; + // [GtkChild] + // private unowned Gtk.ListView listview; } [GtkTemplate (ui = "/me/ppvan/psequel/gtk/connection-row.ui")] diff --git a/src/ui/connection/ConnectionView.vala b/src/ui/connection/ConnectionView.vala index 26c67dc..f490c13 100644 --- a/src/ui/connection/ConnectionView.vala +++ b/src/ui/connection/ConnectionView.vala @@ -4,11 +4,7 @@ namespace Psequel { [GtkTemplate (ui = "/me/ppvan/psequel/gtk/connection-view.ui")] public class ConnectionView : Adw.Bin { - - - public ConnectionViewModel viewmodel { get; set; } - - public signal void request_database (Connection conn); + public ConnectionViewModel viewmodel { get; private set; } public ConnectionView (Application app) { Object (); @@ -18,10 +14,7 @@ namespace Psequel { construct { debug ("[CONTRUCT] %s", this.name); setup_paned (paned); - - debug ("%s", Window.temp.get_type ().name ()); - var container = Window.temp as Psequel.Container; - viewmodel = container.find_type (typeof (ConnectionViewModel)) as ConnectionViewModel; + viewmodel = autowire (); } [GtkCallback] @@ -36,8 +29,7 @@ namespace Psequel { [GtkCallback] public void active_connection (Connection conn) { - viewmodel.is_connectting = true; - request_database (conn); + viewmodel.active_connection.begin (conn); } [GtkCallback] diff --git a/src/ui/schema/QueryEditor.vala b/src/ui/schema/QueryEditor.vala index e8e0de7..3856a06 100644 --- a/src/ui/schema/QueryEditor.vala +++ b/src/ui/schema/QueryEditor.vala @@ -31,18 +31,16 @@ namespace Psequel { construct { debug ("[CONTRUCT] %s", this.name); - default_setttings (); + this.query_viewmodel = autowire (); + this.query_history_viewmodel = autowire (); + default_setttings (); selection_model.bind_property ("selected", this, "selected-query", BindingFlags.BIDIRECTIONAL, from_selected, to_selected); spinner.bind_property ("spinning", run_query_btn, "sensitive", BindingFlags.INVERT_BOOLEAN); buffer.changed.connect (highlight_current_query); buffer.cursor_moved.connect (highlight_current_query); - this.notify["query-viewmodel"].connect (() => { - this.provider.query_viewmodel = query_viewmodel; - }); - create_action_group (); setup_paned (paned); } diff --git a/src/ui/schema/SchemaSidebar.vala b/src/ui/schema/SchemaSidebar.vala index 24859ac..22cb743 100644 --- a/src/ui/schema/SchemaSidebar.vala +++ b/src/ui/schema/SchemaSidebar.vala @@ -16,10 +16,10 @@ namespace Psequel { } construct { - this.table_viewmodel = (TableViewModel)Window.temp.find_type (typeof (TableViewModel)); - this.view_viewmodel = (ViewViewModel)Window.temp.find_type (typeof (ViewViewModel)); - this.schema_viewmodel = (SchemaViewModel)Window.temp.find_type (typeof (SchemaViewModel)); - this.navigation_service = (NavigationService)Window.temp.find_type (typeof (NavigationService)); + this.table_viewmodel = autowire (); + this.view_viewmodel = autowire (); + this.schema_viewmodel = autowire (); + this.navigation_service = autowire (); sql_views.bind_property ("visible-child-name", this, "view-mode", DEFAULT); diff --git a/src/ui/schema/SchemaView.vala b/src/ui/schema/SchemaView.vala index bde62ad..75600b5 100644 --- a/src/ui/schema/SchemaView.vala +++ b/src/ui/schema/SchemaView.vala @@ -13,8 +13,7 @@ namespace Psequel { construct { setup_paned (paned); - var container = Window.temp; - schema_viewmodel = container.find_type (typeof (SchemaViewModel)) as SchemaViewModel; + schema_viewmodel = autowire (); } diff --git a/src/ui/schema/TableDataView.vala b/src/ui/schema/TableDataView.vala index 21763d9..4ebdc88 100644 --- a/src/ui/schema/TableDataView.vala +++ b/src/ui/schema/TableDataView.vala @@ -10,7 +10,7 @@ namespace Psequel { } construct { - tabledata_viewmodel = Window.temp.find_type (typeof (TableDataViewModel)) as TableDataViewModel; + tabledata_viewmodel = autowire (); } [GtkCallback] diff --git a/src/ui/schema/TableStructureView.vala b/src/ui/schema/TableStructureView.vala index 3f370d1..436c52c 100644 --- a/src/ui/schema/TableStructureView.vala +++ b/src/ui/schema/TableStructureView.vala @@ -14,7 +14,7 @@ namespace Psequel { } construct { - this.tablestructure_viewmodel = Window.temp.find_type (typeof (TableStructureViewModel)) as TableStructureViewModel; + this.tablestructure_viewmodel = autowire (); this.filter = new Gtk.StringFilter (null); filter.expression = new Gtk.PropertyExpression (typeof (BaseType), null, "table"); diff --git a/src/ui/schema/ViewDataView.vala b/src/ui/schema/ViewDataView.vala index a9327ac..8e7b68a 100644 --- a/src/ui/schema/ViewDataView.vala +++ b/src/ui/schema/ViewDataView.vala @@ -10,7 +10,7 @@ namespace Psequel { } construct { - viewdata_viewmodel = Window.temp.find_type (typeof (ViewDataViewModel)) as ViewDataViewModel; + viewdata_viewmodel = autowire (); } [GtkCallback] diff --git a/src/ui/schema/ViewStructureView.vala b/src/ui/schema/ViewStructureView.vala index 479a382..71f77c6 100644 --- a/src/ui/schema/ViewStructureView.vala +++ b/src/ui/schema/ViewStructureView.vala @@ -13,7 +13,7 @@ namespace Psequel { } construct { - this.viewstructure_viewmodel = Window.temp.find_type (typeof (ViewStructureViewModel)) as ViewStructureViewModel; + this.viewstructure_viewmodel = autowire (); var expresion = new Gtk.PropertyExpression (typeof(BaseType), null, "table"); this.filter = new Gtk.StringFilter (expresion); diff --git a/src/utils/Event.vala b/src/utils/Event.vala index 22d58d5..f55abc4 100644 --- a/src/utils/Event.vala +++ b/src/utils/Event.vala @@ -36,6 +36,7 @@ namespace Psequel { public const string SCHEMA_CHANGED = "schema-changed"; public const string SELECTED_TABLE_CHANGED = "selected-table-changed"; public const string SELECTED_VIEW_CHANGED = "selected-view-changed"; + public const string ACTIVE_CONNECTION = "active-connection"; public string type; public Object data; diff --git a/src/utils/helpers.vala b/src/utils/helpers.vala index a7246ba..6232350 100644 --- a/src/utils/helpers.vala +++ b/src/utils/helpers.vala @@ -40,6 +40,11 @@ namespace Psequel { }); } + public T autowire () { + var container = Window.temp; + return (T)container.find_type (typeof (T)); + } + public Adw.MessageDialog create_dialog (string heading, string body) { var window = Application.app.active_window; var dialog = new Adw.MessageDialog (window, heading, body); diff --git a/src/viewmodels/ConnectionViewModel.vala b/src/viewmodels/ConnectionViewModel.vala index 9f421ea..b12703c 100644 --- a/src/viewmodels/ConnectionViewModel.vala +++ b/src/viewmodels/ConnectionViewModel.vala @@ -1,7 +1,9 @@ namespace Psequel { public class ConnectionViewModel : BaseViewModel { uint timeout_id = 0; - public ConnectionRepository repository { get; construct; } + public ConnectionRepository repository { get; private set; } + public SQLService sql_service { get; private set; } + public NavigationService navigation_service { get; private set; } public ObservableList connections { get; private set; default = new ObservableList (); } public Connection? selected_connection { get; set; } @@ -9,24 +11,23 @@ namespace Psequel { /** True when trying to establish a connection util know results. */ public bool is_connectting { get; set; default = false; } + public ConnectionViewModel (ConnectionRepository repository, SQLService sql_service, NavigationService navigation_service) { + base (); + this.repository = repository; + this.sql_service = sql_service; + this.navigation_service = navigation_service; - - public ConnectionViewModel (ConnectionRepository repository) { - Object (repository: repository); - } - - construct { unowned var loaded_conn = repository.get_connections (); connections.extend (loaded_conn); if (connections.empty ()) { new_connection (); } - // selected_connection = (Connection)connections.get_item (2); // Auto save data each 10 secs in case app crash. Timeout.add_seconds (10, () => { repository.save (); + return Source.CONTINUE; }, Priority.LOW); } @@ -62,6 +63,20 @@ namespace Psequel { this.connections.append_all (connections); } + public async void active_connection (Connection connection) { + this.is_connectting = true; + try { + yield sql_service.connect_db (connection); + this.emit_event (Event.ACTIVE_CONNECTION, connection); + this.navigation_service.navigate (NavigationService.QUERY_VIEW); + + } catch (PsequelError err) { + debug ("Error: %s", err.message); + create_dialog ("Connection Error", err.message.dup ()).present (); + } + this.is_connectting = false; + } + public unowned List export_connections () { return repository.get_connections (); } diff --git a/src/viewmodels/QueryViewModel.vala b/src/viewmodels/QueryViewModel.vala index ad52759..ca749e9 100644 --- a/src/viewmodels/QueryViewModel.vala +++ b/src/viewmodels/QueryViewModel.vala @@ -10,9 +10,8 @@ namespace Psequel { public Schema? current_schema { get; construct; } public SQLService sql_service { get; construct; } - public QueryViewModel (Schema? current_schema, SQLService sql_service) { - Object (current_schema: current_schema,sql_service: sql_service); - query_history_viewmodel = new QueryHistoryViewModel (sql_service); + public QueryViewModel (QueryHistoryViewModel query_history_viewmodel) { + Object (query_history_viewmodel: query_history_viewmodel); } public async void run_selected_query () { diff --git a/src/viewmodels/SchemaViewModel.vala b/src/viewmodels/SchemaViewModel.vala index 5ad3a19..7032b5f 100644 --- a/src/viewmodels/SchemaViewModel.vala +++ b/src/viewmodels/SchemaViewModel.vala @@ -1,39 +1,34 @@ namespace Psequel { - public class SchemaViewModel : BaseViewModel { + public class SchemaViewModel : BaseViewModel, Observer { const string DEFAULT = "public"; public ObservableList schemas { get; set; default = new ObservableList (); } public Schema? current_schema { get; set; } - // Child viewmodel - public TableViewModel table_viewmodel { get; set; } - public ViewViewModel view_viewmodel { get; set; } - public QueryViewModel query_viewmodel { get; set; } - public SchemaRepository repository; // Services - public SQLService sql_service { get; private set; } + public SchemaService schema_service { get; private set; } - public SchemaViewModel (SQLService service) { + public SchemaViewModel (SchemaService service) { base(); - this.sql_service = service; + this.schema_service = service; this.notify["current-schema"].connect (() => { this.emit_event (Event.SCHEMA_CHANGED, current_schema); - // table_viewmodel = new TableViewModel (current_schema, sql_service); - // view_viewmodel = new ViewViewModel (current_schema, sql_service); - query_viewmodel = new QueryViewModel (current_schema, sql_service); }); } - public async void connect_db (Connection conn) throws PsequelError { - yield sql_service.connect_db (conn); + public void update (Event event) { + if (event.type == Event.ACTIVE_CONNECTION) { + database_connected.begin (); + } + } + public async void database_connected () throws PsequelError { // auto load schema list. yield list_schemas (); - yield load_schema (schemas.find (s => s.name == DEFAULT)); } @@ -52,9 +47,6 @@ namespace Psequel { } public async void list_schemas () throws PsequelError { - - schema_service = new SchemaService (sql_service); - var unload_schemas = yield schema_service.get_schemas (); schemas.append_all (unload_schemas);