From 22e949fa439273798d6718b837f817bbb97678ba Mon Sep 17 00:00:00 2001 From: Alessandro Date: Tue, 31 Mar 2020 23:38:20 -0700 Subject: [PATCH] Add github actions (#304) * Add github actions * Fix yaml syntax * Fix yaml syntax * Fix vala lint --- .editorconfig | 4 +- .github/workflows/build.yml | 25 + .github/workflows/lint.yml | 16 + README.md | 4 +- src/Application.vala | 18 +- src/Layouts/DataBaseSchema.vala | 816 +++++++-------- src/Layouts/DataBaseView.vala | 392 +++---- src/Layouts/HeaderBar.vala | 182 ++-- src/Layouts/Library.vala | 850 +++++++-------- src/Layouts/Main.vala | 152 +-- src/Layouts/Views/Content.vala | 496 ++++----- src/Layouts/Views/Query.vala | 1008 +++++++++--------- src/Layouts/Views/Relations.vala | 326 +++--- src/Layouts/Views/Structure.vala | 342 +++---- src/Layouts/Welcome.vala | 190 ++-- src/Main.vala | 8 +- src/Partials/ButtonType.vala | 82 +- src/Partials/Helpers.vala | 140 +-- src/Partials/LibraryItem.vala | 382 +++---- src/Partials/TreeBuilder.vala | 324 +++--- src/Services/ActionManager.vala | 410 ++++---- src/Services/ConnectionManager.vala | 1002 +++++++++--------- src/Services/DataManager.vala | 12 +- src/Services/PasswordManager.vala | 82 +- src/Services/Settings.vala | 298 +++--- src/Services/Types/DataBaseType.vala | 56 +- src/Services/Types/MySQL.vala | 80 +- src/Services/Types/PostgreSQL.vala | 16 +- src/Services/Types/SQLite.vala | 64 +- src/Services/UpgradeManager.vala | 50 +- src/Widgets/ConnectionDialog.vala | 1424 +++++++++++++------------- src/Window.vala | 124 +-- 32 files changed, 4716 insertions(+), 4659 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/lint.yml diff --git a/.editorconfig b/.editorconfig index b3fcc90e..dc57efd2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,6 +1,6 @@ root = true [*] -indent_style = tab +indent_style = space trim_trailing_whitespace = true insert_final_newline = true charset = utf-8 @@ -9,4 +9,4 @@ charset = utf-8 indent_size = 2 [*.vala] -indent_size = 4 \ No newline at end of file +indent_size = 4 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..cd0f73aa --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,25 @@ +name: "CI" + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + container: + image: elementary/docker:unstable + + steps: + - uses: actions/checkout@v1 + - name: Install Dependencies + run: | + apt update + apt install -y meson libgranite-dev libgtk-3-dev libjson-glib-dev libgudev-1.0-dev libevdev-dev libgtksourceview-3.0-dev libxml2-dev libglib2.0-dev libgda-5.0-dev libmysqlclient-dev libpq-dev libgda-5.0-mysql libgda-5.0-postgres libsecret-1-dev libssh2-1-dev valac + - name: Build + env: + DESTDIR: out + run: | + meson build + ninja -C build + ninja -C build install diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..e56bfc60 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,16 @@ +name: "CI: Lint" + +on: [push, pull_request] + +jobs: + lint: + + runs-on: ubuntu-latest + + container: + image: valalang/lint + + steps: + - uses: actions/checkout@v1 + - name: Lint + run: io.elementary.vala-lint -d . diff --git a/README.md b/README.md index 533b63ec..549eee02 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ If you like Sequeler and you want to support its development, consider donating ## Install it from source You can install Sequeler by compiling from source, here's the list of dependencies required: - `gtk+-3.0>=3.22.29` - - `granite>=0.5.1` + - `granite>=5.2` - `glib-2.0` - `gee-0.8` - `gobject-2.0` @@ -41,7 +41,7 @@ You can install Sequeler by compiling from source, here's the list of dependenci - `libssh2` - `meson` -## Building +## Building ``` meson build --prefix=/usr sudo -C build ninja install diff --git a/src/Application.vala b/src/Application.vala index 2de3436d..c5e78631 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -20,10 +20,10 @@ */ namespace Sequeler { - public Sequeler.Services.Settings settings; - public Sequeler.Services.PasswordManager password_mngr; - public Sequeler.Services.UpgradeManager upgrade_mngr; - public Secret.Schema schema; + public Sequeler.Services.Settings settings; + public Sequeler.Services.PasswordManager password_mngr; + public Sequeler.Services.UpgradeManager upgrade_mngr; + public Secret.Schema schema; } public class Sequeler.Application : Gtk.Application { @@ -74,11 +74,11 @@ public class Sequeler.Application : Gtk.Application { var window = this.add_new_window (); window.main.library.check_open_sqlite_file (file.get_uri (), file.get_basename ()); - break; + break; - default: - error (_("Something completely unexpected happened")); - } + default: + error (_("Something completely unexpected happened")); + } } } @@ -95,6 +95,6 @@ public class Sequeler.Application : Gtk.Application { } protected override void activate () { - this.add_new_window (); + this.add_new_window (); } } diff --git a/src/Layouts/DataBaseSchema.vala b/src/Layouts/DataBaseSchema.vala index 6972e267..35271677 100644 --- a/src/Layouts/DataBaseSchema.vala +++ b/src/Layouts/DataBaseSchema.vala @@ -20,414 +20,414 @@ */ public class Sequeler.Layouts.DataBaseSchema : Gtk.Grid { - public weak Sequeler.Window window { get; construct; } - - public Gtk.ListStore schema_list; - public Gtk.ComboBox schema_list_combo; - public Gtk.TreeIter iter; - private bool reloading { get; set; default = false;} - - public Gee.HashMap schemas; - private ulong handler_id; - - public Gtk.Stack stack; - public Gtk.ScrolledWindow scroll; - private Gda.DataModel? schema_table; - public Granite.Widgets.SourceList.ExpandableItem tables_category; - public Granite.Widgets.SourceList source_list; - - private Gtk.Grid toolbar; - private Gtk.Spinner spinner; - public Gtk.Revealer revealer; - public Gtk.SearchEntry search; - public string search_text; - - enum Column { - SCHEMAS - } - - public DataBaseSchema (Sequeler.Window main_window) { - Object ( - orientation: Gtk.Orientation.VERTICAL, - window: main_window, - column_homogeneous: true - ); - } - - construct { - var dropdown_area = new Gtk.Grid (); - dropdown_area.column_homogeneous = false; - dropdown_area.get_style_context ().add_class ("library-titlebar"); - - var cell = new Gtk.CellRendererText (); - - schema_list = new Gtk.ListStore (1, typeof (string)); - schema_list.append (out iter); - schema_list.set (iter, Column.SCHEMAS, _("- Select Database -")); - - schema_list_combo = new Gtk.ComboBox.with_model (schema_list); - schema_list_combo.hexpand = true; - schema_list_combo.pack_start (cell, false); - schema_list_combo.set_attributes (cell, "text", Column.SCHEMAS); - - schema_list_combo.set_active (0); - schema_list_combo.margin_top = 10; - schema_list_combo.margin_bottom = 10; - schema_list_combo.margin_start = 10; - schema_list_combo.sensitive = false; - - handler_id = schema_list_combo.changed.connect (() => { - if (schema_list_combo.get_active () == 0) { - return; - } - start_spinner (); - init_populate_schema.begin (null); - }); - - var search_btn = new Sequeler.Partials.HeaderBarButton ("system-search-symbolic", _("Search Tables")); - search_btn.clicked.connect (toggle_search_tables); - - dropdown_area.attach (schema_list_combo, 0, 0, 1, 1); - dropdown_area.attach (search_btn, 1, 0, 1, 1); - - revealer = new Gtk.Revealer (); - revealer.hexpand = true; - revealer.reveal_child = false; - - search = new Gtk.SearchEntry (); - search.placeholder_text = _("Search Tables\u2026"); - search.hexpand = true; - search.margin = 10; - search.search_changed.connect(on_search_tables); - search.key_press_event.connect (key => { - if (key.keyval == 65307) { - search.set_text (""); - toggle_search_tables (); - return true; - } - return false; - }); - revealer.add (search); - - scroll = new Gtk.ScrolledWindow (null, null); - scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - scroll.vexpand = true; - - toolbar = new Gtk.Grid (); - toolbar.get_style_context ().add_class ("library-toolbar"); - - var reload_btn = new Sequeler.Partials.HeaderBarButton ("view-refresh-symbolic", _("Reload Tables")); - reload_btn.clicked.connect (reload_schema); - reload_btn.hexpand = true; - reload_btn.halign = Gtk.Align.START; - - var add_table_btn = new Sequeler.Partials.HeaderBarButton ("list-add-symbolic", _("Add Table")); - add_table_btn.clicked.connect (add_table); - add_table_btn.sensitive = false; - - spinner = new Gtk.Spinner (); - spinner.hexpand = true; - spinner.vexpand = true; - spinner.halign = Gtk.Align.CENTER; - spinner.valign = Gtk.Align.CENTER; - spinner.start (); - - toolbar.attach (add_table_btn, 0, 0, 1, 1); - toolbar.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0, 1, 1); - toolbar.attach (reload_btn, 2, 0, 1, 1); - - stack = new Gtk.Stack (); - stack.hexpand = true; - stack.vexpand = true; - stack.add_named (scroll, "list"); - stack.add_named (spinner, "spinner"); - - attach (dropdown_area, 0, 0, 1, 1); - attach (revealer, 0, 1, 1, 1); - attach (stack, 0, 2, 1, 2); - attach (toolbar, 0, 4, 1, 1); - - start_spinner (); - } - - public void start_spinner () { - stack.visible_child_name = "spinner"; - } - - public void stop_spinner () { - stack.visible_child_name = "list"; - } - - private async void reset_schema_combo () { - schema_list_combo.disconnect (handler_id); - - schema_list.clear (); - schema_list.append (out iter); - schema_list.set (iter, Column.SCHEMAS, _("- Select Database -")); - schema_list_combo.set_active (0); - schema_list_combo.sensitive = false; - - handler_id = schema_list_combo.changed.connect (() => { - if (schema_list_combo.get_active () == 0) { - return; - } - start_spinner (); - init_populate_schema.begin (null); - }); - } - - public async void init_populate_schema (Gda.DataModel? schema) { - var database = window.data_manager.data["type"] == "SQLite" ? null : schemas[schema_list_combo.get_active ()]; - - yield populate_schema (database, schema); - } - - public async void reload_schema () { - if (reloading) { - debug ("still loading"); - return; - } - - Gda.DataModel? schema = null; - Gda.DataModelIter? _iter = null; - reloading = true; - - schema = yield get_schema (); - - if (schema == null) { - reloading = false; - return; - } - - yield reset_schema_combo (); - - if (window.data_manager.data["type"] == "SQLite") { - yield init_populate_schema (schema); - reloading = false; - return; - } - - _iter = schema.create_iter (); - - if (_iter == null) { - debug ("not a valid iter"); - return; - } - - schemas = new Gee.HashMap (); - int i = 1; - while (_iter.move_next ()) { - schema_list.append (out iter); - schema_list.set (iter, Column.SCHEMAS, _iter.get_value_at (0).get_string ()); - schemas.set (i,_iter.get_value_at (0).get_string ()); - i++; - } - if (window.data_manager.data["type"] != "PostgreSQL") { - schema_list_combo.sensitive = true; - } - - if (window.data_manager.data["type"] == "PostgreSQL") { - foreach (var entry in schemas.entries) { - if ("public" == entry.value) { - schema_list_combo.set_active (entry.key); - } - } - reloading = false; - return; - } - - foreach (var entry in schemas.entries) { - if (window.data_manager.data["name"] == entry.value) { - schema_list_combo.set_active (entry.key); - } - } - - reloading = false; - } - - public async Gda.DataModel? get_schema () { - Gda.DataModel? result = null; - var query = (window.main.connection_manager.db_type as DataBaseType).show_schema (); - - result = yield window.main.connection_manager.init_select_query (query); - - if (result == null) { - reloading = false; - yield reset_schema_combo (); - } - - return result; - } - - public async void populate_schema (string? database, Gda.DataModel? schema) { - yield clear_views (); - - if (database != null && window.data_manager.data["name"] != database && window.data_manager.data["type"] != "PostgreSQL") { - window.data_manager.data["name"] = database; - yield update_connection (); - return; - } - - if (database == null && window.data_manager.data["type"] == "SQLite" && schema != null) { - schema_table = schema; - } else { - yield get_schema_table (database); - } - - if (schema_table == null) { - stop_spinner (); - return; - } - - if (scroll.get_child () != null) { - scroll.remove (scroll.get_child ()); - } - - source_list = new Granite.Widgets.SourceList (); - source_list.set_filter_func (source_list_visible_func, true); - tables_category = new Granite.Widgets.SourceList.ExpandableItem (_("TABLES")); - tables_category.expand_all (); - - Gda.DataModelIter _iter = schema_table.create_iter (); - int top = 0; - int count = 0; - while (_iter.move_next ()) { - var item = new Granite.Widgets.SourceList.Item (_iter.get_value_at (0).get_string ()); - - // Get the table rows coutn with an extra query for SQLite - if (window.data_manager.data["type"] == "SQLite") { - var table_count = yield get_table_count (item.name); - Gda.DataModelIter count_iter = table_count.create_iter (); - - while (count_iter.move_next ()) { - count = count_iter.get_value_at (0).get_int (); - item.badge = count.to_string (); - } - } else { - count = (int) _iter.get_value_at (1).get_long (); - item.badge = count.to_string (); - } - - var icon_name = count == 0 ? "table-empty" : "table"; - item.editable = true; - item.icon = new GLib.ThemedIcon (icon_name); - item.edited.connect ((new_name) => { - if (new_name != item.name) { - edit_table_name.begin (item.name, new_name); - } - }); - tables_category.add (item); - top++; - } - - source_list.root.add (tables_category); - scroll.add (source_list); - - source_list.item_selected.connect (item => { - if (item == null) { - return; - } - - if (window.main.database_view.tabs.selected == 0) { - window.main.database_view.structure.fill (item.name, database); - } - - if (window.main.database_view.tabs.selected == 1) { - window.main.database_view.content.fill (item.name, database, item.badge); - } - - if (window.main.database_view.tabs.selected == 2) { - window.main.database_view.relations.fill (item.name, database); - } - }); - - window.main.database_view.structure.database = database; - window.main.database_view.content.database = database; - window.main.database_view.relations.database = database; - stop_spinner (); - } - - public async void get_schema_table (string database) { - var query = (window.main.connection_manager.db_type as DataBaseType).show_table_list (database); - - schema_table = yield window.main.connection_manager.init_select_query (query); - } - - public async Gda.DataModel? get_table_count (string table) { - var query = (window.main.connection_manager.db_type as DataBaseType).show_table_list (table); - - return yield window.main.connection_manager.init_select_query (query); - } - - private async void update_connection () { - if (window.data_manager.data["type"] == "PostgreSQL") { - return; - } - - schema_list_combo.sensitive = false; - - if (scroll.get_child () != null) { - scroll.remove (scroll.get_child ()); - } - - if (window.main.connection_manager.connection != null && window.main.connection_manager.connection.is_opened ()) { - window.main.connection_manager.connection.clear_events_list (); - window.main.connection_manager.connection.close (); - } - - var result = new Gee.HashMap (); - try { - result = yield window.main.connection_manager.init_connection (); - } catch (ThreadError e) { - window.main.connection_manager.query_warning (e.message); - } - - if (result["status"] == "true") { - reload_schema.begin (); - } else { - window.main.connection_manager.query_warning (result["msg"]); - } - } - - private async void edit_table_name (string old_name, string new_name) { - var query = (window.main.connection_manager.db_type as DataBaseType).edit_table_name (old_name, new_name); - - yield window.main.connection_manager.init_query (query); - - yield reload_schema (); - } - - public void toggle_search_tables () { - revealer.reveal_child = ! revealer.get_reveal_child (); - if (revealer.get_reveal_child ()) { - search.grab_focus_without_selecting (); - } - - search.text = ""; - } - - public void on_search_tables (Gtk.Entry searchentry) { - search_text = searchentry.get_text ().down (); - source_list.refilter (); - tables_category.expand_all (); - } - - private bool source_list_visible_func (Granite.Widgets.SourceList.Item item) { - if (search_text == null || item is Granite.Widgets.SourceList.ExpandableItem) { - return true; - } - - return item.name.down ().contains (search_text); - } + public weak Sequeler.Window window { get; construct; } + + public Gtk.ListStore schema_list; + public Gtk.ComboBox schema_list_combo; + public Gtk.TreeIter iter; + private bool reloading { get; set; default = false;} + + public Gee.HashMap schemas; + private ulong handler_id; + + public Gtk.Stack stack; + public Gtk.ScrolledWindow scroll; + private Gda.DataModel? schema_table; + public Granite.Widgets.SourceList.ExpandableItem tables_category; + public Granite.Widgets.SourceList source_list; + + private Gtk.Grid toolbar; + private Gtk.Spinner spinner; + public Gtk.Revealer revealer; + public Gtk.SearchEntry search; + public string search_text; + + enum Column { + SCHEMAS + } + + public DataBaseSchema (Sequeler.Window main_window) { + Object ( + orientation: Gtk.Orientation.VERTICAL, + window: main_window, + column_homogeneous: true + ); + } + + construct { + var dropdown_area = new Gtk.Grid (); + dropdown_area.column_homogeneous = false; + dropdown_area.get_style_context ().add_class ("library-titlebar"); + + var cell = new Gtk.CellRendererText (); + + schema_list = new Gtk.ListStore (1, typeof (string)); + schema_list.append (out iter); + schema_list.set (iter, Column.SCHEMAS, _("- Select Database -")); + + schema_list_combo = new Gtk.ComboBox.with_model (schema_list); + schema_list_combo.hexpand = true; + schema_list_combo.pack_start (cell, false); + schema_list_combo.set_attributes (cell, "text", Column.SCHEMAS); + + schema_list_combo.set_active (0); + schema_list_combo.margin_top = 10; + schema_list_combo.margin_bottom = 10; + schema_list_combo.margin_start = 10; + schema_list_combo.sensitive = false; + + handler_id = schema_list_combo.changed.connect (() => { + if (schema_list_combo.get_active () == 0) { + return; + } + start_spinner (); + init_populate_schema.begin (null); + }); + + var search_btn = new Sequeler.Partials.HeaderBarButton ("system-search-symbolic", _("Search Tables")); + search_btn.clicked.connect (toggle_search_tables); + + dropdown_area.attach (schema_list_combo, 0, 0, 1, 1); + dropdown_area.attach (search_btn, 1, 0, 1, 1); + + revealer = new Gtk.Revealer (); + revealer.hexpand = true; + revealer.reveal_child = false; + + search = new Gtk.SearchEntry (); + search.placeholder_text = _("Search Tables\u2026"); + search.hexpand = true; + search.margin = 10; + search.search_changed.connect (on_search_tables); + search.key_press_event.connect (key => { + if (key.keyval == 65307) { + search.set_text (""); + toggle_search_tables (); + return true; + } + return false; + }); + revealer.add (search); + + scroll = new Gtk.ScrolledWindow (null, null); + scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + scroll.vexpand = true; + + toolbar = new Gtk.Grid (); + toolbar.get_style_context ().add_class ("library-toolbar"); + + var reload_btn = new Sequeler.Partials.HeaderBarButton ("view-refresh-symbolic", _("Reload Tables")); + reload_btn.clicked.connect (reload_schema); + reload_btn.hexpand = true; + reload_btn.halign = Gtk.Align.START; + + var add_table_btn = new Sequeler.Partials.HeaderBarButton ("list-add-symbolic", _("Add Table")); + add_table_btn.clicked.connect (add_table); + add_table_btn.sensitive = false; + + spinner = new Gtk.Spinner (); + spinner.hexpand = true; + spinner.vexpand = true; + spinner.halign = Gtk.Align.CENTER; + spinner.valign = Gtk.Align.CENTER; + spinner.start (); + + toolbar.attach (add_table_btn, 0, 0, 1, 1); + toolbar.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0, 1, 1); + toolbar.attach (reload_btn, 2, 0, 1, 1); + + stack = new Gtk.Stack (); + stack.hexpand = true; + stack.vexpand = true; + stack.add_named (scroll, "list"); + stack.add_named (spinner, "spinner"); + + attach (dropdown_area, 0, 0, 1, 1); + attach (revealer, 0, 1, 1, 1); + attach (stack, 0, 2, 1, 2); + attach (toolbar, 0, 4, 1, 1); + + start_spinner (); + } + + public void start_spinner () { + stack.visible_child_name = "spinner"; + } + + public void stop_spinner () { + stack.visible_child_name = "list"; + } + + private async void reset_schema_combo () { + schema_list_combo.disconnect (handler_id); + + schema_list.clear (); + schema_list.append (out iter); + schema_list.set (iter, Column.SCHEMAS, _("- Select Database -")); + schema_list_combo.set_active (0); + schema_list_combo.sensitive = false; + + handler_id = schema_list_combo.changed.connect (() => { + if (schema_list_combo.get_active () == 0) { + return; + } + start_spinner (); + init_populate_schema.begin (null); + }); + } + + public async void init_populate_schema (Gda.DataModel? schema) { + var database = window.data_manager.data["type"] == "SQLite" ? null : schemas[schema_list_combo.get_active ()]; + + yield populate_schema (database, schema); + } + + public async void reload_schema () { + if (reloading) { + debug ("still loading"); + return; + } + + Gda.DataModel? schema = null; + Gda.DataModelIter? _iter = null; + reloading = true; + + schema = yield get_schema (); + + if (schema == null) { + reloading = false; + return; + } + + yield reset_schema_combo (); + + if (window.data_manager.data["type"] == "SQLite") { + yield init_populate_schema (schema); + reloading = false; + return; + } + + _iter = schema.create_iter (); + + if (_iter == null) { + debug ("not a valid iter"); + return; + } + + schemas = new Gee.HashMap (); + int i = 1; + while (_iter.move_next ()) { + schema_list.append (out iter); + schema_list.set (iter, Column.SCHEMAS, _iter.get_value_at (0).get_string ()); + schemas.set (i, _iter.get_value_at (0).get_string ()); + i++; + } + if (window.data_manager.data["type"] != "PostgreSQL") { + schema_list_combo.sensitive = true; + } + + if (window.data_manager.data["type"] == "PostgreSQL") { + foreach (var entry in schemas.entries) { + if ("public" == entry.value) { + schema_list_combo.set_active (entry.key); + } + } + reloading = false; + return; + } + + foreach (var entry in schemas.entries) { + if (window.data_manager.data["name"] == entry.value) { + schema_list_combo.set_active (entry.key); + } + } + + reloading = false; + } + + public async Gda.DataModel? get_schema () { + Gda.DataModel? result = null; + var query = (window.main.connection_manager.db_type as DataBaseType).show_schema (); + + result = yield window.main.connection_manager.init_select_query (query); + + if (result == null) { + reloading = false; + yield reset_schema_combo (); + } + + return result; + } + + public async void populate_schema (string? database, Gda.DataModel? schema) { + yield clear_views (); + + if (database != null && window.data_manager.data["name"] != database && window.data_manager.data["type"] != "PostgreSQL") { + window.data_manager.data["name"] = database; + yield update_connection (); + return; + } + + if (database == null && window.data_manager.data["type"] == "SQLite" && schema != null) { + schema_table = schema; + } else { + yield get_schema_table (database); + } + + if (schema_table == null) { + stop_spinner (); + return; + } + + if (scroll.get_child () != null) { + scroll.remove (scroll.get_child ()); + } + + source_list = new Granite.Widgets.SourceList (); + source_list.set_filter_func (source_list_visible_func, true); + tables_category = new Granite.Widgets.SourceList.ExpandableItem (_("TABLES")); + tables_category.expand_all (); + + Gda.DataModelIter _iter = schema_table.create_iter (); + int top = 0; + int count = 0; + while (_iter.move_next ()) { + var item = new Granite.Widgets.SourceList.Item (_iter.get_value_at (0).get_string ()); + + // Get the table rows coutn with an extra query for SQLite + if (window.data_manager.data["type"] == "SQLite") { + var table_count = yield get_table_count (item.name); + Gda.DataModelIter count_iter = table_count.create_iter (); + + while (count_iter.move_next ()) { + count = count_iter.get_value_at (0).get_int (); + item.badge = count.to_string (); + } + } else { + count = (int) _iter.get_value_at (1).get_long (); + item.badge = count.to_string (); + } + + var icon_name = count == 0 ? "table-empty" : "table"; + item.editable = true; + item.icon = new GLib.ThemedIcon (icon_name); + item.edited.connect ((new_name) => { + if (new_name != item.name) { + edit_table_name.begin (item.name, new_name); + } + }); + tables_category.add (item); + top++; + } + + source_list.root.add (tables_category); + scroll.add (source_list); + + source_list.item_selected.connect (item => { + if (item == null) { + return; + } + + if (window.main.database_view.tabs.selected == 0) { + window.main.database_view.structure.fill (item.name, database); + } + + if (window.main.database_view.tabs.selected == 1) { + window.main.database_view.content.fill (item.name, database, item.badge); + } + + if (window.main.database_view.tabs.selected == 2) { + window.main.database_view.relations.fill (item.name, database); + } + }); + + window.main.database_view.structure.database = database; + window.main.database_view.content.database = database; + window.main.database_view.relations.database = database; + stop_spinner (); + } + + public async void get_schema_table (string database) { + var query = (window.main.connection_manager.db_type as DataBaseType).show_table_list (database); + + schema_table = yield window.main.connection_manager.init_select_query (query); + } + + public async Gda.DataModel? get_table_count (string table) { + var query = (window.main.connection_manager.db_type as DataBaseType).show_table_list (table); + + return yield window.main.connection_manager.init_select_query (query); + } + + private async void update_connection () { + if (window.data_manager.data["type"] == "PostgreSQL") { + return; + } + + schema_list_combo.sensitive = false; + + if (scroll.get_child () != null) { + scroll.remove (scroll.get_child ()); + } + + if (window.main.connection_manager.connection != null && window.main.connection_manager.connection.is_opened ()) { + window.main.connection_manager.connection.clear_events_list (); + window.main.connection_manager.connection.close (); + } + + var result = new Gee.HashMap (); + try { + result = yield window.main.connection_manager.init_connection (); + } catch (ThreadError e) { + window.main.connection_manager.query_warning (e.message); + } + + if (result["status"] == "true") { + reload_schema.begin (); + } else { + window.main.connection_manager.query_warning (result["msg"]); + } + } + + private async void edit_table_name (string old_name, string new_name) { + var query = (window.main.connection_manager.db_type as DataBaseType).edit_table_name (old_name, new_name); + + yield window.main.connection_manager.init_query (query); + + yield reload_schema (); + } + + public void toggle_search_tables () { + revealer.reveal_child = ! revealer.get_reveal_child (); + if (revealer.get_reveal_child ()) { + search.grab_focus_without_selecting (); + } + + search.text = ""; + } + + public void on_search_tables (Gtk.Entry searchentry) { + search_text = searchentry.get_text ().down (); + source_list.refilter (); + tables_category.expand_all (); + } + + private bool source_list_visible_func (Granite.Widgets.SourceList.Item item) { + if (search_text == null || item is Granite.Widgets.SourceList.ExpandableItem) { + return true; + } + + return item.name.down ().contains (search_text); + } - private async void clear_views () { - window.main.database_view.content.reset.begin (); - window.main.database_view.relations.reset.begin (); - window.main.database_view.structure.reset.begin (); - } - - public void add_table () { + private async void clear_views () { + window.main.database_view.content.reset.begin (); + window.main.database_view.relations.reset.begin (); + window.main.database_view.structure.reset.begin (); + } + + public void add_table () { - } + } } diff --git a/src/Layouts/DataBaseView.vala b/src/Layouts/DataBaseView.vala index 4b5e7e90..bb002edc 100644 --- a/src/Layouts/DataBaseView.vala +++ b/src/Layouts/DataBaseView.vala @@ -20,200 +20,200 @@ */ public class Sequeler.Layouts.DataBaseView : Gtk.Grid { - public weak Sequeler.Window window { get; construct; } - - public Granite.Widgets.ModeButton tabs; - public Gtk.Stack stack; - public Sequeler.Layouts.Views.Structure structure; - public Sequeler.Layouts.Views.Content content; - public Sequeler.Layouts.Views.Relations relations; - public Sequeler.Layouts.Views.Query query; - - public Gtk.MenuButton font_style; - - public DataBaseView (Sequeler.Window main_window) { - Object ( - orientation: Gtk.Orientation.VERTICAL, - window: main_window, - column_homogeneous: true - ); - } - - construct { - var toolbar = new Gtk.Grid (); - toolbar.get_style_context ().add_class ("library-titlebar"); - - tabs = new Granite.Widgets.ModeButton (); - tabs.append (new Sequeler.Partials.ToolBarButton ("x-office-spreadsheet-template", "Structure", _("Structure"))); - tabs.append (new Sequeler.Partials.ToolBarButton ("x-office-document", "Content", _("Content"))); - tabs.append (new Sequeler.Partials.ToolBarButton ("preferences-system-windows", "Relations", _("Relations"))); - tabs.append (new Sequeler.Partials.ToolBarButton ("accessories-text-editor", "Query", _("Query"))); - tabs.set_active (0); - tabs.margin = 10; - tabs.margin_bottom = 9; - - tabs.mode_changed.connect ((tab) => { - stack.set_visible_child_name (tab.name); - - if (tab.name == "Query") { - font_style.visible = true; - font_style.no_show_all = false; - } else { - font_style.visible = false; - font_style.no_show_all = true; - } - - if (window.main.database_schema.source_list == null) { - return; - } - - var item_selected = window.main.database_schema.source_list.selected; - - if (item_selected == null) { - return; - } - - if (tab.name == "Structure") { - window.main.database_view.structure.fill (item_selected.name, window.main.database_view.structure.database); - } - - if (tab.name == "Content") { - window.main.database_view.content.fill (item_selected.name, window.main.database_view.content.database, item_selected.badge); - } - - if (tab.name == "Relations") { - window.main.database_view.relations.fill (item_selected.name, window.main.database_view.relations.database); - } - }); - - toolbar.attach (tabs, 0, 0, 1, 1); - - var view_options = new Gtk.Grid (); - view_options.hexpand = true; - view_options.halign = Gtk.Align.END; - view_options.valign = Gtk.Align.CENTER; - - // Query View buttons - var zoom_out_button = new Gtk.Button.from_icon_name ("zoom-out-symbolic", Gtk.IconSize.MENU); - zoom_out_button.action_name = Sequeler.Services.ActionManager.ACTION_PREFIX + Sequeler.Services.ActionManager.ACTION_ZOOM_OUT; - zoom_out_button.tooltip_markup = Granite.markup_accel_tooltip ({"minus"}, _("Zoom Out")); - - var zoom_default_button = new Gtk.Button.with_label ("100%"); - zoom_default_button.action_name = Sequeler.Services.ActionManager.ACTION_PREFIX + Sequeler.Services.ActionManager.ACTION_ZOOM_DEFAULT; - zoom_default_button.tooltip_markup = Granite.markup_accel_tooltip ({"0"}, _("Zoom 1:1")); - - var zoom_in_button = new Gtk.Button.from_icon_name ("zoom-in-symbolic", Gtk.IconSize.MENU); - zoom_in_button.action_name = Sequeler.Services.ActionManager.ACTION_PREFIX + Sequeler.Services.ActionManager.ACTION_ZOOM_IN; - zoom_in_button.tooltip_markup = Granite.markup_accel_tooltip ({"plus"}, _("Zoom In")); - - var font_size_grid = new Gtk.Grid (); - font_size_grid.column_homogeneous = true; - font_size_grid.hexpand = true; - font_size_grid.margin = 12; - font_size_grid.get_style_context ().add_class (Gtk.STYLE_CLASS_LINKED); - font_size_grid.add (zoom_out_button); - font_size_grid.add (zoom_default_button); - font_size_grid.add (zoom_in_button); - - var color_button_white = new Gtk.RadioButton (null); - color_button_white.halign = Gtk.Align.CENTER; - color_button_white.tooltip_text = _("High Contrast"); - - var color_button_white_context = color_button_white.get_style_context (); - color_button_white_context.add_class ("color-button"); - color_button_white_context.add_class ("color-white"); - - var color_button_light = new Gtk.RadioButton.from_widget (color_button_white); - color_button_light.halign = Gtk.Align.CENTER; - color_button_light.tooltip_text = _("Solarized Light"); - - var color_button_light_context = color_button_light.get_style_context (); - color_button_light_context.add_class ("color-button"); - color_button_light_context.add_class ("color-light"); - - var color_button_dark = new Gtk.RadioButton.from_widget (color_button_white); - color_button_dark.halign = Gtk.Align.CENTER; - color_button_dark.tooltip_text = _("Solarized Dark"); - - var color_button_dark_context = color_button_dark.get_style_context (); - color_button_dark_context.add_class ("color-button"); - color_button_dark_context.add_class ("color-dark"); - - var menu_grid = new Gtk.Grid (); - menu_grid.margin_bottom = 12; - menu_grid.orientation = Gtk.Orientation.VERTICAL; - menu_grid.width_request = 200; - menu_grid.attach (font_size_grid, 0, 0, 3, 1); - menu_grid.attach (color_button_white, 0, 1, 1, 1); - menu_grid.attach (color_button_light, 1, 1, 1, 1); - menu_grid.attach (color_button_dark, 2, 1, 1, 1); - menu_grid.show_all (); - - var menu = new Gtk.Popover (null); - menu.add (menu_grid); - - font_style = new Gtk.MenuButton (); - font_style.margin_end = 10; - font_style.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - font_style.set_image (new Gtk.Image.from_icon_name ("font-select-symbolic", Gtk.IconSize.LARGE_TOOLBAR)); - font_style.tooltip_text = _("Change Text Style"); - font_style.popover = menu; - font_style.can_focus = false; - font_style.visible = false; - font_style.no_show_all = true; - - view_options.add (font_style); - - // Content View buttons - // Structure View buttons - // Relations View buttons - - toolbar.attach (view_options, 1, 0, 1, 1); - - stack = new Gtk.Stack (); - structure = new Sequeler.Layouts.Views.Structure (window); - content = new Sequeler.Layouts.Views.Content (window); - relations = new Sequeler.Layouts.Views.Relations (window); - query = new Sequeler.Layouts.Views.Query (window); - - stack.add_named (structure, "Structure"); - stack.add_named (content, "Content"); - stack.add_named (relations, "Relations"); - stack.add_named (query, "Query"); - stack.expand = true; - - attach (toolbar, 0, 0, 1, 1); - attach (stack, 0, 1, 1, 1); - - settings.changed.connect (() => { - zoom_default_button.label = "%.0f%%".printf (window.action_manager.get_current_font_size () * 10); - }); - - switch (Sequeler.settings.style_scheme) { - case "high-contrast": - color_button_white.active = true; - break; - case "solarized-light": - color_button_light.active = true; - break; - case "solarized-dark": - color_button_dark.active = true; - break; - } - - color_button_dark.clicked.connect (() => { - Sequeler.settings.style_scheme = "solarized-dark"; - query.update_color_style (); - }); - - color_button_light.clicked.connect (() => { - Sequeler.settings.style_scheme = "solarized-light"; - query.update_color_style (); - }); - - color_button_white.clicked.connect (() => { - Sequeler.settings.style_scheme = "classic"; - query.update_color_style (); - }); - } + public weak Sequeler.Window window { get; construct; } + + public Granite.Widgets.ModeButton tabs; + public Gtk.Stack stack; + public Sequeler.Layouts.Views.Structure structure; + public Sequeler.Layouts.Views.Content content; + public Sequeler.Layouts.Views.Relations relations; + public Sequeler.Layouts.Views.Query query; + + public Gtk.MenuButton font_style; + + public DataBaseView (Sequeler.Window main_window) { + Object ( + orientation: Gtk.Orientation.VERTICAL, + window: main_window, + column_homogeneous: true + ); + } + + construct { + var toolbar = new Gtk.Grid (); + toolbar.get_style_context ().add_class ("library-titlebar"); + + tabs = new Granite.Widgets.ModeButton (); + tabs.append (new Sequeler.Partials.ToolBarButton ("x-office-spreadsheet-template", "Structure", _("Structure"))); + tabs.append (new Sequeler.Partials.ToolBarButton ("x-office-document", "Content", _("Content"))); + tabs.append (new Sequeler.Partials.ToolBarButton ("preferences-system-windows", "Relations", _("Relations"))); + tabs.append (new Sequeler.Partials.ToolBarButton ("accessories-text-editor", "Query", _("Query"))); + tabs.set_active (0); + tabs.margin = 10; + tabs.margin_bottom = 9; + + tabs.mode_changed.connect ((tab) => { + stack.set_visible_child_name (tab.name); + + if (tab.name == "Query") { + font_style.visible = true; + font_style.no_show_all = false; + } else { + font_style.visible = false; + font_style.no_show_all = true; + } + + if (window.main.database_schema.source_list == null) { + return; + } + + var item_selected = window.main.database_schema.source_list.selected; + + if (item_selected == null) { + return; + } + + if (tab.name == "Structure") { + window.main.database_view.structure.fill (item_selected.name, window.main.database_view.structure.database); + } + + if (tab.name == "Content") { + window.main.database_view.content.fill (item_selected.name, window.main.database_view.content.database, item_selected.badge); + } + + if (tab.name == "Relations") { + window.main.database_view.relations.fill (item_selected.name, window.main.database_view.relations.database); + } + }); + + toolbar.attach (tabs, 0, 0, 1, 1); + + var view_options = new Gtk.Grid (); + view_options.hexpand = true; + view_options.halign = Gtk.Align.END; + view_options.valign = Gtk.Align.CENTER; + + // Query View buttons + var zoom_out_button = new Gtk.Button.from_icon_name ("zoom-out-symbolic", Gtk.IconSize.MENU); + zoom_out_button.action_name = Sequeler.Services.ActionManager.ACTION_PREFIX + Sequeler.Services.ActionManager.ACTION_ZOOM_OUT; + zoom_out_button.tooltip_markup = Granite.markup_accel_tooltip ({"minus"}, _("Zoom Out")); + + var zoom_default_button = new Gtk.Button.with_label ("100%"); + zoom_default_button.action_name = Sequeler.Services.ActionManager.ACTION_PREFIX + Sequeler.Services.ActionManager.ACTION_ZOOM_DEFAULT; + zoom_default_button.tooltip_markup = Granite.markup_accel_tooltip ({"0"}, _("Zoom 1:1")); + + var zoom_in_button = new Gtk.Button.from_icon_name ("zoom-in-symbolic", Gtk.IconSize.MENU); + zoom_in_button.action_name = Sequeler.Services.ActionManager.ACTION_PREFIX + Sequeler.Services.ActionManager.ACTION_ZOOM_IN; + zoom_in_button.tooltip_markup = Granite.markup_accel_tooltip ({"plus"}, _("Zoom In")); + + var font_size_grid = new Gtk.Grid (); + font_size_grid.column_homogeneous = true; + font_size_grid.hexpand = true; + font_size_grid.margin = 12; + font_size_grid.get_style_context ().add_class (Gtk.STYLE_CLASS_LINKED); + font_size_grid.add (zoom_out_button); + font_size_grid.add (zoom_default_button); + font_size_grid.add (zoom_in_button); + + var color_button_white = new Gtk.RadioButton (null); + color_button_white.halign = Gtk.Align.CENTER; + color_button_white.tooltip_text = _("High Contrast"); + + var color_button_white_context = color_button_white.get_style_context (); + color_button_white_context.add_class ("color-button"); + color_button_white_context.add_class ("color-white"); + + var color_button_light = new Gtk.RadioButton.from_widget (color_button_white); + color_button_light.halign = Gtk.Align.CENTER; + color_button_light.tooltip_text = _("Solarized Light"); + + var color_button_light_context = color_button_light.get_style_context (); + color_button_light_context.add_class ("color-button"); + color_button_light_context.add_class ("color-light"); + + var color_button_dark = new Gtk.RadioButton.from_widget (color_button_white); + color_button_dark.halign = Gtk.Align.CENTER; + color_button_dark.tooltip_text = _("Solarized Dark"); + + var color_button_dark_context = color_button_dark.get_style_context (); + color_button_dark_context.add_class ("color-button"); + color_button_dark_context.add_class ("color-dark"); + + var menu_grid = new Gtk.Grid (); + menu_grid.margin_bottom = 12; + menu_grid.orientation = Gtk.Orientation.VERTICAL; + menu_grid.width_request = 200; + menu_grid.attach (font_size_grid, 0, 0, 3, 1); + menu_grid.attach (color_button_white, 0, 1, 1, 1); + menu_grid.attach (color_button_light, 1, 1, 1, 1); + menu_grid.attach (color_button_dark, 2, 1, 1, 1); + menu_grid.show_all (); + + var menu = new Gtk.Popover (null); + menu.add (menu_grid); + + font_style = new Gtk.MenuButton (); + font_style.margin_end = 10; + font_style.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); + font_style.set_image (new Gtk.Image.from_icon_name ("font-select-symbolic", Gtk.IconSize.LARGE_TOOLBAR)); + font_style.tooltip_text = _("Change Text Style"); + font_style.popover = menu; + font_style.can_focus = false; + font_style.visible = false; + font_style.no_show_all = true; + + view_options.add (font_style); + + // Content View buttons + // Structure View buttons + // Relations View buttons + + toolbar.attach (view_options, 1, 0, 1, 1); + + stack = new Gtk.Stack (); + structure = new Sequeler.Layouts.Views.Structure (window); + content = new Sequeler.Layouts.Views.Content (window); + relations = new Sequeler.Layouts.Views.Relations (window); + query = new Sequeler.Layouts.Views.Query (window); + + stack.add_named (structure, "Structure"); + stack.add_named (content, "Content"); + stack.add_named (relations, "Relations"); + stack.add_named (query, "Query"); + stack.expand = true; + + attach (toolbar, 0, 0, 1, 1); + attach (stack, 0, 1, 1, 1); + + settings.changed.connect (() => { + zoom_default_button.label = "%.0f%%".printf (window.action_manager.get_current_font_size () * 10); + }); + + switch (Sequeler.settings.style_scheme) { + case "high-contrast": + color_button_white.active = true; + break; + case "solarized-light": + color_button_light.active = true; + break; + case "solarized-dark": + color_button_dark.active = true; + break; + } + + color_button_dark.clicked.connect (() => { + Sequeler.settings.style_scheme = "solarized-dark"; + query.update_color_style (); + }); + + color_button_light.clicked.connect (() => { + Sequeler.settings.style_scheme = "solarized-light"; + query.update_color_style (); + }); + + color_button_white.clicked.connect (() => { + Sequeler.settings.style_scheme = "classic"; + query.update_color_style (); + }); + } } diff --git a/src/Layouts/HeaderBar.vala b/src/Layouts/HeaderBar.vala index e5052327..d3f399cf 100644 --- a/src/Layouts/HeaderBar.vala +++ b/src/Layouts/HeaderBar.vala @@ -20,102 +20,102 @@ */ public class Sequeler.Layouts.HeaderBar : Gtk.HeaderBar { - public weak Sequeler.Window window { get; construct; } - - private Gtk.Button logout_button; - private Granite.ModeSwitch mode_switch; - private Gtk.Popover menu_popover; - - public bool logged_out { get; set; } - - public HeaderBar (Sequeler.Window main_window) { - Object ( - window: main_window, - logged_out: true - ); - - set_title (APP_NAME); - set_show_close_button (true); - - build_ui (); - toggle_logout.begin (); - } - - private void build_ui () { - var eject_image = new Gtk.Image.from_icon_name ("media-eject-symbolic", Gtk.IconSize.BUTTON); - logout_button = new Gtk.Button.with_label (_("Logout")); - logout_button.get_style_context ().add_class ("back-button"); - logout_button.valign = Gtk.Align.CENTER; - logout_button.always_show_image = true; - logout_button.set_image (eject_image); - logout_button.can_focus = false; - logout_button.action_name = Sequeler.Services.ActionManager.ACTION_PREFIX + Sequeler.Services.ActionManager.ACTION_LOGOUT; - logout_button.tooltip_markup = Granite.markup_accel_tooltip ({"Escape"}, _("Logout")); - - mode_switch = new Granite.ModeSwitch.from_icon_name ("display-brightness-symbolic", "weather-clear-night-symbolic"); - mode_switch.primary_icon_tooltip_text = _("Light background"); - mode_switch.secondary_icon_tooltip_text = _("Dark background"); - mode_switch.valign = Gtk.Align.CENTER; - mode_switch.bind_property ("active", settings, "dark-theme"); - mode_switch.notify.connect (() => { - Gtk.Settings.get_default ().gtk_application_prefer_dark_theme = settings.dark_theme; - }); - - if (settings.dark_theme) { - mode_switch.active = true; - } + public weak Sequeler.Window window { get; construct; } + + private Gtk.Button logout_button; + private Granite.ModeSwitch mode_switch; + private Gtk.Popover menu_popover; + + public bool logged_out { get; set; } + + public HeaderBar (Sequeler.Window main_window) { + Object ( + window: main_window, + logged_out: true + ); + + set_title (APP_NAME); + set_show_close_button (true); + + build_ui (); + toggle_logout.begin (); + } + + private void build_ui () { + var eject_image = new Gtk.Image.from_icon_name ("media-eject-symbolic", Gtk.IconSize.BUTTON); + logout_button = new Gtk.Button.with_label (_("Logout")); + logout_button.get_style_context ().add_class ("back-button"); + logout_button.valign = Gtk.Align.CENTER; + logout_button.always_show_image = true; + logout_button.set_image (eject_image); + logout_button.can_focus = false; + logout_button.action_name = Sequeler.Services.ActionManager.ACTION_PREFIX + Sequeler.Services.ActionManager.ACTION_LOGOUT; + logout_button.tooltip_markup = Granite.markup_accel_tooltip ({"Escape"}, _("Logout")); + + mode_switch = new Granite.ModeSwitch.from_icon_name ("display-brightness-symbolic", "weather-clear-night-symbolic"); + mode_switch.primary_icon_tooltip_text = _("Light background"); + mode_switch.secondary_icon_tooltip_text = _("Dark background"); + mode_switch.valign = Gtk.Align.CENTER; + mode_switch.bind_property ("active", settings, "dark-theme"); + mode_switch.notify.connect (() => { + Gtk.Settings.get_default ().gtk_application_prefer_dark_theme = settings.dark_theme; + }); + + if (settings.dark_theme) { + mode_switch.active = true; + } var new_window_item = new_menuitem (_("New Window"), {"n"}); - new_window_item.action_name = Sequeler.Services.ActionManager.ACTION_PREFIX + Sequeler.Services.ActionManager.ACTION_NEW_WINDOW; + new_window_item.action_name = Sequeler.Services.ActionManager.ACTION_PREFIX + Sequeler.Services.ActionManager.ACTION_NEW_WINDOW; - var new_connection_item = new_menuitem (_("New Connection"), {"n"}); - new_connection_item.action_name = Sequeler.Services.ActionManager.ACTION_PREFIX + Sequeler.Services.ActionManager.ACTION_NEW_CONNECTION; + var new_connection_item = new_menuitem (_("New Connection"), {"n"}); + new_connection_item.action_name = Sequeler.Services.ActionManager.ACTION_PREFIX + Sequeler.Services.ActionManager.ACTION_NEW_CONNECTION; - var quit_item = new_menuitem (_("Quit"), {"q"}); - quit_item.action_name = Sequeler.Services.ActionManager.ACTION_PREFIX + Sequeler.Services.ActionManager.ACTION_QUIT; + var quit_item = new_menuitem (_("Quit"), {"q"}); + quit_item.action_name = Sequeler.Services.ActionManager.ACTION_PREFIX + Sequeler.Services.ActionManager.ACTION_QUIT; - var menu_separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); - menu_separator.margin_top = 6; - menu_separator.margin_bottom = 6; + var menu_separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); + menu_separator.margin_top = 6; + menu_separator.margin_bottom = 6; - var menu_grid = new Gtk.Grid (); - menu_grid.expand = true; - menu_grid.margin_top = menu_grid.margin_bottom = 6; - menu_grid.orientation = Gtk.Orientation.VERTICAL; + var menu_grid = new Gtk.Grid (); + menu_grid.expand = true; + menu_grid.margin_top = menu_grid.margin_bottom = 6; + menu_grid.orientation = Gtk.Orientation.VERTICAL; - menu_grid.attach (new_window_item, 0, 1, 1, 1); - menu_grid.attach (new_connection_item, 0, 2, 1, 1); - menu_grid.attach (menu_separator, 0, 3, 1, 1); - menu_grid.attach (quit_item, 0, 4, 1, 1); - menu_grid.show_all (); + menu_grid.attach (new_window_item, 0, 1, 1, 1); + menu_grid.attach (new_connection_item, 0, 2, 1, 1); + menu_grid.attach (menu_separator, 0, 3, 1, 1); + menu_grid.attach (quit_item, 0, 4, 1, 1); + menu_grid.show_all (); - var open_menu = new Gtk.MenuButton (); - open_menu.set_image (new Gtk.Image.from_icon_name ("open-menu", Gtk.IconSize.LARGE_TOOLBAR)); - open_menu.tooltip_text = _("Menu"); + var open_menu = new Gtk.MenuButton (); + open_menu.set_image (new Gtk.Image.from_icon_name ("open-menu", Gtk.IconSize.LARGE_TOOLBAR)); + open_menu.tooltip_text = _("Menu"); - menu_popover = new Gtk.Popover (open_menu); - menu_popover.add (menu_grid); + menu_popover = new Gtk.Popover (open_menu); + menu_popover.add (menu_grid); - open_menu.popover = menu_popover; - open_menu.valign = Gtk.Align.CENTER; + open_menu.popover = menu_popover; + open_menu.valign = Gtk.Align.CENTER; - pack_start (logout_button); - pack_end (open_menu); + pack_start (logout_button); + pack_end (open_menu); - var separator = new Gtk.Separator (Gtk.Orientation.VERTICAL); - separator.get_style_context ().add_class ("headerbar-separator"); + var separator = new Gtk.Separator (Gtk.Orientation.VERTICAL); + separator.get_style_context ().add_class ("headerbar-separator"); - pack_end (separator); - pack_end (mode_switch); - } + pack_end (separator); + pack_end (mode_switch); + } - private Gtk.Button new_menuitem (string label, string[] accels) { - var item_label = new Gtk.Label (label); + private Gtk.Button new_menuitem (string label, string[] accels) { + var item_label = new Gtk.Label (label); item_label.halign = Gtk.Align.START; item_label.hexpand = true; - item_label.margin_start = 6; + item_label.margin_start = 6; - var item_accel_label = new Gtk.Label (Granite.markup_accel_tooltip (accels)); + var item_accel_label = new Gtk.Label (Granite.markup_accel_tooltip (accels)); item_accel_label.halign = Gtk.Align.END; item_accel_label.margin_end = item_accel_label.margin_start = 6; item_accel_label.use_markup = true; @@ -126,19 +126,19 @@ public class Sequeler.Layouts.HeaderBar : Gtk.HeaderBar { var item = new Gtk.Button (); item.add (item_grid); - item.get_style_context ().add_class (Gtk.STYLE_CLASS_MENUITEM); - item.clicked.connect (() => { - menu_popover.hide (); - }); + item.get_style_context ().add_class (Gtk.STYLE_CLASS_MENUITEM); + item.clicked.connect (() => { + menu_popover.hide (); + }); - return item; - } + return item; + } - public async void toggle_logout () { - logged_out = !logged_out; - logout_button.visible = logged_out; - logout_button.no_show_all = !logged_out; + public async void toggle_logout () { + logged_out = !logged_out; + logout_button.visible = logged_out; + logout_button.no_show_all = !logged_out; - yield; - } + yield; + } } diff --git a/src/Layouts/Library.vala b/src/Layouts/Library.vala index d1336a2b..e4b8d243 100644 --- a/src/Layouts/Library.vala +++ b/src/Layouts/Library.vala @@ -20,155 +20,155 @@ */ public class Sequeler.Layouts.Library : Gtk.Grid { - public weak Sequeler.Window window { get; construct; } - - GLib.File? file; - Gtk.TextBuffer buffer; - - private Gtk.Grid title; - private Gtk.Revealer motion_revealer; - public Gtk.ListBox item_box; - public Gtk.ScrolledWindow scroll; - public Sequeler.Partials.HeaderBarButton delete_all; - - public Gee.HashMap real_data; - public Gtk.Spinner real_spinner; - public Gtk.ModelButton real_button; - public Sequeler.Services.ConnectionManager connection_manager; - - public signal void edit_dialog (Gee.HashMap data); - - // Datatype restrictions on DnD (Gtk.TargetFlags). - public const Gtk.TargetEntry[] TARGET_ENTRIES_LABEL = { - { "LIBRARYITEM", Gtk.TargetFlags.SAME_APP, 0 } - }; - - public Library (Sequeler.Window main_window) { - Object( - orientation: Gtk.Orientation.VERTICAL, - window: main_window, - width_request: 260, - column_homogeneous: true - ); - } - - construct { - var motion_grid = new Gtk.Grid (); + public weak Sequeler.Window window { get; construct; } + + GLib.File? file; + Gtk.TextBuffer buffer; + + private Gtk.Grid title; + private Gtk.Revealer motion_revealer; + public Gtk.ListBox item_box; + public Gtk.ScrolledWindow scroll; + public Sequeler.Partials.HeaderBarButton delete_all; + + public Gee.HashMap real_data; + public Gtk.Spinner real_spinner; + public Gtk.ModelButton real_button; + public Sequeler.Services.ConnectionManager connection_manager; + + public signal void edit_dialog (Gee.HashMap data); + + // Datatype restrictions on DnD (Gtk.TargetFlags). + public const Gtk.TargetEntry[] TARGET_ENTRIES_LABEL = { + { "LIBRARYITEM", Gtk.TargetFlags.SAME_APP, 0 } + }; + + public Library (Sequeler.Window main_window) { + Object ( + orientation: Gtk.Orientation.VERTICAL, + window: main_window, + width_request: 260, + column_homogeneous: true + ); + } + + construct { + var motion_grid = new Gtk.Grid (); motion_grid.margin = 6; motion_grid.get_style_context ().add_class ("grid-motion"); motion_grid.height_request = 18; motion_revealer = new Gtk.Revealer (); motion_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN; - motion_revealer.add (motion_grid); - - var titlebar = new Sequeler.Partials.TitleBar (_("SAVED CONNECTIONS")); - - title = new Gtk.Grid (); - title.attach (titlebar, 0, 0); - title.attach (motion_revealer, 0, 1); - - var toolbar = new Gtk.Grid (); - toolbar.get_style_context ().add_class ("library-toolbar"); - - delete_all = new Sequeler.Partials.HeaderBarButton ("user-trash-symbolic", _("Delete All")); - delete_all.halign = Gtk.Align.END; - delete_all.hexpand = true; - delete_all.clicked.connect (() => { - confirm_delete_all (); - }); - - var reload_btn = new Sequeler.Partials.HeaderBarButton ("view-refresh-symbolic", _("Reload Library")); - reload_btn.clicked.connect (() => reload_library.begin ()); - - var export_btn = new Sequeler.Partials.HeaderBarButton ("document-save-symbolic", _("Export Library")); - export_btn.clicked.connect (export_library); - - toolbar.attach (reload_btn, 0, 0, 1, 1); - toolbar.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0, 1, 1); - toolbar.attach (export_btn, 2, 0, 1, 1); - toolbar.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 3, 0, 1, 1); - toolbar.attach (delete_all, 4, 0, 1, 1); - - scroll = new Gtk.ScrolledWindow (null, null); - scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - - item_box = new Gtk.ListBox (); - item_box.get_style_context ().add_class ("library-box"); - item_box.set_activate_on_single_click (false); - item_box.selection_mode = Gtk.SelectionMode.SINGLE; - item_box.valign = Gtk.Align.FILL; - item_box.expand = true; - - scroll.add (item_box); - - foreach (var conn in settings.saved_connections) { - add_item (settings.arraify_data (conn)); - } - - if (settings.saved_connections.length > 0) { - delete_all.sensitive = true; - } - - item_box.row_activated.connect ((row) => { - var item = row as Sequeler.Partials.LibraryItem; - item.spinner.start (); - item.connect_button.sensitive = false; - window.data_manager.data = item.data; - init_connection_begin (item.data, item.spinner, item.connect_button, false); - }); - - attach (title, 0, 0, 1, 1); - scroll.expand = true; - attach (scroll, 0, 1, 1, 2); - attach (toolbar, 0, 3, 1, 1); - - build_drag_and_drop (); - } - - private void build_drag_and_drop () { - Gtk.drag_dest_set (item_box, Gtk.DestDefaults.ALL, TARGET_ENTRIES_LABEL, Gdk.DragAction.MOVE); + motion_revealer.add (motion_grid); + + var titlebar = new Sequeler.Partials.TitleBar (_("SAVED CONNECTIONS")); + + title = new Gtk.Grid (); + title.attach (titlebar, 0, 0); + title.attach (motion_revealer, 0, 1); + + var toolbar = new Gtk.Grid (); + toolbar.get_style_context ().add_class ("library-toolbar"); + + delete_all = new Sequeler.Partials.HeaderBarButton ("user-trash-symbolic", _("Delete All")); + delete_all.halign = Gtk.Align.END; + delete_all.hexpand = true; + delete_all.clicked.connect (() => { + confirm_delete_all (); + }); + + var reload_btn = new Sequeler.Partials.HeaderBarButton ("view-refresh-symbolic", _("Reload Library")); + reload_btn.clicked.connect (() => reload_library.begin ()); + + var export_btn = new Sequeler.Partials.HeaderBarButton ("document-save-symbolic", _("Export Library")); + export_btn.clicked.connect (export_library); + + toolbar.attach (reload_btn, 0, 0, 1, 1); + toolbar.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0, 1, 1); + toolbar.attach (export_btn, 2, 0, 1, 1); + toolbar.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 3, 0, 1, 1); + toolbar.attach (delete_all, 4, 0, 1, 1); + + scroll = new Gtk.ScrolledWindow (null, null); + scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + + item_box = new Gtk.ListBox (); + item_box.get_style_context ().add_class ("library-box"); + item_box.set_activate_on_single_click (false); + item_box.selection_mode = Gtk.SelectionMode.SINGLE; + item_box.valign = Gtk.Align.FILL; + item_box.expand = true; + + scroll.add (item_box); + + foreach (var conn in settings.saved_connections) { + add_item (settings.arraify_data (conn)); + } + + if (settings.saved_connections.length > 0) { + delete_all.sensitive = true; + } + + item_box.row_activated.connect ((row) => { + var item = row as Sequeler.Partials.LibraryItem; + item.spinner.start (); + item.connect_button.sensitive = false; + window.data_manager.data = item.data; + init_connection_begin (item.data, item.spinner, item.connect_button, false); + }); + + attach (title, 0, 0, 1, 1); + scroll.expand = true; + attach (scroll, 0, 1, 1, 2); + attach (toolbar, 0, 3, 1, 1); + + build_drag_and_drop (); + } + + private void build_drag_and_drop () { + Gtk.drag_dest_set (item_box, Gtk.DestDefaults.ALL, TARGET_ENTRIES_LABEL, Gdk.DragAction.MOVE); item_box.drag_data_received.connect (on_drag_data_received); - Gtk.drag_dest_set (title, Gtk.DestDefaults.ALL, TARGET_ENTRIES_LABEL, Gdk.DragAction.MOVE); + Gtk.drag_dest_set (title, Gtk.DestDefaults.ALL, TARGET_ENTRIES_LABEL, Gdk.DragAction.MOVE); title.drag_data_received.connect (on_drag_item_received); title.drag_motion.connect (on_drag_motion); title.drag_leave.connect (on_drag_leave); - } + } - private void on_drag_data_received (Gdk.DragContext context, int x, int y, + private void on_drag_data_received (Gdk.DragContext context, int x, int y, Gtk.SelectionData selection_data, uint target_type, uint time) { int new_pos; - var target = (Partials.LibraryItem) item_box.get_row_at_y (y); + var target = (Partials.LibraryItem) item_box.get_row_at_y (y); - var row = ((Gtk.Widget[]) selection_data.get_data ())[0]; - var source = (Partials.LibraryItem) row; + var row = ((Gtk.Widget[]) selection_data.get_data ())[0]; + var source = (Partials.LibraryItem) row; - int last_index = (int) item_box.get_children ().length (); + int last_index = (int) item_box.get_children ().length (); - if (target == null) { - new_pos = last_index - 1; - } else { - new_pos = source.get_index () < target.get_index () - ? target.get_index () - : target.get_index () + 1; - } + if (target == null) { + new_pos = last_index - 1; + } else { + new_pos = source.get_index () < target.get_index () + ? target.get_index () + : target.get_index () + 1; + } - settings.reorder_connection (source.data, new_pos); - reload_library.begin (); - } + settings.reorder_connection (source.data, new_pos); + reload_library.begin (); + } - private void on_drag_item_received (Gdk.DragContext context, int x, int y, + private void on_drag_item_received (Gdk.DragContext context, int x, int y, Gtk.SelectionData selection_data, uint target_type, uint time) { var row = ((Gtk.Widget[]) selection_data.get_data ())[0]; var source = (Partials.LibraryItem) row; settings.reorder_connection (source.data, 0); - reload_library.begin (); + reload_library.begin (); } - public bool on_drag_motion (Gdk.DragContext context, int x, int y, uint time) { + public bool on_drag_motion (Gdk.DragContext context, int x, int y, uint time) { motion_revealer.reveal_child = true; return true; } @@ -177,306 +177,306 @@ public class Sequeler.Layouts.Library : Gtk.Grid { motion_revealer.reveal_child = false; } - public void add_item (Gee.HashMap data) { - var item = new Sequeler.Partials.LibraryItem (data); - item.scrolled = scroll; - item_box.add (item); - - item.confirm_delete.connect ((item, data) => { - confirm_delete (item, data); - }); - - item.edit_dialog.connect ((data) => { - window.data_manager.data = data; - - if (window.connection_dialog == null) { - window.connection_dialog = new Sequeler.Widgets.ConnectionDialog (window); - window.connection_dialog.show_all (); - - window.connection_dialog.destroy.connect (() => { - window.connection_dialog = null; - }); - } - - window.connection_dialog.present (); - }); - - item.connect_to.connect ((data, spinner, connect_button) => { - window.data_manager.data = data; - init_connection_begin (data, spinner, connect_button); - }); - } - - public void confirm_delete (Gtk.ListBoxRow item, Gee.HashMap data) { - var message_dialog = new Granite.MessageDialog.with_image_from_icon_name (_("Are you sure you want to proceed?"), _("By deleting this connection you won’t be able to recover this data."), "dialog-warning", Gtk.ButtonsType.CANCEL); - message_dialog.transient_for = window; - - var suggested_button = new Gtk.Button.with_label (_("Yes, Delete!")); - suggested_button.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); - message_dialog.add_action_widget (suggested_button, Gtk.ResponseType.ACCEPT); - - message_dialog.show_all (); - if (message_dialog.run () == Gtk.ResponseType.ACCEPT) { - settings.delete_connection (data); - item_box.remove (item); - reload_library.begin (); - } - - message_dialog.destroy (); - } - - public void confirm_delete_all () { - var message_dialog = new Granite.MessageDialog.with_image_from_icon_name (_("Are you sure you want to proceed?"), _("All the data will be deleted and you won’t be able to recover it."), "dialog-warning", Gtk.ButtonsType.CANCEL); - message_dialog.transient_for = window; - - var suggested_button = new Gtk.Button.with_label (_("Yes, Delete All!")); - suggested_button.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); - message_dialog.add_action_widget (suggested_button, Gtk.ResponseType.ACCEPT); - - message_dialog.show_all (); - if (message_dialog.run () == Gtk.ResponseType.ACCEPT) { - settings.clear_connections (); - item_box.forall ((item) => item_box.remove (item)); - reload_library.begin (); - } - - message_dialog.destroy (); - } - - public async void reload_library () { - item_box.@foreach ((item) => item_box.remove (item)); - - foreach (var new_conn in settings.saved_connections) { - var array = settings.arraify_data (new_conn); - add_item (array); - } - item_box.show_all (); - - delete_all.sensitive = (settings.saved_connections.length > 0); - } - - public async void check_add_item (Gee.HashMap data) { - new Thread ("check-add-item", () => { - foreach (var conn in settings.saved_connections) { - var check = settings.arraify_data (conn); - if (check["id"] == data["id"]) { - settings.edit_connection (data, conn); - - Idle.add (() => { - reload_library.begin (); - return false; - }); - return null; - } - } - - settings.add_connection (data); - add_item (data); - - Idle.add (() => { - reload_library.begin (); - return false; - }); - - return null; - }); - - yield; - } - - public void check_open_sqlite_file (string path, string name) { - foreach (var conn in settings.saved_connections) { - var check = settings.arraify_data (conn); - if (check["file_path"] == path) { - settings.edit_connection (check, conn); - reload_library.begin ((obj, res) => { - item_box.get_row_at_index (0).activate (); - }); - return; - } - } - - var data = new Gee.HashMap (); - - data.set ("id", settings.tot_connections.to_string ()); - data.set ("title", name); - data.set ("color", "rgb(222,222,222)"); - data.set ("type", "SQLite"); - data.set ("host", ""); - data.set ("name", ""); - data.set ("file_path", path); - data.set ("username", ""); - data.set ("password", ""); - data.set ("port", ""); - - settings.add_connection (data); - add_item (data); - - reload_library.begin ((obj, res) => { - item_box.get_row_at_index (0).activate (); - }); - } - - private void init_connection_begin (Gee.HashMap data, Gtk.Spinner spinner, Gtk.ModelButton button, bool update = true) { - connection_manager = new Sequeler.Services.ConnectionManager (window, data); - - if (data["has_ssh"] == "true") { - real_data = data; - real_spinner = spinner; - real_button = button; - connection_manager.ssh_tunnel_ready.connect (() => - init_real_connection_begin (real_data, real_spinner, real_button, update) - ); - - new Thread (null, () => { - var result = new Gee.HashMap (); - try { - connection_manager.ssh_tunnel_init (true); - } catch (Error e) { - result["status"] = "false"; - result["message"] = e.message; - } - - Idle.add (() => { - if (result["status"] == "false") { - spinner.stop (); - button.sensitive = true; - connection_warning (result["message"], data["name"]); - } - return false; - }); - - return null; - }); - } else { - init_real_connection_begin (data, spinner, button, update); - } - } - - private void init_real_connection_begin (Gee.HashMap data, Gtk.Spinner spinner, Gtk.ModelButton button, bool update) { - var result = new Gee.HashMap (); - - connection_manager.init_connection.begin ((obj, res) => { - new Thread (null, () => { - try { - result = connection_manager.init_connection.end (res); - } catch (ThreadError e) { - connection_warning (e.message, data["name"]); - spinner.stop (); - button.sensitive = true; - } - - Idle.add (() => { - spinner.stop (); - button.sensitive = true; - - if (result["status"] == "true") { - if (settings.save_quick && update) { - window.main.library.check_add_item.begin (data); - } - - window.main.connection_opened.begin (connection_manager); - } else { - connection_warning (result["msg"], data["name"]); - } - return false; - }); - return null; - }); - }); - } - - private void export_library () { - file = null; - buffer = new Gtk.TextBuffer (null); - - var save_dialog = new Gtk.FileChooserNative (_("Pick a file"), - window, - Gtk.FileChooserAction.SAVE, - _("_Save"), - _("_Cancel")); - - save_dialog.do_overwrite_confirmation = true; - save_dialog.modal = true; - save_dialog.response.connect ((dialog, response_id) => { - switch (response_id) { - case Gtk.ResponseType.ACCEPT: - file = save_dialog.get_file (); - save_to_file.begin (); - break; - default: - break; - } - dialog.destroy (); - }); - - save_dialog.run (); - } - - private async void save_to_file () { - var buffer_content = ""; - var library = settings.saved_connections; - - foreach (var lib in library) { - var array = settings.arraify_data (lib); - - try { - array["password"] = yield password_mngr.get_password_async (array["id"]); - debug ("PSWD: " + array["password"]); - } catch (Error e) { - debug ("Unable to get the password from libsecret"); - } - - if (array["has_ssh"] == "true") { - try { - array["ssh_password"] = yield password_mngr.get_password_async (array["id"] + "9999"); - debug ("SSH: " + array["ssh_password"]); - } catch { - debug ("Unable to get the SSH password from libsecret"); - } - } - - buffer_content += settings.stringify_data (array) + "---\n"; - } - - buffer.set_text (buffer_content); - - Gtk.TextIter start; - Gtk.TextIter end; - - buffer.get_bounds (out start, out end); - string current_contents = buffer.get_text (start, end, false); - try { - file.replace_contents (current_contents.data, null, false, GLib.FileCreateFlags.NONE, null, null); - } - catch (GLib.Error err) { - export_warning (err.message); - } - } - - private void connection_warning (string message, string title) { - var message_dialog = new Granite.MessageDialog.with_image_from_icon_name (_("Unable to Connect to %s").printf (title), message, "dialog-error", Gtk.ButtonsType.NONE); - message_dialog.transient_for = window; - - var suggested_button = new Gtk.Button.with_label ("Close"); - message_dialog.add_action_widget (suggested_button, Gtk.ResponseType.ACCEPT); - - message_dialog.show_all (); - if (message_dialog.run () == Gtk.ResponseType.ACCEPT) {} - - message_dialog.destroy (); - } - - private void export_warning (string message) { - var message_dialog = new Granite.MessageDialog.with_image_from_icon_name (_("Unable to Export Library "), message, "dialog-error", Gtk.ButtonsType.NONE); - message_dialog.transient_for = window; - - var suggested_button = new Gtk.Button.with_label ("Close"); - message_dialog.add_action_widget (suggested_button, Gtk.ResponseType.ACCEPT); - - message_dialog.show_all (); - if (message_dialog.run () == Gtk.ResponseType.ACCEPT) {} - - message_dialog.destroy (); - } + public void add_item (Gee.HashMap data) { + var item = new Sequeler.Partials.LibraryItem (data); + item.scrolled = scroll; + item_box.add (item); + + item.confirm_delete.connect ((item, data) => { + confirm_delete (item, data); + }); + + item.edit_dialog.connect ((data) => { + window.data_manager.data = data; + + if (window.connection_dialog == null) { + window.connection_dialog = new Sequeler.Widgets.ConnectionDialog (window); + window.connection_dialog.show_all (); + + window.connection_dialog.destroy.connect (() => { + window.connection_dialog = null; + }); + } + + window.connection_dialog.present (); + }); + + item.connect_to.connect ((data, spinner, connect_button) => { + window.data_manager.data = data; + init_connection_begin (data, spinner, connect_button); + }); + } + + public void confirm_delete (Gtk.ListBoxRow item, Gee.HashMap data) { + var message_dialog = new Granite.MessageDialog.with_image_from_icon_name (_("Are you sure you want to proceed?"), _("By deleting this connection you won’t be able to recover this data."), "dialog-warning", Gtk.ButtonsType.CANCEL); + message_dialog.transient_for = window; + + var suggested_button = new Gtk.Button.with_label (_("Yes, Delete!")); + suggested_button.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); + message_dialog.add_action_widget (suggested_button, Gtk.ResponseType.ACCEPT); + + message_dialog.show_all (); + if (message_dialog.run () == Gtk.ResponseType.ACCEPT) { + settings.delete_connection (data); + item_box.remove (item); + reload_library.begin (); + } + + message_dialog.destroy (); + } + + public void confirm_delete_all () { + var message_dialog = new Granite.MessageDialog.with_image_from_icon_name (_("Are you sure you want to proceed?"), _("All the data will be deleted and you won’t be able to recover it."), "dialog-warning", Gtk.ButtonsType.CANCEL); + message_dialog.transient_for = window; + + var suggested_button = new Gtk.Button.with_label (_("Yes, Delete All!")); + suggested_button.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); + message_dialog.add_action_widget (suggested_button, Gtk.ResponseType.ACCEPT); + + message_dialog.show_all (); + if (message_dialog.run () == Gtk.ResponseType.ACCEPT) { + settings.clear_connections (); + item_box.forall ((item) => item_box.remove (item)); + reload_library.begin (); + } + + message_dialog.destroy (); + } + + public async void reload_library () { + item_box.@foreach ((item) => item_box.remove (item)); + + foreach (var new_conn in settings.saved_connections) { + var array = settings.arraify_data (new_conn); + add_item (array); + } + item_box.show_all (); + + delete_all.sensitive = (settings.saved_connections.length > 0); + } + + public async void check_add_item (Gee.HashMap data) { + new Thread ("check-add-item", () => { + foreach (var conn in settings.saved_connections) { + var check = settings.arraify_data (conn); + if (check["id"] == data["id"]) { + settings.edit_connection (data, conn); + + Idle.add (() => { + reload_library.begin (); + return false; + }); + return null; + } + } + + settings.add_connection (data); + add_item (data); + + Idle.add (() => { + reload_library.begin (); + return false; + }); + + return null; + }); + + yield; + } + + public void check_open_sqlite_file (string path, string name) { + foreach (var conn in settings.saved_connections) { + var check = settings.arraify_data (conn); + if (check["file_path"] == path) { + settings.edit_connection (check, conn); + reload_library.begin ((obj, res) => { + item_box.get_row_at_index (0).activate (); + }); + return; + } + } + + var data = new Gee.HashMap (); + + data.set ("id", settings.tot_connections.to_string ()); + data.set ("title", name); + data.set ("color", "rgb(222,222,222)"); + data.set ("type", "SQLite"); + data.set ("host", ""); + data.set ("name", ""); + data.set ("file_path", path); + data.set ("username", ""); + data.set ("password", ""); + data.set ("port", ""); + + settings.add_connection (data); + add_item (data); + + reload_library.begin ((obj, res) => { + item_box.get_row_at_index (0).activate (); + }); + } + + private void init_connection_begin (Gee.HashMap data, Gtk.Spinner spinner, Gtk.ModelButton button, bool update = true) { + connection_manager = new Sequeler.Services.ConnectionManager (window, data); + + if (data["has_ssh"] == "true") { + real_data = data; + real_spinner = spinner; + real_button = button; + connection_manager.ssh_tunnel_ready.connect (() => + init_real_connection_begin (real_data, real_spinner, real_button, update) + ); + + new Thread (null, () => { + var result = new Gee.HashMap (); + try { + connection_manager.ssh_tunnel_init (true); + } catch (Error e) { + result["status"] = "false"; + result["message"] = e.message; + } + + Idle.add (() => { + if (result["status"] == "false") { + spinner.stop (); + button.sensitive = true; + connection_warning (result["message"], data["name"]); + } + return false; + }); + + return null; + }); + } else { + init_real_connection_begin (data, spinner, button, update); + } + } + + private void init_real_connection_begin (Gee.HashMap data, Gtk.Spinner spinner, Gtk.ModelButton button, bool update) { + var result = new Gee.HashMap (); + + connection_manager.init_connection.begin ((obj, res) => { + new Thread (null, () => { + try { + result = connection_manager.init_connection.end (res); + } catch (ThreadError e) { + connection_warning (e.message, data["name"]); + spinner.stop (); + button.sensitive = true; + } + + Idle.add (() => { + spinner.stop (); + button.sensitive = true; + + if (result["status"] == "true") { + if (settings.save_quick && update) { + window.main.library.check_add_item.begin (data); + } + + window.main.connection_opened.begin (connection_manager); + } else { + connection_warning (result["msg"], data["name"]); + } + return false; + }); + return null; + }); + }); + } + + private void export_library () { + file = null; + buffer = new Gtk.TextBuffer (null); + + var save_dialog = new Gtk.FileChooserNative (_("Pick a file"), + window, + Gtk.FileChooserAction.SAVE, + _("_Save"), + _("_Cancel")); + + save_dialog.do_overwrite_confirmation = true; + save_dialog.modal = true; + save_dialog.response.connect ((dialog, response_id) => { + switch (response_id) { + case Gtk.ResponseType.ACCEPT: + file = save_dialog.get_file (); + save_to_file.begin (); + break; + default: + break; + } + dialog.destroy (); + }); + + save_dialog.run (); + } + + private async void save_to_file () { + var buffer_content = ""; + var library = settings.saved_connections; + + foreach (var lib in library) { + var array = settings.arraify_data (lib); + + try { + array["password"] = yield password_mngr.get_password_async (array["id"]); + debug ("PSWD: " + array["password"]); + } catch (Error e) { + debug ("Unable to get the password from libsecret"); + } + + if (array["has_ssh"] == "true") { + try { + array["ssh_password"] = yield password_mngr.get_password_async (array["id"] + "9999"); + debug ("SSH: " + array["ssh_password"]); + } catch { + debug ("Unable to get the SSH password from libsecret"); + } + } + + buffer_content += settings.stringify_data (array) + "---\n"; + } + + buffer.set_text (buffer_content); + + Gtk.TextIter start; + Gtk.TextIter end; + + buffer.get_bounds (out start, out end); + string current_contents = buffer.get_text (start, end, false); + try { + file.replace_contents (current_contents.data, null, false, GLib.FileCreateFlags.NONE, null, null); + } + catch (GLib.Error err) { + export_warning (err.message); + } + } + + private void connection_warning (string message, string title) { + var message_dialog = new Granite.MessageDialog.with_image_from_icon_name (_("Unable to Connect to %s").printf (title), message, "dialog-error", Gtk.ButtonsType.NONE); + message_dialog.transient_for = window; + + var suggested_button = new Gtk.Button.with_label ("Close"); + message_dialog.add_action_widget (suggested_button, Gtk.ResponseType.ACCEPT); + + message_dialog.show_all (); + if (message_dialog.run () == Gtk.ResponseType.ACCEPT) {} + + message_dialog.destroy (); + } + + private void export_warning (string message) { + var message_dialog = new Granite.MessageDialog.with_image_from_icon_name (_("Unable to Export Library "), message, "dialog-error", Gtk.ButtonsType.NONE); + message_dialog.transient_for = window; + + var suggested_button = new Gtk.Button.with_label ("Close"); + message_dialog.add_action_widget (suggested_button, Gtk.ResponseType.ACCEPT); + + message_dialog.show_all (); + if (message_dialog.run () == Gtk.ResponseType.ACCEPT) {} + + message_dialog.destroy (); + } } diff --git a/src/Layouts/Main.vala b/src/Layouts/Main.vala index ffdb8826..b9ad98e3 100644 --- a/src/Layouts/Main.vala +++ b/src/Layouts/Main.vala @@ -20,80 +20,80 @@ */ public class Sequeler.Layouts.Main : Gtk.Paned { - public weak Sequeler.Window window { get; construct; } - public Sequeler.Services.ConnectionManager? connection_manager { get; set; default = null; } - - public Sequeler.Layouts.Library library; - public Sequeler.Layouts.DataBaseSchema database_schema; - public Sequeler.Layouts.Welcome welcome; - public Sequeler.Layouts.DataBaseView database_view; - - public Gtk.Stack sidebar_stack; - public Gtk.Stack main_stack; - - public Main (Sequeler.Window main_window) { - Object ( - orientation: Gtk.Orientation.HORIZONTAL, - window: main_window - ); - } - - construct { - position = settings.sidebar_width; - - sidebar_stack = new Gtk.Stack (); - library = new Sequeler.Layouts.Library (window); - database_schema = new Sequeler.Layouts.DataBaseSchema (window); - sidebar_stack.add_named (library, "library"); - sidebar_stack.add_named (database_schema, "database_schema"); - - main_stack = new Gtk.Stack (); - welcome = new Sequeler.Layouts.Welcome (window); - database_view = new Sequeler.Layouts.DataBaseView (window); - main_stack.add_named (welcome, "welcome"); - main_stack.add_named (database_view, "database_view"); - - build_sidebar (); - build_main (); - } - - public void build_sidebar () { - pack1 (sidebar_stack, false, false); - } - - public void build_main () { - pack2 (main_stack, true, false); - } - - public async void connection_opened (Sequeler.Services.ConnectionManager? cnn_manager) { - debug ("connection opened"); - connection_manager = cnn_manager; - var host = cnn_manager.data["host"] != "" ? cnn_manager.data["host"] : "127.0.0.1"; - - window.headerbar.toggle_logout.begin (); - sidebar_stack.set_visible_child_full ("database_schema", Gtk.StackTransitionType.CROSSFADE); - main_stack.set_visible_child_full ("database_view", Gtk.StackTransitionType.SLIDE_LEFT); - - window.headerbar.title = _("Connected to %s").printf (cnn_manager.data["title"]); - window.headerbar.subtitle = cnn_manager.data["username"] + "@" + host; - - database_schema.reload_schema.begin (); - } - - public void connection_closed () { - if (connection_manager.data["has_ssh"] == "true") { - debug ("connection manager %p", connection_manager); - connection_manager.ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - } - - if (connection_manager.connection != null && connection_manager.connection.is_opened ()) { - connection_manager.connection.clear_events_list (); - connection_manager.connection.close (); - connection_manager.connection = null; - } - - connection_manager = null; - sidebar_stack.set_visible_child_full ("library", Gtk.StackTransitionType.CROSSFADE); - main_stack.set_visible_child_full ("welcome", Gtk.StackTransitionType.UNDER_RIGHT); - } + public weak Sequeler.Window window { get; construct; } + public Sequeler.Services.ConnectionManager? connection_manager { get; set; default = null; } + + public Sequeler.Layouts.Library library; + public Sequeler.Layouts.DataBaseSchema database_schema; + public Sequeler.Layouts.Welcome welcome; + public Sequeler.Layouts.DataBaseView database_view; + + public Gtk.Stack sidebar_stack; + public Gtk.Stack main_stack; + + public Main (Sequeler.Window main_window) { + Object ( + orientation: Gtk.Orientation.HORIZONTAL, + window: main_window + ); + } + + construct { + position = settings.sidebar_width; + + sidebar_stack = new Gtk.Stack (); + library = new Sequeler.Layouts.Library (window); + database_schema = new Sequeler.Layouts.DataBaseSchema (window); + sidebar_stack.add_named (library, "library"); + sidebar_stack.add_named (database_schema, "database_schema"); + + main_stack = new Gtk.Stack (); + welcome = new Sequeler.Layouts.Welcome (window); + database_view = new Sequeler.Layouts.DataBaseView (window); + main_stack.add_named (welcome, "welcome"); + main_stack.add_named (database_view, "database_view"); + + build_sidebar (); + build_main (); + } + + public void build_sidebar () { + pack1 (sidebar_stack, false, false); + } + + public void build_main () { + pack2 (main_stack, true, false); + } + + public async void connection_opened (Sequeler.Services.ConnectionManager? cnn_manager) { + debug ("connection opened"); + connection_manager = cnn_manager; + var host = cnn_manager.data["host"] != "" ? cnn_manager.data["host"] : "127.0.0.1"; + + window.headerbar.toggle_logout.begin (); + sidebar_stack.set_visible_child_full ("database_schema", Gtk.StackTransitionType.CROSSFADE); + main_stack.set_visible_child_full ("database_view", Gtk.StackTransitionType.SLIDE_LEFT); + + window.headerbar.title = _("Connected to %s").printf (cnn_manager.data["title"]); + window.headerbar.subtitle = cnn_manager.data["username"] + "@" + host; + + database_schema.reload_schema.begin (); + } + + public void connection_closed () { + if (connection_manager.data["has_ssh"] == "true") { + debug ("connection manager %p", connection_manager); + connection_manager.ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + } + + if (connection_manager.connection != null && connection_manager.connection.is_opened ()) { + connection_manager.connection.clear_events_list (); + connection_manager.connection.close (); + connection_manager.connection = null; + } + + connection_manager = null; + sidebar_stack.set_visible_child_full ("library", Gtk.StackTransitionType.CROSSFADE); + main_stack.set_visible_child_full ("welcome", Gtk.StackTransitionType.UNDER_RIGHT); + } } diff --git a/src/Layouts/Views/Content.vala b/src/Layouts/Views/Content.vala index f0209d7d..2f761034 100644 --- a/src/Layouts/Views/Content.vala +++ b/src/Layouts/Views/Content.vala @@ -20,258 +20,258 @@ */ public class Sequeler.Layouts.Views.Content : Gtk.Grid { - public weak Sequeler.Window window { get; construct; } - - public Gtk.Stack stack; - private Gda.DataModel? table_content; - public Gtk.Grid scroll_grid; - public Gtk.ScrolledWindow scroll; - public Gtk.Label result_message; - private Gtk.Spinner spinner; - - private Sequeler.Partials.HeaderBarButton page_prev_btn; - private Sequeler.Partials.HeaderBarButton page_next_btn; - private Gtk.Label pages_label; - private int tot_pages { get; set; default = 0; } - private int current_page { get; set; default = 1; } - private bool reloading { get; set; default = false; } - - private string _table_name = ""; - - public string table_name { - get { return _table_name; } - set { _table_name = value; } - } - - private string _database = ""; - - public string database { - get { return _database; } - set { _database = value; } - } - - public int table_count = 0; - - public Content (Sequeler.Window main_window) { - Object ( - orientation: Gtk.Orientation.VERTICAL, - window: main_window - ); - } - - construct { - scroll_grid = new Gtk.Grid (); - scroll_grid.expand = true; - - scroll = new Gtk.ScrolledWindow (null, null); - scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - scroll.expand = true; - scroll_grid.add (scroll); - - var info_bar = new Gtk.Grid (); - info_bar.get_style_context ().add_class ("library-toolbar"); - info_bar.attach (build_pagination (), 0, 0, 1, 1); - info_bar.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0, 1, 1); - info_bar.attach (build_results_msg (), 2, 0, 1, 1); - info_bar.attach (build_reload_btn (), 3, 0, 1, 1); - - spinner = new Gtk.Spinner (); - spinner.hexpand = true; - spinner.vexpand = true; - spinner.halign = Gtk.Align.CENTER; - spinner.valign = Gtk.Align.CENTER; - spinner.start (); - - var welcome = new Granite.Widgets.Welcome (_("Select Table"), _("Select a table from the left sidebar to activate this view.")); - - stack = new Gtk.Stack (); - stack.hexpand = true; - stack.vexpand = true; - stack.add_named (welcome, "welcome"); - stack.add_named (spinner, "spinner"); - stack.add_named (scroll_grid, "list"); - - attach (stack, 0, 0, 1, 1); - attach (info_bar, 0, 1, 1, 1); - - placeholder (); - } - - public void placeholder () { - stack.visible_child_name = "welcome"; - } - - public void start_spinner () { - stack.visible_child_name = "spinner"; - } - - public void stop_spinner () { - stack.visible_child_name = "list"; - } - - public Gtk.Grid build_pagination () { - var page_grid = new Gtk.Grid (); - - page_prev_btn = new Sequeler.Partials.HeaderBarButton ("go-previous-symbolic", _("Previous Page")); - page_prev_btn.clicked.connect (go_prev_page); - page_prev_btn.halign = Gtk.Align.START; - page_prev_btn.sensitive = false; - - page_next_btn = new Sequeler.Partials.HeaderBarButton ("go-next-symbolic", _("Next Page")); - page_next_btn.clicked.connect (go_next_page); - page_next_btn.halign = Gtk.Align.END; - page_next_btn.sensitive = false; - - pages_label = new Gtk.Label (_("%d Pages").printf(tot_pages)); - pages_label.margin = 7; - - page_grid.attach (page_prev_btn, 0, 0, 1, 1); - page_grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0, 1, 1); - page_grid.attach (pages_label, 2, 0, 1, 1); - page_grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 3, 0, 1, 1); - page_grid.attach (page_next_btn, 4, 0, 1, 1); - - return page_grid; - } - - private void update_pagination () { - if (table_count <= settings.limit_results) { - pages_label.set_text (_("1 Page")); - return; - } - - tot_pages = (int) Math.ceilf (((float) table_count) / settings.limit_results); - pages_label.set_text (_("%d of %d Pages").printf (current_page, tot_pages)); - - page_prev_btn.sensitive = (current_page > 1); - page_next_btn.sensitive = (current_page < tot_pages); - } - - public Gtk.Label build_results_msg () { - result_message = new Gtk.Label (_("No Results Available")); - result_message.halign = Gtk.Align.START; - result_message.margin = 7; - result_message.margin_top = 6; - result_message.hexpand = true; - result_message.wrap = true; - - return result_message; - } - - private Gtk.Button build_reload_btn () { - var reload_btn = new Sequeler.Partials.HeaderBarButton ("view-refresh-symbolic", _("Reload Results")); - reload_btn.clicked.connect (reload_results); - reload_btn.halign = Gtk.Align.END; - - return reload_btn; - } - - public async void clear () { - if (scroll == null) { - return; - } - - scroll.destroy (); - - scroll = new Gtk.ScrolledWindow (null, null); - scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - scroll.expand = true; - - scroll_grid.add (scroll); - } - - public async void reset () { - if (scroll.get_child () != null) { - scroll.remove (scroll.get_child ()); - } - - result_message.label = _("No Results Available"); - table_name = ""; - database = ""; - placeholder (); - } - - public void fill (string? table, string? db_name = null, string? count = null) { - if (table == null) { - return; - } - - if (table == _table_name && db_name == _database) { - return; - } - - table_name = table; - database = db_name; - table_count = count != null ? int.parse (count) : 0; - - tot_pages = 0; - current_page = 1; - - get_content_and_fill.begin (); - } - - public void reload_results () { - if (table_name == "") { - return; - } - - get_content_and_fill.begin (); - } - - public async void get_content_and_fill () { - if (reloading) { - debug ("still loading"); - return; - } - - start_spinner (); - var query = (window.main.connection_manager.db_type as DataBaseType) - .show_table_content (table_name, table_count, current_page); - reloading = true; - - table_content = yield get_table_content (query); - - if (table_content == null) { - return; - } - - var result_data = new Sequeler.Partials.TreeBuilder (table_content, window, settings.limit_results, current_page); - result_message.label = _("%d Entries").printf (table_count); + public weak Sequeler.Window window { get; construct; } + + public Gtk.Stack stack; + private Gda.DataModel? table_content; + public Gtk.Grid scroll_grid; + public Gtk.ScrolledWindow scroll; + public Gtk.Label result_message; + private Gtk.Spinner spinner; + + private Sequeler.Partials.HeaderBarButton page_prev_btn; + private Sequeler.Partials.HeaderBarButton page_next_btn; + private Gtk.Label pages_label; + private int tot_pages { get; set; default = 0; } + private int current_page { get; set; default = 1; } + private bool reloading { get; set; default = false; } + + private string _table_name = ""; + + public string table_name { + get { return _table_name; } + set { _table_name = value; } + } + + private string _database = ""; + + public string database { + get { return _database; } + set { _database = value; } + } + + public int table_count = 0; + + public Content (Sequeler.Window main_window) { + Object ( + orientation: Gtk.Orientation.VERTICAL, + window: main_window + ); + } + + construct { + scroll_grid = new Gtk.Grid (); + scroll_grid.expand = true; + + scroll = new Gtk.ScrolledWindow (null, null); + scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + scroll.expand = true; + scroll_grid.add (scroll); + + var info_bar = new Gtk.Grid (); + info_bar.get_style_context ().add_class ("library-toolbar"); + info_bar.attach (build_pagination (), 0, 0, 1, 1); + info_bar.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0, 1, 1); + info_bar.attach (build_results_msg (), 2, 0, 1, 1); + info_bar.attach (build_reload_btn (), 3, 0, 1, 1); + + spinner = new Gtk.Spinner (); + spinner.hexpand = true; + spinner.vexpand = true; + spinner.halign = Gtk.Align.CENTER; + spinner.valign = Gtk.Align.CENTER; + spinner.start (); + + var welcome = new Granite.Widgets.Welcome (_("Select Table"), _("Select a table from the left sidebar to activate this view.")); + + stack = new Gtk.Stack (); + stack.hexpand = true; + stack.vexpand = true; + stack.add_named (welcome, "welcome"); + stack.add_named (spinner, "spinner"); + stack.add_named (scroll_grid, "list"); + + attach (stack, 0, 0, 1, 1); + attach (info_bar, 0, 1, 1, 1); + + placeholder (); + } + + public void placeholder () { + stack.visible_child_name = "welcome"; + } + + public void start_spinner () { + stack.visible_child_name = "spinner"; + } + + public void stop_spinner () { + stack.visible_child_name = "list"; + } + + public Gtk.Grid build_pagination () { + var page_grid = new Gtk.Grid (); + + page_prev_btn = new Sequeler.Partials.HeaderBarButton ("go-previous-symbolic", _("Previous Page")); + page_prev_btn.clicked.connect (go_prev_page); + page_prev_btn.halign = Gtk.Align.START; + page_prev_btn.sensitive = false; + + page_next_btn = new Sequeler.Partials.HeaderBarButton ("go-next-symbolic", _("Next Page")); + page_next_btn.clicked.connect (go_next_page); + page_next_btn.halign = Gtk.Align.END; + page_next_btn.sensitive = false; + + pages_label = new Gtk.Label (_("%d Pages").printf (tot_pages)); + pages_label.margin = 7; + + page_grid.attach (page_prev_btn, 0, 0, 1, 1); + page_grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0, 1, 1); + page_grid.attach (pages_label, 2, 0, 1, 1); + page_grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 3, 0, 1, 1); + page_grid.attach (page_next_btn, 4, 0, 1, 1); + + return page_grid; + } + + private void update_pagination () { + if (table_count <= settings.limit_results) { + pages_label.set_text (_("1 Page")); + return; + } + + tot_pages = (int) Math.ceilf (((float) table_count) / settings.limit_results); + pages_label.set_text (_("%d of %d Pages").printf (current_page, tot_pages)); + + page_prev_btn.sensitive = (current_page > 1); + page_next_btn.sensitive = (current_page < tot_pages); + } + + public Gtk.Label build_results_msg () { + result_message = new Gtk.Label (_("No Results Available")); + result_message.halign = Gtk.Align.START; + result_message.margin = 7; + result_message.margin_top = 6; + result_message.hexpand = true; + result_message.wrap = true; + + return result_message; + } + + private Gtk.Button build_reload_btn () { + var reload_btn = new Sequeler.Partials.HeaderBarButton ("view-refresh-symbolic", _("Reload Results")); + reload_btn.clicked.connect (reload_results); + reload_btn.halign = Gtk.Align.END; + + return reload_btn; + } + + public async void clear () { + if (scroll == null) { + return; + } + + scroll.destroy (); + + scroll = new Gtk.ScrolledWindow (null, null); + scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + scroll.expand = true; + + scroll_grid.add (scroll); + } + + public async void reset () { + if (scroll.get_child () != null) { + scroll.remove (scroll.get_child ()); + } + + result_message.label = _("No Results Available"); + table_name = ""; + database = ""; + placeholder (); + } + + public void fill (string? table, string? db_name = null, string? count = null) { + if (table == null) { + return; + } + + if (table == _table_name && db_name == _database) { + return; + } + + table_name = table; + database = db_name; + table_count = count != null ? int.parse (count) : 0; + + tot_pages = 0; + current_page = 1; + + get_content_and_fill.begin (); + } + + public void reload_results () { + if (table_name == "") { + return; + } + + get_content_and_fill.begin (); + } + + public async void get_content_and_fill () { + if (reloading) { + debug ("still loading"); + return; + } + + start_spinner (); + var query = (window.main.connection_manager.db_type as DataBaseType) + .show_table_content (table_name, table_count, current_page); + reloading = true; + + table_content = yield get_table_content (query); + + if (table_content == null) { + return; + } + + var result_data = new Sequeler.Partials.TreeBuilder (table_content, window, settings.limit_results, current_page); + result_message.label = _("%d Entries").printf (table_count); - yield clear (); - update_pagination (); - - scroll.add (result_data); - scroll.show_all (); - reloading = false; - - stop_spinner (); - } - - private async Gda.DataModel? get_table_content (string query) { - Gda.DataModel? result = null; + yield clear (); + update_pagination (); + + scroll.add (result_data); + scroll.show_all (); + reloading = false; + + stop_spinner (); + } + + private async Gda.DataModel? get_table_content (string query) { + Gda.DataModel? result = null; - result = yield window.main.connection_manager.init_select_query (query); + result = yield window.main.connection_manager.init_select_query (query); - if (result == null) { - reloading = false; - yield reset (); - } + if (result == null) { + reloading = false; + yield reset (); + } - return result; - } + return result; + } - public void go_prev_page () { - page_prev_btn.sensitive = false; - current_page--; - get_content_and_fill.begin (); - } + public void go_prev_page () { + page_prev_btn.sensitive = false; + current_page--; + get_content_and_fill.begin (); + } - public void go_next_page () { - page_next_btn.sensitive = false; - current_page++; - get_content_and_fill.begin (); - } + public void go_next_page () { + page_next_btn.sensitive = false; + current_page++; + get_content_and_fill.begin (); + } } diff --git a/src/Layouts/Views/Query.vala b/src/Layouts/Views/Query.vala index 758896d4..acbbfea2 100644 --- a/src/Layouts/Views/Query.vala +++ b/src/Layouts/Views/Query.vala @@ -20,168 +20,168 @@ */ public class Sequeler.Layouts.Views.Query : Gtk.Grid { - public weak Sequeler.Window window { get; construct; } - - public Gtk.SourceView query_builder; - public Gtk.SourceBuffer buffer; - public Gtk.SourceBuffer buffer_copy; - public Gtk.SourceStyleSchemeManager style_scheme_manager; - public Gtk.CssProvider style_provider; - public Gtk.ScrolledWindow scroll_results; - public Gtk.Spinner spinner; - public Gtk.Label loading_msg; - public Gtk.Label result_message; - public Gtk.Image icon_success; - public Gtk.Image icon_fail; - public Gtk.Button run_button; - public Gtk.MenuButton export_button; - private string font; - public string default_font { get; set; } - - GLib.File? file; - Gda.DataModel? response_data; - - public Gtk.Paned panels; - public Sequeler.Partials.TreeBuilder result_data; - - public Query (Sequeler.Window main_window) { - Object ( - orientation: Gtk.Orientation.VERTICAL, - window: main_window - ); - } - - construct { - default_font = new GLib.Settings ("org.gnome.desktop.interface").get_string ("monospace-font-name"); - - panels = new Gtk.Paned (Gtk.Orientation.VERTICAL); - panels.position = settings.query_area; - panels.expand = true; - - attach (panels, 0, 0, 1, 1); - - var scroll = new Gtk.ScrolledWindow (null, null); - scroll.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC); - build_query_builder (); - scroll.add (query_builder); - - panels.pack1 (scroll, false, false); - panels.pack2 (results_view (), true, false); - } - - public void use_default_font (bool value) { - if (!value) { - return; - } - - font = default_font; - } - - public void build_query_builder () { - var manager = Gtk.SourceLanguageManager.get_default (); - style_provider = new Gtk.CssProvider (); - style_scheme_manager = new Gtk.SourceStyleSchemeManager (); - - buffer = new Gtk.SourceBuffer (null); - buffer.highlight_syntax = true; - buffer.highlight_matching_brackets = true; - buffer.language = manager.get_language ("sql"); - - query_builder = new Gtk.SourceView.with_buffer (buffer); - query_builder.show_line_numbers = true; - query_builder.highlight_current_line = true; - query_builder.show_right_margin = false; - query_builder.wrap_mode = Gtk.WrapMode.WORD; - query_builder.smart_home_end = Gtk.SourceSmartHomeEndType.AFTER; - - Gtk.drag_dest_add_uri_targets (query_builder); - - update_font_style (); - update_color_style (); - } - - private string get_current_font_family () { - return font.substring (0, font.last_index_of (" ")); - } - - private double get_current_font_size () { - return double.parse (font.substring (font.last_index_of (" ") + 1)); - } - - public void update_font_style () { - font = Sequeler.settings.font; - use_default_font (Sequeler.settings.use_system_font); - var font_family = get_current_font_family (); - var font_size = get_current_font_size ().to_string (); - - try { - style_provider.load_from_data (" - * { - font-family: '%s'; - font-size: %spx; - }".printf (font_family, font_size), -1); - query_builder.get_style_context ().add_provider ( - style_provider, - Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - ); - } catch (Error e) { - debug ("Internal error loading session chooser style: %s", e.message); - } - } - - public void update_color_style () { - buffer.style_scheme = style_scheme_manager.get_scheme (Sequeler.settings.style_scheme); - } - - /** - * Get the text buffer based on user cursor, selection, and semicolon - */ - public string get_text () { - Gtk.TextIter start, end; - - // If a portion of text is selected - if (buffer.get_selection_bounds (out start, out end)) { - strip_comments (buffer.get_text (start, end, true).strip ()); - return buffer_copy.text.strip (); - } - - // If there's a semicolon, return the currently highlighted line - if (buffer.text.contains (";")) { - buffer.get_selection_bounds (out start, out end); - start.set_line_offset (0); - start.backward_find_char (is_semicolon, null); - if (! start.starts_line ()) { - start.forward_char (); - } - - if (end.starts_line ()) { - end.backward_char (); - } - - if (!end.ends_line ()) { - end.forward_to_line_end (); - } - - end.forward_find_char (is_semicolon, null); - - debug (buffer.get_text (start, end, true).strip ()); - strip_comments (buffer.get_text (start, end, true).strip ()); - return buffer_copy.text.strip (); - } - - // Return full text - strip_comments (); - debug (buffer_copy.text.strip ()); - return buffer_copy.text.strip (); - } - - /** + public weak Sequeler.Window window { get; construct; } + + public Gtk.SourceView query_builder; + public Gtk.SourceBuffer buffer; + public Gtk.SourceBuffer buffer_copy; + public Gtk.SourceStyleSchemeManager style_scheme_manager; + public Gtk.CssProvider style_provider; + public Gtk.ScrolledWindow scroll_results; + public Gtk.Spinner spinner; + public Gtk.Label loading_msg; + public Gtk.Label result_message; + public Gtk.Image icon_success; + public Gtk.Image icon_fail; + public Gtk.Button run_button; + public Gtk.MenuButton export_button; + private string font; + public string default_font { get; set; } + + GLib.File? file; + Gda.DataModel? response_data; + + public Gtk.Paned panels; + public Sequeler.Partials.TreeBuilder result_data; + + public Query (Sequeler.Window main_window) { + Object ( + orientation: Gtk.Orientation.VERTICAL, + window: main_window + ); + } + + construct { + default_font = new GLib.Settings ("org.gnome.desktop.interface").get_string ("monospace-font-name"); + + panels = new Gtk.Paned (Gtk.Orientation.VERTICAL); + panels.position = settings.query_area; + panels.expand = true; + + attach (panels, 0, 0, 1, 1); + + var scroll = new Gtk.ScrolledWindow (null, null); + scroll.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC); + build_query_builder (); + scroll.add (query_builder); + + panels.pack1 (scroll, false, false); + panels.pack2 (results_view (), true, false); + } + + public void use_default_font (bool value) { + if (!value) { + return; + } + + font = default_font; + } + + public void build_query_builder () { + var manager = Gtk.SourceLanguageManager.get_default (); + style_provider = new Gtk.CssProvider (); + style_scheme_manager = new Gtk.SourceStyleSchemeManager (); + + buffer = new Gtk.SourceBuffer (null); + buffer.highlight_syntax = true; + buffer.highlight_matching_brackets = true; + buffer.language = manager.get_language ("sql"); + + query_builder = new Gtk.SourceView.with_buffer (buffer); + query_builder.show_line_numbers = true; + query_builder.highlight_current_line = true; + query_builder.show_right_margin = false; + query_builder.wrap_mode = Gtk.WrapMode.WORD; + query_builder.smart_home_end = Gtk.SourceSmartHomeEndType.AFTER; + + Gtk.drag_dest_add_uri_targets (query_builder); + + update_font_style (); + update_color_style (); + } + + private string get_current_font_family () { + return font.substring (0, font.last_index_of (" ")); + } + + private double get_current_font_size () { + return double.parse (font.substring (font.last_index_of (" ") + 1)); + } + + public void update_font_style () { + font = Sequeler.settings.font; + use_default_font (Sequeler.settings.use_system_font); + var font_family = get_current_font_family (); + var font_size = get_current_font_size ().to_string (); + + try { + style_provider.load_from_data (" + * { + font-family: '%s'; + font-size: %spx; + }".printf (font_family, font_size), -1); + query_builder.get_style_context ().add_provider ( + style_provider, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION + ); + } catch (Error e) { + debug ("Internal error loading session chooser style: %s", e.message); + } + } + + public void update_color_style () { + buffer.style_scheme = style_scheme_manager.get_scheme (Sequeler.settings.style_scheme); + } + + /** + * Get the text buffer based on user cursor, selection, and semicolon + */ + public string get_text () { + Gtk.TextIter start, end; + + // If a portion of text is selected + if (buffer.get_selection_bounds (out start, out end)) { + strip_comments (buffer.get_text (start, end, true).strip ()); + return buffer_copy.text.strip (); + } + + // If there's a semicolon, return the currently highlighted line + if (buffer.text.contains (";")) { + buffer.get_selection_bounds (out start, out end); + start.set_line_offset (0); + start.backward_find_char (is_semicolon, null); + if (! start.starts_line ()) { + start.forward_char (); + } + + if (end.starts_line ()) { + end.backward_char (); + } + + if (!end.ends_line ()) { + end.forward_to_line_end (); + } + + end.forward_find_char (is_semicolon, null); + + debug (buffer.get_text (start, end, true).strip ()); + strip_comments (buffer.get_text (start, end, true).strip ()); + return buffer_copy.text.strip (); + } + + // Return full text + strip_comments (); + debug (buffer_copy.text.strip ()); + return buffer_copy.text.strip (); + } + + /** * Remove inline comments (//) and block comments (/*) */ public void strip_comments (string? source_text = null) { var text = source_text != null ? source_text : buffer.text; - buffer_copy = new Gtk.SourceBuffer (null); - buffer_copy.set_text (text); + buffer_copy = new Gtk.SourceBuffer (null); + buffer_copy.set_text (text); string[] lines = Regex.split_simple ("""[\r\n]""", text); if (lines.length != buffer_copy.get_line_count ()) { @@ -198,364 +198,364 @@ public class Sequeler.Layouts.Views.Query : Gtk.Grid { } catch (RegexError e) { critical ("Error while building regex to replace trailing whitespace: %s", e.message); return; - } + } - // Find comments line by line + // Find comments line by line for (int line_no = 0; line_no < lines.length; line_no++) { if (comments.match (lines[line_no], 0, out info)) { buffer_copy.get_iter_at_line (out start_delete, line_no); start_delete.forward_to_line_end (); end_delete = start_delete; - end_delete.backward_chars (info.fetch (0).length); + end_delete.backward_chars (info.fetch (0).length); buffer_copy.@delete (ref start_delete, ref end_delete); } - } + } - int start_pos, end_pos; + int start_pos, end_pos; - // Find leftover comment blocks - if (comments.match (text, 0, out info)) { - info.fetch_pos (0, out start_pos, out end_pos); - buffer_copy.get_iter_at_offset (out start_delete, start_pos); - end_delete = start_delete; - end_delete.forward_chars (info.fetch (0).length); + // Find leftover comment blocks + if (comments.match (text, 0, out info)) { + info.fetch_pos (0, out start_pos, out end_pos); + buffer_copy.get_iter_at_offset (out start_delete, start_pos); + end_delete = start_delete; + end_delete.forward_chars (info.fetch (0).length); - buffer_copy.@delete (ref start_delete, ref end_delete); - } + buffer_copy.@delete (ref start_delete, ref end_delete); + } } - public Gtk.Grid results_view () { - var results_view = new Gtk.Grid (); - - spinner = new Gtk.Spinner (); - spinner.hexpand = true; - spinner.halign = Gtk.Align.END; - spinner.margin = 10; - - var action_bar = new Gtk.Grid (); - action_bar.get_style_context ().add_class ("library-titlebar"); - action_bar.attach (build_loading_msg (), 0, 0, 1, 1); - action_bar.attach (spinner, 1, 0, 1, 1); - action_bar.attach (build_run_button (), 2, 0, 1, 1); - - scroll_results = new Gtk.ScrolledWindow (null, null); - scroll_results.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC); - scroll_results.expand = true; - - var info_bar = new Gtk.Grid (); - info_bar.get_style_context ().add_class ("library-toolbar"); - info_bar.attach (build_results_msg (), 0, 0, 1, 1); - info_bar.attach (build_export_btn (), 1, 0, 1, 1); - - results_view.attach (action_bar, 0, 0, 1, 1); - results_view.attach (scroll_results, 0, 1, 1, 1); - results_view.attach (info_bar, 0, 2, 1, 1); - - return results_view; - } - - public Gtk.Label build_loading_msg () { - loading_msg = new Gtk.Label (_("Running Query\u2026")); - loading_msg.halign = Gtk.Align.START; - loading_msg.margin = 10; - loading_msg.hexpand = true; - loading_msg.wrap = true; - toggle_loading_msg (false); - - return loading_msg; - } - - public void toggle_loading_msg (bool toggle) { - loading_msg.visible = toggle; - loading_msg.no_show_all = !toggle; - } - - public Gtk.Button build_run_button () { - var run_image = new Gtk.Image.from_icon_name ("system-run-symbolic", Gtk.IconSize.BUTTON); - run_button = new Gtk.Button.with_label (_("Run Query")); - run_button.get_style_context ().add_class ("suggested-action"); - run_button.always_show_image = true; - run_button.set_image (run_image); - run_button.can_focus = false; - run_button.margin = 10; - run_button.sensitive = false; - run_button.tooltip_markup = Granite.markup_accel_tooltip ({"Return"}, _("Run Query")); - run_button.action_name = Services.ActionManager.ACTION_PREFIX + Services.ActionManager.ACTION_RUN_QUERY; - - return run_button; - } - - public Gtk.Grid build_results_msg () { - var result_box = new Gtk.Grid (); - - icon_success = new Gtk.Image.from_icon_name ("process-completed-symbolic", Gtk.IconSize.BUTTON); - icon_success.margin_start = 7; - icon_success.visible = false; - icon_success.no_show_all = true; - - icon_fail = new Gtk.Image.from_icon_name ("dialog-error-symbolic", Gtk.IconSize.BUTTON); - icon_fail.margin_start = 7; - icon_fail.visible = false; - icon_fail.no_show_all = true; - - result_message = new Gtk.Label (_("No Results Available")); - result_message.halign = Gtk.Align.START; - result_message.margin = 7; - result_message.margin_top = 6; - result_message.hexpand = true; - result_message.wrap = true; - - result_box.attach (icon_success, 0, 0, 1, 1); - result_box.attach (icon_fail, 1, 0, 1, 1); - result_box.attach (result_message, 2, 0, 1, 1); - - return result_box; - } - - public void show_result_icon (bool status) { - if (status) { - icon_success.visible = true; - icon_success.no_show_all = false; - icon_fail.visible = false; - icon_fail.no_show_all = true; - return; - } - - icon_success.visible = false; - icon_success.no_show_all = true; - icon_fail.visible = true; - icon_fail.no_show_all = false; - } - - public Gtk.Button build_export_btn () { - var export_image = new Gtk.Image.from_icon_name ("document-save-symbolic", Gtk.IconSize.BUTTON); - export_button = new Gtk.MenuButton (); - export_button.label = _("Export Results"); - export_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - export_button.always_show_image = true; - export_button.set_image (export_image); - export_button.can_focus = false; - - var menu_grid = new Gtk.Grid (); - menu_grid.expand = true; - menu_grid.margin_top = 3; - menu_grid.margin_bottom = 3; - menu_grid.orientation = Gtk.Orientation.VERTICAL; - - var export_csv = new Gtk.ModelButton (); - export_csv.label = _("Export as CSV"); - export_csv.image = new Gtk.Image.from_icon_name ("x-office-spreadsheet", Gtk.IconSize.BUTTON); - export_csv.always_show_image = true; - export_csv.clicked.connect (() => { - export_results (1); - }); - - var export_text = new Gtk.ModelButton (); - export_text.label = _("Export as Text"); - export_text.image = new Gtk.Image.from_icon_name ("text-x-generic", Gtk.IconSize.BUTTON); - export_text.always_show_image = true; - export_text.clicked.connect (() => { - export_results (2); - }); - - menu_grid.attach (export_csv, 0, 1, 1, 1); - menu_grid.attach (export_text, 0, 2, 1, 1); - menu_grid.show_all (); - - var export_menu = new Gtk.Popover (null); - export_menu.add (menu_grid); - - export_button.popover = export_menu; - export_button.direction = Gtk.ArrowType.UP; - export_button.sensitive = false; - - return export_button; - } - - public void run_query (string query) { - toggle_loading_msg (true); - spinner.start (); - - var select_pos = query.down ().index_of ("select", 0); - var show_pos = query.down ().index_of ("show", 0); - var pragma_pos = query.down ().index_of ("pragma", 0); - var explain_pos = query.down ().index_of ("explain", 0); - - if (select_pos == 0 || show_pos == 0 || pragma_pos == 0 || explain_pos == 0) { - select_statement.begin (query, (obj, res) => { - handle_select_response (select_statement.end (res)); - }); - } else { - non_select_statement.begin (query, (obj, res) => { - handle_query_response (non_select_statement.end (res)); - }); - } - } - - private async Gda.DataModel? select_statement (string query) { - return yield window.main.connection_manager.init_select_query (query); - } - - public async int? non_select_statement (string query) { - return yield window.main.connection_manager.init_query (query); - } - - public void handle_select_response (Gda.DataModel? response) { - response_data = response; - - if (response == null) { - toggle_loading_msg (false); - spinner.stop (); - - result_message.label = _("Unable to process Query!"); - show_result_icon (false); - - export_button.sensitive = false; - return; - } - - if (result_data != null) { - scroll_results.remove (result_data); - result_data = null; - } - - result_data = new Sequeler.Partials.TreeBuilder (response, window); - - toggle_loading_msg (false); - spinner.stop (); - - result_message.label = _("%d Total Results").printf (response.get_n_rows ()); - show_result_icon (true); - - scroll_results.add (result_data); - scroll_results.show_all (); - - if (response.get_n_rows () == 0) { - export_button.sensitive = false; - } else { - export_button.sensitive = true; - } - } - - public void handle_query_response (int? response) { - toggle_loading_msg (false); - spinner.stop (); - - if (result_data != null) { - scroll_results.remove (result_data); - result_data = null; - } - - if (response == null) { - result_message.label = _("Unable to process Query!"); - show_result_icon (false); - return; - } - - if (response > 0) { - result_message.label = _("Query Successfully Executed! Rows Affected: %d").printf(response); - show_result_icon (true); - } else { - result_message.label = _("Query Executed!"); - show_result_icon (true); - } - - window.main.database_schema.reload_schema.begin (); - - // Force reset all views to fetch updated data - window.main.database_view.content.reset.begin (); - window.main.database_view.relations.reset.begin (); - window.main.database_view.structure.reset.begin (); - } - - private bool is_semicolon (unichar semicolon) { - return semicolon.to_string () == ";"; - } - - private void export_results (int type) { - file = null; - - var save_dialog = new Gtk.FileChooserNative (_("Pick a file"), - window, - Gtk.FileChooserAction.SAVE, - _("_Save"), - _("_Cancel")); - - save_dialog.do_overwrite_confirmation = true; - save_dialog.modal = true; - save_dialog.response.connect ((dialog, response_id) => { - switch (response_id) { - case Gtk.ResponseType.ACCEPT: - file = save_dialog.get_file (); - save_to_file (type); - break; - default: - break; - } - dialog.destroy (); - }); - - save_dialog.run (); - } - - private void save_to_file (int type) { - var options_list = new GLib.SList (); - var separator_holder = new Gda.Holder (GLib.Type.STRING); - var first_line_holder = new Gda.Holder (GLib.Type.BOOLEAN); - var overwrite_holder = new Gda.Holder (GLib.Type.BOOLEAN); - - separator_holder.id = "SEPARATOR"; - try { - separator_holder.set_value (","); - } - catch (GLib.Error err) { - window.main.connection_manager.query_warning (err.message); - } - - first_line_holder.id = "NAMES_ON_FIRST_LINE"; - try { - first_line_holder.set_value (true); - } - catch (GLib.Error err) { - window.main.connection_manager.query_warning (err.message); - } - - overwrite_holder.id = "OVERWRITE"; - try { - overwrite_holder.set_value (true); - } - catch (GLib.Error err) { - window.main.connection_manager.query_warning (err.message); - } - - options_list.append (separator_holder); - options_list.append (first_line_holder); - options_list.append (overwrite_holder); - - var options = new Gda.Set (options_list); - - switch (type) { - case 1: - // Export as CSV - try { - response_data.export_to_file (Gda.DataModelIOFormat.TEXT_SEPARATED, file.get_path (), null, null, options); - } - catch (GLib.Error err) { - window.main.connection_manager.query_warning (err.message); - } - break; - case 2: - // Export as plain text - try { - response_data.export_to_file (Gda.DataModelIOFormat.TEXT_TABLE, file.get_path (), null, null, options); - } - catch (GLib.Error err) { - window.main.connection_manager.query_warning (err.message); - } - break; - default: - break; - } - } + public Gtk.Grid results_view () { + var results_view = new Gtk.Grid (); + + spinner = new Gtk.Spinner (); + spinner.hexpand = true; + spinner.halign = Gtk.Align.END; + spinner.margin = 10; + + var action_bar = new Gtk.Grid (); + action_bar.get_style_context ().add_class ("library-titlebar"); + action_bar.attach (build_loading_msg (), 0, 0, 1, 1); + action_bar.attach (spinner, 1, 0, 1, 1); + action_bar.attach (build_run_button (), 2, 0, 1, 1); + + scroll_results = new Gtk.ScrolledWindow (null, null); + scroll_results.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC); + scroll_results.expand = true; + + var info_bar = new Gtk.Grid (); + info_bar.get_style_context ().add_class ("library-toolbar"); + info_bar.attach (build_results_msg (), 0, 0, 1, 1); + info_bar.attach (build_export_btn (), 1, 0, 1, 1); + + results_view.attach (action_bar, 0, 0, 1, 1); + results_view.attach (scroll_results, 0, 1, 1, 1); + results_view.attach (info_bar, 0, 2, 1, 1); + + return results_view; + } + + public Gtk.Label build_loading_msg () { + loading_msg = new Gtk.Label (_("Running Query\u2026")); + loading_msg.halign = Gtk.Align.START; + loading_msg.margin = 10; + loading_msg.hexpand = true; + loading_msg.wrap = true; + toggle_loading_msg (false); + + return loading_msg; + } + + public void toggle_loading_msg (bool toggle) { + loading_msg.visible = toggle; + loading_msg.no_show_all = !toggle; + } + + public Gtk.Button build_run_button () { + var run_image = new Gtk.Image.from_icon_name ("system-run-symbolic", Gtk.IconSize.BUTTON); + run_button = new Gtk.Button.with_label (_("Run Query")); + run_button.get_style_context ().add_class ("suggested-action"); + run_button.always_show_image = true; + run_button.set_image (run_image); + run_button.can_focus = false; + run_button.margin = 10; + run_button.sensitive = false; + run_button.tooltip_markup = Granite.markup_accel_tooltip ({"Return"}, _("Run Query")); + run_button.action_name = Services.ActionManager.ACTION_PREFIX + Services.ActionManager.ACTION_RUN_QUERY; + + return run_button; + } + + public Gtk.Grid build_results_msg () { + var result_box = new Gtk.Grid (); + + icon_success = new Gtk.Image.from_icon_name ("process-completed-symbolic", Gtk.IconSize.BUTTON); + icon_success.margin_start = 7; + icon_success.visible = false; + icon_success.no_show_all = true; + + icon_fail = new Gtk.Image.from_icon_name ("dialog-error-symbolic", Gtk.IconSize.BUTTON); + icon_fail.margin_start = 7; + icon_fail.visible = false; + icon_fail.no_show_all = true; + + result_message = new Gtk.Label (_("No Results Available")); + result_message.halign = Gtk.Align.START; + result_message.margin = 7; + result_message.margin_top = 6; + result_message.hexpand = true; + result_message.wrap = true; + + result_box.attach (icon_success, 0, 0, 1, 1); + result_box.attach (icon_fail, 1, 0, 1, 1); + result_box.attach (result_message, 2, 0, 1, 1); + + return result_box; + } + + public void show_result_icon (bool status) { + if (status) { + icon_success.visible = true; + icon_success.no_show_all = false; + icon_fail.visible = false; + icon_fail.no_show_all = true; + return; + } + + icon_success.visible = false; + icon_success.no_show_all = true; + icon_fail.visible = true; + icon_fail.no_show_all = false; + } + + public Gtk.Button build_export_btn () { + var export_image = new Gtk.Image.from_icon_name ("document-save-symbolic", Gtk.IconSize.BUTTON); + export_button = new Gtk.MenuButton (); + export_button.label = _("Export Results"); + export_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); + export_button.always_show_image = true; + export_button.set_image (export_image); + export_button.can_focus = false; + + var menu_grid = new Gtk.Grid (); + menu_grid.expand = true; + menu_grid.margin_top = 3; + menu_grid.margin_bottom = 3; + menu_grid.orientation = Gtk.Orientation.VERTICAL; + + var export_csv = new Gtk.ModelButton (); + export_csv.label = _("Export as CSV"); + export_csv.image = new Gtk.Image.from_icon_name ("x-office-spreadsheet", Gtk.IconSize.BUTTON); + export_csv.always_show_image = true; + export_csv.clicked.connect (() => { + export_results (1); + }); + + var export_text = new Gtk.ModelButton (); + export_text.label = _("Export as Text"); + export_text.image = new Gtk.Image.from_icon_name ("text-x-generic", Gtk.IconSize.BUTTON); + export_text.always_show_image = true; + export_text.clicked.connect (() => { + export_results (2); + }); + + menu_grid.attach (export_csv, 0, 1, 1, 1); + menu_grid.attach (export_text, 0, 2, 1, 1); + menu_grid.show_all (); + + var export_menu = new Gtk.Popover (null); + export_menu.add (menu_grid); + + export_button.popover = export_menu; + export_button.direction = Gtk.ArrowType.UP; + export_button.sensitive = false; + + return export_button; + } + + public void run_query (string query) { + toggle_loading_msg (true); + spinner.start (); + + var select_pos = query.down ().index_of ("select", 0); + var show_pos = query.down ().index_of ("show", 0); + var pragma_pos = query.down ().index_of ("pragma", 0); + var explain_pos = query.down ().index_of ("explain", 0); + + if (select_pos == 0 || show_pos == 0 || pragma_pos == 0 || explain_pos == 0) { + select_statement.begin (query, (obj, res) => { + handle_select_response (select_statement.end (res)); + }); + } else { + non_select_statement.begin (query, (obj, res) => { + handle_query_response (non_select_statement.end (res)); + }); + } + } + + private async Gda.DataModel? select_statement (string query) { + return yield window.main.connection_manager.init_select_query (query); + } + + public async int? non_select_statement (string query) { + return yield window.main.connection_manager.init_query (query); + } + + public void handle_select_response (Gda.DataModel? response) { + response_data = response; + + if (response == null) { + toggle_loading_msg (false); + spinner.stop (); + + result_message.label = _("Unable to process Query!"); + show_result_icon (false); + + export_button.sensitive = false; + return; + } + + if (result_data != null) { + scroll_results.remove (result_data); + result_data = null; + } + + result_data = new Sequeler.Partials.TreeBuilder (response, window); + + toggle_loading_msg (false); + spinner.stop (); + + result_message.label = _("%d Total Results").printf (response.get_n_rows ()); + show_result_icon (true); + + scroll_results.add (result_data); + scroll_results.show_all (); + + if (response.get_n_rows () == 0) { + export_button.sensitive = false; + } else { + export_button.sensitive = true; + } + } + + public void handle_query_response (int? response) { + toggle_loading_msg (false); + spinner.stop (); + + if (result_data != null) { + scroll_results.remove (result_data); + result_data = null; + } + + if (response == null) { + result_message.label = _("Unable to process Query!"); + show_result_icon (false); + return; + } + + if (response > 0) { + result_message.label = _("Query Successfully Executed! Rows Affected: %d").printf (response); + show_result_icon (true); + } else { + result_message.label = _("Query Executed!"); + show_result_icon (true); + } + + window.main.database_schema.reload_schema.begin (); + + // Force reset all views to fetch updated data + window.main.database_view.content.reset.begin (); + window.main.database_view.relations.reset.begin (); + window.main.database_view.structure.reset.begin (); + } + + private bool is_semicolon (unichar semicolon) { + return semicolon.to_string () == ";"; + } + + private void export_results (int type) { + file = null; + + var save_dialog = new Gtk.FileChooserNative (_("Pick a file"), + window, + Gtk.FileChooserAction.SAVE, + _("_Save"), + _("_Cancel")); + + save_dialog.do_overwrite_confirmation = true; + save_dialog.modal = true; + save_dialog.response.connect ((dialog, response_id) => { + switch (response_id) { + case Gtk.ResponseType.ACCEPT: + file = save_dialog.get_file (); + save_to_file (type); + break; + default: + break; + } + dialog.destroy (); + }); + + save_dialog.run (); + } + + private void save_to_file (int type) { + var options_list = new GLib.SList (); + var separator_holder = new Gda.Holder (GLib.Type.STRING); + var first_line_holder = new Gda.Holder (GLib.Type.BOOLEAN); + var overwrite_holder = new Gda.Holder (GLib.Type.BOOLEAN); + + separator_holder.id = "SEPARATOR"; + try { + separator_holder.set_value (","); + } + catch (GLib.Error err) { + window.main.connection_manager.query_warning (err.message); + } + + first_line_holder.id = "NAMES_ON_FIRST_LINE"; + try { + first_line_holder.set_value (true); + } + catch (GLib.Error err) { + window.main.connection_manager.query_warning (err.message); + } + + overwrite_holder.id = "OVERWRITE"; + try { + overwrite_holder.set_value (true); + } + catch (GLib.Error err) { + window.main.connection_manager.query_warning (err.message); + } + + options_list.append (separator_holder); + options_list.append (first_line_holder); + options_list.append (overwrite_holder); + + var options = new Gda.Set (options_list); + + switch (type) { + case 1: + // Export as CSV + try { + response_data.export_to_file (Gda.DataModelIOFormat.TEXT_SEPARATED, file.get_path (), null, null, options); + } + catch (GLib.Error err) { + window.main.connection_manager.query_warning (err.message); + } + break; + case 2: + // Export as plain text + try { + response_data.export_to_file (Gda.DataModelIOFormat.TEXT_TABLE, file.get_path (), null, null, options); + } + catch (GLib.Error err) { + window.main.connection_manager.query_warning (err.message); + } + break; + default: + break; + } + } } diff --git a/src/Layouts/Views/Relations.vala b/src/Layouts/Views/Relations.vala index ab6d6910..46c92535 100644 --- a/src/Layouts/Views/Relations.vala +++ b/src/Layouts/Views/Relations.vala @@ -20,191 +20,191 @@ */ public class Sequeler.Layouts.Views.Relations : Gtk.Grid { - public weak Sequeler.Window window { get; construct; } - - public Gtk.Stack stack; - public Gtk.Grid scroll_grid; - public Gtk.ScrolledWindow scroll; - public Gtk.Label result_message; - private Gtk.Spinner spinner; - - private bool reloading { get; set; default = false; } - - private string _table_name = ""; - - public string table_name { - get { return _table_name; } - set { _table_name = value; } - } - - private string _database = ""; - - public string database { - get { return _database; } - set { _database = value; } - } - - public Relations (Sequeler.Window main_window) { - Object ( - orientation: Gtk.Orientation.VERTICAL, - window: main_window - ); - } - - construct { - scroll_grid = new Gtk.Grid (); - scroll_grid.expand = true; - - scroll = new Gtk.ScrolledWindow (null, null); - scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - scroll.expand = true; - - var info_bar = new Gtk.Grid (); - info_bar.get_style_context ().add_class ("library-toolbar"); - info_bar.attach (build_results_msg (), 0, 0, 1, 1); - info_bar.attach (build_reload_btn (), 1, 0, 1, 1); - - spinner = new Gtk.Spinner (); - spinner.hexpand = true; - spinner.vexpand = true; - spinner.halign = Gtk.Align.CENTER; - spinner.valign = Gtk.Align.CENTER; - spinner.start (); - - var welcome = new Granite.Widgets.Welcome (_("Select Table"), _("Select a table from the left sidebar to activate this view.")); - - stack = new Gtk.Stack (); - stack.hexpand = true; - stack.vexpand = true; - stack.add_named (welcome, "welcome"); - stack.add_named (spinner, "spinner"); - stack.add_named (scroll_grid, "list"); - - attach (stack, 0, 0, 1, 1); - attach (info_bar, 0, 1, 1, 1); - - placeholder (); - } - - public void placeholder () { - stack.visible_child_name = "welcome"; - } - - public void start_spinner () { - stack.visible_child_name = "spinner"; - } + public weak Sequeler.Window window { get; construct; } + + public Gtk.Stack stack; + public Gtk.Grid scroll_grid; + public Gtk.ScrolledWindow scroll; + public Gtk.Label result_message; + private Gtk.Spinner spinner; + + private bool reloading { get; set; default = false; } + + private string _table_name = ""; + + public string table_name { + get { return _table_name; } + set { _table_name = value; } + } + + private string _database = ""; + + public string database { + get { return _database; } + set { _database = value; } + } + + public Relations (Sequeler.Window main_window) { + Object ( + orientation: Gtk.Orientation.VERTICAL, + window: main_window + ); + } + + construct { + scroll_grid = new Gtk.Grid (); + scroll_grid.expand = true; + + scroll = new Gtk.ScrolledWindow (null, null); + scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + scroll.expand = true; + + var info_bar = new Gtk.Grid (); + info_bar.get_style_context ().add_class ("library-toolbar"); + info_bar.attach (build_results_msg (), 0, 0, 1, 1); + info_bar.attach (build_reload_btn (), 1, 0, 1, 1); + + spinner = new Gtk.Spinner (); + spinner.hexpand = true; + spinner.vexpand = true; + spinner.halign = Gtk.Align.CENTER; + spinner.valign = Gtk.Align.CENTER; + spinner.start (); + + var welcome = new Granite.Widgets.Welcome (_("Select Table"), _("Select a table from the left sidebar to activate this view.")); + + stack = new Gtk.Stack (); + stack.hexpand = true; + stack.vexpand = true; + stack.add_named (welcome, "welcome"); + stack.add_named (spinner, "spinner"); + stack.add_named (scroll_grid, "list"); + + attach (stack, 0, 0, 1, 1); + attach (info_bar, 0, 1, 1, 1); + + placeholder (); + } + + public void placeholder () { + stack.visible_child_name = "welcome"; + } + + public void start_spinner () { + stack.visible_child_name = "spinner"; + } - public void stop_spinner () { - stack.visible_child_name = "list"; - } + public void stop_spinner () { + stack.visible_child_name = "list"; + } - public Gtk.Label build_results_msg () { - result_message = new Gtk.Label (_("No Results Available")); - result_message.halign = Gtk.Align.START; - result_message.margin = 7; - result_message.margin_top = 6; - result_message.hexpand = true; - result_message.wrap = true; + public Gtk.Label build_results_msg () { + result_message = new Gtk.Label (_("No Results Available")); + result_message.halign = Gtk.Align.START; + result_message.margin = 7; + result_message.margin_top = 6; + result_message.hexpand = true; + result_message.wrap = true; - return result_message; - } + return result_message; + } - private Gtk.Button build_reload_btn () { - var reload_btn = new Sequeler.Partials.HeaderBarButton ("view-refresh-symbolic", _("Reload Results")); - reload_btn.clicked.connect (reload_results); - reload_btn.halign = Gtk.Align.END; + private Gtk.Button build_reload_btn () { + var reload_btn = new Sequeler.Partials.HeaderBarButton ("view-refresh-symbolic", _("Reload Results")); + reload_btn.clicked.connect (reload_results); + reload_btn.halign = Gtk.Align.END; - return reload_btn; - } + return reload_btn; + } - public async void clear () { - if (scroll == null) { - return; - } - - scroll.destroy (); + public async void clear () { + if (scroll == null) { + return; + } + + scroll.destroy (); - scroll = new Gtk.ScrolledWindow (null, null); - scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - scroll.expand = true; + scroll = new Gtk.ScrolledWindow (null, null); + scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + scroll.expand = true; - scroll_grid.add (scroll); - } - - public async void reset () { - if (scroll.get_child () != null) { - scroll.remove (scroll.get_child ()); - } - - result_message.label = _("No Results Available"); - table_name = ""; - database = ""; - placeholder (); - } - - public void fill (string? table, string? db_name = null) { - if (table == null) { - return; - } + scroll_grid.add (scroll); + } + + public async void reset () { + if (scroll.get_child () != null) { + scroll.remove (scroll.get_child ()); + } + + result_message.label = _("No Results Available"); + table_name = ""; + database = ""; + placeholder (); + } + + public void fill (string? table, string? db_name = null) { + if (table == null) { + return; + } - if (table == _table_name && db_name == _database) { - return; - } + if (table == _table_name && db_name == _database) { + return; + } - table_name = table; - database = db_name; - - get_content_and_fill.begin (); - } + table_name = table; + database = db_name; + + get_content_and_fill.begin (); + } - public void reload_results () { - if (table_name == "") { - return; - } + public void reload_results () { + if (table_name == "") { + return; + } - get_content_and_fill.begin (); - } + get_content_and_fill.begin (); + } - public async void get_content_and_fill () { - if (reloading) { - debug ("still loading"); - return; - } + public async void get_content_and_fill () { + if (reloading) { + debug ("still loading"); + return; + } - start_spinner (); - var query = (window.main.connection_manager.db_type as DataBaseType).show_table_relations (table_name, database); - reloading = true; + start_spinner (); + var query = (window.main.connection_manager.db_type as DataBaseType).show_table_relations (table_name, database); + reloading = true; - var table_relations = yield get_table_relations (query); + var table_relations = yield get_table_relations (query); - if (table_relations == null) { - return; - } + if (table_relations == null) { + return; + } - var result_data = new Sequeler.Partials.TreeBuilder (table_relations, window); - result_message.label = table_relations.get_n_rows ().to_string () + _(" Constraints"); + var result_data = new Sequeler.Partials.TreeBuilder (table_relations, window); + result_message.label = table_relations.get_n_rows ().to_string () + _(" Constraints"); - yield clear (); + yield clear (); - scroll.add (result_data); - scroll.show_all (); - reloading = false; + scroll.add (result_data); + scroll.show_all (); + reloading = false; - stop_spinner (); - } + stop_spinner (); + } - private async Gda.DataModel? get_table_relations (string query) { - Gda.DataModel? result = null; + private async Gda.DataModel? get_table_relations (string query) { + Gda.DataModel? result = null; - result = yield window.main.connection_manager.init_select_query (query); + result = yield window.main.connection_manager.init_select_query (query); - if (result == null) { - reloading = false; - yield reset (); - } + if (result == null) { + reloading = false; + yield reset (); + } - return result; - } + return result; + } } diff --git a/src/Layouts/Views/Structure.vala b/src/Layouts/Views/Structure.vala index 34dd38c4..b5079b68 100644 --- a/src/Layouts/Views/Structure.vala +++ b/src/Layouts/Views/Structure.vala @@ -20,192 +20,192 @@ */ public class Sequeler.Layouts.Views.Structure : Gtk.Grid { - public weak Sequeler.Window window { get; construct; } - - public Gtk.Stack stack; - public Gtk.Grid scroll_grid; - public Gtk.ScrolledWindow scroll; - public Gtk.Label result_message; - private Gtk.Spinner spinner; - - private bool reloading { get; set; default = false; } - - private string _table_name = ""; - - public string table_name { - get { return _table_name; } - set { _table_name = value; } - } - - private string _database = ""; - - public string database { - get { return _database; } - set { _database = value; } - } - - public Structure (Sequeler.Window main_window) { - Object ( - orientation: Gtk.Orientation.VERTICAL, - window: main_window - ); - } - - construct { - scroll_grid = new Gtk.Grid (); - scroll_grid.expand = true; - - scroll = new Gtk.ScrolledWindow (null, null); - scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - scroll.expand = true; - scroll_grid.add (scroll); - - var info_bar = new Gtk.Grid (); - info_bar.get_style_context ().add_class ("library-toolbar"); - info_bar.attach (build_results_msg (), 0, 0, 1, 1); - info_bar.attach (build_reload_btn (), 1, 0, 1, 1); - - spinner = new Gtk.Spinner (); - spinner.hexpand = true; - spinner.vexpand = true; - spinner.halign = Gtk.Align.CENTER; - spinner.valign = Gtk.Align.CENTER; - spinner.start (); - - var welcome = new Granite.Widgets.Welcome (_("Select Table"), _("Select a table from the left sidebar to activate this view.")); - - stack = new Gtk.Stack (); - stack.hexpand = true; - stack.vexpand = true; - stack.add_named (welcome, "welcome"); - stack.add_named (spinner, "spinner"); - stack.add_named (scroll_grid, "list"); - - attach (stack, 0, 0, 1, 1); - attach (info_bar, 0, 1, 1, 1); - - placeholder (); - } - - public void placeholder () { - stack.visible_child_name = "welcome"; - } - - public void start_spinner () { - stack.visible_child_name = "spinner"; - } - - public void stop_spinner () { - stack.visible_child_name = "list"; - } - - public Gtk.Label build_results_msg () { - result_message = new Gtk.Label (_("No Results Available")); - result_message.halign = Gtk.Align.START; - result_message.margin = 7; - result_message.margin_top = 6; - result_message.hexpand = true; - result_message.wrap = true; - - return result_message; - } - - private Gtk.Button build_reload_btn () { - var reload_btn = new Sequeler.Partials.HeaderBarButton ("view-refresh-symbolic", _("Reload Results")); - reload_btn.clicked.connect (reload_results); - reload_btn.halign = Gtk.Align.END; - - return reload_btn; - } - - public async void clear () { - if (scroll == null) { - return; - } - - scroll.destroy (); + public weak Sequeler.Window window { get; construct; } + + public Gtk.Stack stack; + public Gtk.Grid scroll_grid; + public Gtk.ScrolledWindow scroll; + public Gtk.Label result_message; + private Gtk.Spinner spinner; + + private bool reloading { get; set; default = false; } + + private string _table_name = ""; + + public string table_name { + get { return _table_name; } + set { _table_name = value; } + } + + private string _database = ""; + + public string database { + get { return _database; } + set { _database = value; } + } + + public Structure (Sequeler.Window main_window) { + Object ( + orientation: Gtk.Orientation.VERTICAL, + window: main_window + ); + } + + construct { + scroll_grid = new Gtk.Grid (); + scroll_grid.expand = true; + + scroll = new Gtk.ScrolledWindow (null, null); + scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + scroll.expand = true; + scroll_grid.add (scroll); + + var info_bar = new Gtk.Grid (); + info_bar.get_style_context ().add_class ("library-toolbar"); + info_bar.attach (build_results_msg (), 0, 0, 1, 1); + info_bar.attach (build_reload_btn (), 1, 0, 1, 1); + + spinner = new Gtk.Spinner (); + spinner.hexpand = true; + spinner.vexpand = true; + spinner.halign = Gtk.Align.CENTER; + spinner.valign = Gtk.Align.CENTER; + spinner.start (); + + var welcome = new Granite.Widgets.Welcome (_("Select Table"), _("Select a table from the left sidebar to activate this view.")); + + stack = new Gtk.Stack (); + stack.hexpand = true; + stack.vexpand = true; + stack.add_named (welcome, "welcome"); + stack.add_named (spinner, "spinner"); + stack.add_named (scroll_grid, "list"); + + attach (stack, 0, 0, 1, 1); + attach (info_bar, 0, 1, 1, 1); + + placeholder (); + } + + public void placeholder () { + stack.visible_child_name = "welcome"; + } + + public void start_spinner () { + stack.visible_child_name = "spinner"; + } + + public void stop_spinner () { + stack.visible_child_name = "list"; + } + + public Gtk.Label build_results_msg () { + result_message = new Gtk.Label (_("No Results Available")); + result_message.halign = Gtk.Align.START; + result_message.margin = 7; + result_message.margin_top = 6; + result_message.hexpand = true; + result_message.wrap = true; + + return result_message; + } + + private Gtk.Button build_reload_btn () { + var reload_btn = new Sequeler.Partials.HeaderBarButton ("view-refresh-symbolic", _("Reload Results")); + reload_btn.clicked.connect (reload_results); + reload_btn.halign = Gtk.Align.END; + + return reload_btn; + } + + public async void clear () { + if (scroll == null) { + return; + } + + scroll.destroy (); - scroll = new Gtk.ScrolledWindow (null, null); - scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - scroll.expand = true; - - scroll_grid.add (scroll); - } - - public async void reset () { - if (scroll.get_child () != null) { - scroll.remove (scroll.get_child ()); - } - - result_message.label = _("No Results Available"); - table_name = ""; - database = ""; - placeholder (); - } - - public void fill (string? table, string? db_name = null) { - if (table == null) { - return; - } + scroll = new Gtk.ScrolledWindow (null, null); + scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + scroll.expand = true; + + scroll_grid.add (scroll); + } + + public async void reset () { + if (scroll.get_child () != null) { + scroll.remove (scroll.get_child ()); + } + + result_message.label = _("No Results Available"); + table_name = ""; + database = ""; + placeholder (); + } + + public void fill (string? table, string? db_name = null) { + if (table == null) { + return; + } - if (table == _table_name && db_name == _database) { - return; - } + if (table == _table_name && db_name == _database) { + return; + } - table_name = table; - database = db_name; - - get_content_and_fill.begin (); - } + table_name = table; + database = db_name; + + get_content_and_fill.begin (); + } - public void reload_results () { - if (table_name == "") { - return; - } + public void reload_results () { + if (table_name == "") { + return; + } - get_content_and_fill.begin (); - } + get_content_and_fill.begin (); + } - public async void get_content_and_fill () { - if (reloading) { - debug ("still loading"); - return; - } + public async void get_content_and_fill () { + if (reloading) { + debug ("still loading"); + return; + } - start_spinner (); - var query = (window.main.connection_manager.db_type as DataBaseType).show_table_structure (table_name); - reloading = true; + start_spinner (); + var query = (window.main.connection_manager.db_type as DataBaseType).show_table_structure (table_name); + reloading = true; - var table_schema = yield get_table_schema (query); + var table_schema = yield get_table_schema (query); - if (table_schema == null) { - return; - } + if (table_schema == null) { + return; + } - var result_data = new Sequeler.Partials.TreeBuilder (table_schema, window); - result_message.label = table_schema.get_n_rows ().to_string () + _(" Fields"); + var result_data = new Sequeler.Partials.TreeBuilder (table_schema, window); + result_message.label = table_schema.get_n_rows ().to_string () + _(" Fields"); - yield clear (); + yield clear (); - scroll.add (result_data); - scroll.show_all (); - reloading = false; + scroll.add (result_data); + scroll.show_all (); + reloading = false; - stop_spinner (); - } + stop_spinner (); + } - private async Gda.DataModel? get_table_schema (string query) { - Gda.DataModel? result = null; + private async Gda.DataModel? get_table_schema (string query) { + Gda.DataModel? result = null; - result = yield window.main.connection_manager.init_select_query (query); + result = yield window.main.connection_manager.init_select_query (query); - if (result == null) { - reloading = false; - yield reset (); - } + if (result == null) { + reloading = false; + yield reset (); + } - return result; - } + return result; + } } diff --git a/src/Layouts/Welcome.vala b/src/Layouts/Welcome.vala index d22c7ec1..d21ff2ff 100644 --- a/src/Layouts/Welcome.vala +++ b/src/Layouts/Welcome.vala @@ -20,99 +20,99 @@ */ public class Sequeler.Layouts.Welcome : Granite.Widgets.Welcome { - public unowned Sequeler.Window window { get; construct; } - - public Welcome (Sequeler.Window main_window) { - Object ( - window: main_window, - title: _("Welcome to Sequeler"), - subtitle: _("Connect to Any Local or Remote Database.") - ); - } - - construct { - valign = Gtk.Align.FILL; - halign = Gtk.Align.FILL; - vexpand = true; - - append ("bookmark-new", _("Add a New Database"), _("Connect to a Database and Save It in Your Library")); - append ("window-new", _("New Window"), _("Open a New Sequeler Window")); - append ("folder-download", _("Import Connections"), _("Import Previously Exported Sequeler Connections")); - - activated.connect ( index => { - switch (index) { - case 0: - Sequeler.Services.ActionManager.action_from_group (Sequeler.Services.ActionManager.ACTION_NEW_CONNECTION, window.get_action_group ("win")); - break; - case 1: - Sequeler.Services.ActionManager.action_from_group (Sequeler.Services.ActionManager.ACTION_NEW_WINDOW, window.get_action_group ("win")); - break; - case 2: - import_file (); - break; - } - }); - } - - private void import_file () { - var open_dialog = new Gtk.FileChooserNative (_("Select a file"), - window, - Gtk.FileChooserAction.OPEN, - _("_Open"), - _("_Cancel")); - - open_dialog.local_only = true; - open_dialog.modal = true; - open_dialog.response.connect (open_file); - open_dialog.run (); - } - - private void open_file (Gtk.NativeDialog dialog, int response_id) { - var open_dialog = dialog as Gtk.FileChooserNative; - - switch (response_id) { - case Gtk.ResponseType.ACCEPT: - var file = open_dialog.get_file (); - uint8[] file_contents; - - try { - file.load_contents (null, out file_contents, null); - } - catch (GLib.Error err) { - import_warning (err.message); - } - var imported_connections = (string) file_contents; - var data = imported_connections.split ("---\n"); - foreach (var import in data) { - if (import == "") { - continue; - } - var array = settings.arraify_data (import); - array["id"] = settings.tot_connections.to_string (); - settings.add_connection (array); - } - - window.main.library.reload_library.begin (); - - break; - - case Gtk.ResponseType.CANCEL: - break; - } - - open_dialog.destroy (); - } - - private void import_warning (string message) { - var message_dialog = new Granite.MessageDialog.with_image_from_icon_name (_("Unable to Import Library "), message, "dialog-error", Gtk.ButtonsType.NONE); - message_dialog.transient_for = window; - - var suggested_button = new Gtk.Button.with_label ("Close"); - message_dialog.add_action_widget (suggested_button, Gtk.ResponseType.ACCEPT); - - message_dialog.show_all (); - if (message_dialog.run () == Gtk.ResponseType.ACCEPT) {} - - message_dialog.destroy (); - } + public unowned Sequeler.Window window { get; construct; } + + public Welcome (Sequeler.Window main_window) { + Object ( + window: main_window, + title: _("Welcome to Sequeler"), + subtitle: _("Connect to Any Local or Remote Database.") + ); + } + + construct { + valign = Gtk.Align.FILL; + halign = Gtk.Align.FILL; + vexpand = true; + + append ("bookmark-new", _("Add a New Database"), _("Connect to a Database and Save It in Your Library")); + append ("window-new", _("New Window"), _("Open a New Sequeler Window")); + append ("folder-download", _("Import Connections"), _("Import Previously Exported Sequeler Connections")); + + activated.connect ( index => { + switch (index) { + case 0: + Sequeler.Services.ActionManager.action_from_group (Sequeler.Services.ActionManager.ACTION_NEW_CONNECTION, window.get_action_group ("win")); + break; + case 1: + Sequeler.Services.ActionManager.action_from_group (Sequeler.Services.ActionManager.ACTION_NEW_WINDOW, window.get_action_group ("win")); + break; + case 2: + import_file (); + break; + } + }); + } + + private void import_file () { + var open_dialog = new Gtk.FileChooserNative (_("Select a file"), + window, + Gtk.FileChooserAction.OPEN, + _("_Open"), + _("_Cancel")); + + open_dialog.local_only = true; + open_dialog.modal = true; + open_dialog.response.connect (open_file); + open_dialog.run (); + } + + private void open_file (Gtk.NativeDialog dialog, int response_id) { + var open_dialog = dialog as Gtk.FileChooserNative; + + switch (response_id) { + case Gtk.ResponseType.ACCEPT: + var file = open_dialog.get_file (); + uint8[] file_contents; + + try { + file.load_contents (null, out file_contents, null); + } + catch (GLib.Error err) { + import_warning (err.message); + } + var imported_connections = (string) file_contents; + var data = imported_connections.split ("---\n"); + foreach (var import in data) { + if (import == "") { + continue; + } + var array = settings.arraify_data (import); + array["id"] = settings.tot_connections.to_string (); + settings.add_connection (array); + } + + window.main.library.reload_library.begin (); + + break; + + case Gtk.ResponseType.CANCEL: + break; + } + + open_dialog.destroy (); + } + + private void import_warning (string message) { + var message_dialog = new Granite.MessageDialog.with_image_from_icon_name (_("Unable to Import Library "), message, "dialog-error", Gtk.ButtonsType.NONE); + message_dialog.transient_for = window; + + var suggested_button = new Gtk.Button.with_label ("Close"); + message_dialog.add_action_widget (suggested_button, Gtk.ResponseType.ACCEPT); + + message_dialog.show_all (); + if (message_dialog.run () == Gtk.ResponseType.ACCEPT) {} + + message_dialog.destroy (); + } } diff --git a/src/Main.vala b/src/Main.vala index c66a731b..1cfea947 100644 --- a/src/Main.vala +++ b/src/Main.vala @@ -27,10 +27,10 @@ public const string APP_NAME = "Sequeler"; public const string TERMINAL_NAME = "sequeler"; public static int main (string[] args) { - Environment.set_application_name ("Sequeler"); - Environment.set_prgname ("Sequeler"); + Environment.set_application_name ("Sequeler"); + Environment.set_prgname ("Sequeler"); - var application = new Sequeler.Application (); + var application = new Sequeler.Application (); - return application.run (args); + return application.run (args); } diff --git a/src/Partials/ButtonType.vala b/src/Partials/ButtonType.vala index 23466286..6b0f3c5f 100644 --- a/src/Partials/ButtonType.vala +++ b/src/Partials/ButtonType.vala @@ -20,44 +20,44 @@ */ namespace Sequeler.Partials { - public class HeaderBarButton : Gtk.Button { - public HeaderBarButton (string icon_name, string tooltip) { - can_focus = false; - - Gtk.Image image; - - if (icon_name.contains ("/")) { - image = new Gtk.Image.from_resource (icon_name); - } else { - image = new Gtk.Image.from_icon_name (icon_name, Gtk.IconSize.BUTTON); - } - - image.margin = 3; - - get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - set_tooltip_text (tooltip); - add (image); - } - } - - public class ToolBarButton : Gtk.Grid { - public ToolBarButton (string icon_name, string tooltip, string label) { - name = tooltip; - halign = Gtk.Align.CENTER; - - Gtk.Image icon; - var title = new Gtk.Label (label); - - if (icon_name.contains ("/")) { - icon = new Gtk.Image.from_resource (icon_name); - } else { - icon = new Gtk.Image.from_icon_name (icon_name, Gtk.IconSize.BUTTON); - } - - icon.margin = 2; - - attach (icon, 0, 0, 1, 1); - attach (title, 1, 0, 1, 1); - } - } -} \ No newline at end of file + public class HeaderBarButton : Gtk.Button { + public HeaderBarButton (string icon_name, string tooltip) { + can_focus = false; + + Gtk.Image image; + + if (icon_name.contains ("/")) { + image = new Gtk.Image.from_resource (icon_name); + } else { + image = new Gtk.Image.from_icon_name (icon_name, Gtk.IconSize.BUTTON); + } + + image.margin = 3; + + get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); + set_tooltip_text (tooltip); + add (image); + } + } + + public class ToolBarButton : Gtk.Grid { + public ToolBarButton (string icon_name, string tooltip, string label) { + name = tooltip; + halign = Gtk.Align.CENTER; + + Gtk.Image icon; + var title = new Gtk.Label (label); + + if (icon_name.contains ("/")) { + icon = new Gtk.Image.from_resource (icon_name); + } else { + icon = new Gtk.Image.from_icon_name (icon_name, Gtk.IconSize.BUTTON); + } + + icon.margin = 2; + + attach (icon, 0, 0, 1, 1); + attach (title, 1, 0, 1, 1); + } + } +} diff --git a/src/Partials/Helpers.vala b/src/Partials/Helpers.vala index e069db04..03b34b54 100644 --- a/src/Partials/Helpers.vala +++ b/src/Partials/Helpers.vala @@ -19,75 +19,75 @@ * Authored by: Alessandro "Alecaddd" Castellani */ -namespace Sequeler.Partials { - public class TitleBar : Gtk.Grid { - public TitleBar (string text) { - get_style_context ().add_class ("library-titlebar"); - - var title = new Gtk.Label (text); - title.get_style_context ().add_class ("h4"); - title.halign = Gtk.Align.CENTER; - title.margin = 4; - title.hexpand = true; - - this.add (title); - } - } - - public class ResponseMessage : Gtk.Label { - public ResponseMessage () { - get_style_context ().add_class ("h4"); - halign = Gtk.Align.CENTER; - valign = Gtk.Align.CENTER; - justify = Gtk.Justification.CENTER; - set_line_wrap (true); - margin_bottom = 10; - } - } - - public class Entry : Gtk.Entry { - public Entry (string? placeholder, string? val) { - hexpand = true; - - if (placeholder != null) { - placeholder_text = placeholder; - } - - if (val != null) { - text = val; - } - } - } - - public class ButtonClass : Gtk.Button { - public ButtonClass (string text, string* class) { - label = text; - - if (class != null) { - var style_context = this.get_style_context (); - style_context.add_class (class); - } - } - } - - public class TableRow : Gtk.Grid { - public TableRow (string text, int type) { - if (type % 2 == 0) { - get_style_context ().add_class ("row-odd"); - } else { - get_style_context ().add_class ("row-even"); - } - - var title = new Gtk.Label (text); - title.get_style_context ().add_class ("h4"); - title.halign = Gtk.Align.START; - title.margin_start = 6; - title.margin_end = 6; - title.hexpand = true; - - this.add (title); - } - } +namespace Sequeler.Partials { + public class TitleBar : Gtk.Grid { + public TitleBar (string text) { + get_style_context ().add_class ("library-titlebar"); + + var title = new Gtk.Label (text); + title.get_style_context ().add_class ("h4"); + title.halign = Gtk.Align.CENTER; + title.margin = 4; + title.hexpand = true; + + this.add (title); + } + } + + public class ResponseMessage : Gtk.Label { + public ResponseMessage () { + get_style_context ().add_class ("h4"); + halign = Gtk.Align.CENTER; + valign = Gtk.Align.CENTER; + justify = Gtk.Justification.CENTER; + set_line_wrap (true); + margin_bottom = 10; + } + } + + public class Entry : Gtk.Entry { + public Entry (string? placeholder, string? val) { + hexpand = true; + + if (placeholder != null) { + placeholder_text = placeholder; + } + + if (val != null) { + text = val; + } + } + } + + public class ButtonClass : Gtk.Button { + public ButtonClass (string text, string* class) { + label = text; + + if (class != null) { + var style_context = this.get_style_context (); + style_context.add_class (class); + } + } + } + + public class TableRow : Gtk.Grid { + public TableRow (string text, int type) { + if (type % 2 == 0) { + get_style_context ().add_class ("row-odd"); + } else { + get_style_context ().add_class ("row-even"); + } + + var title = new Gtk.Label (text); + title.get_style_context ().add_class ("h4"); + title.halign = Gtk.Align.START; + title.margin_start = 6; + title.margin_end = 6; + title.hexpand = true; + + this.add (title); + } + } public class LabelForm : Gtk.Label { public LabelForm (string text) { @@ -124,4 +124,4 @@ namespace Sequeler.Partials { }); } } -} \ No newline at end of file +} diff --git a/src/Partials/LibraryItem.vala b/src/Partials/LibraryItem.vala index 6f9cccbf..c66a68c6 100644 --- a/src/Partials/LibraryItem.vala +++ b/src/Partials/LibraryItem.vala @@ -20,219 +20,219 @@ */ public class Sequeler.Partials.LibraryItem : Gtk.ListBoxRow { - public Gee.HashMap data { get; set; } - public Gtk.Label title; - public Gdk.RGBA color; + public Gee.HashMap data { get; set; } + public Gtk.Label title; + public Gdk.RGBA color; - public Gtk.Revealer main_revealer; - private Gtk.Revealer motion_revealer; - public Gtk.ModelButton connect_button; - public Gtk.Spinner spinner; + public Gtk.Revealer main_revealer; + private Gtk.Revealer motion_revealer; + public Gtk.ModelButton connect_button; + public Gtk.Spinner spinner; - public Gtk.ScrolledWindow scrolled { get; set; } - private bool scroll_up = false; + public Gtk.ScrolledWindow scrolled { get; set; } + private bool scroll_up = false; private bool scrolling = false; private bool should_scroll = false; - public Gtk.Adjustment vadjustment; + public Gtk.Adjustment vadjustment; - private const int SCROLL_STEP_SIZE = 5; + private const int SCROLL_STEP_SIZE = 5; private const int SCROLL_DISTANCE = 30; private const int SCROLL_DELAY = 50; - public signal void edit_dialog (Gee.HashMap data); - public signal void confirm_delete ( - Gtk.ListBoxRow item, - Gee.HashMap data - ); - public signal void connect_to ( - Gee.HashMap data, - Gtk.Spinner spinner, - Gtk.ModelButton button - ); - - // Datatype restrictions on DnD (Gtk.TargetFlags). - const Gtk.TargetEntry[] TARGET_ENTRIES_LABEL = { - { "LIBRARYITEM", Gtk.TargetFlags.SAME_APP, 0 } - }; - - public LibraryItem (Gee.HashMap data) { - Object ( - data: data - ); - - get_style_context ().add_class ("library-box"); - expand = true; - - var box = new Gtk.Grid (); - box.get_style_context ().add_class ("library-inner-box"); - box.margin = 3; - - var color_box = new Gtk.Grid (); - color_box.get_style_context ().add_class ("library-colorbox"); - color_box.set_size_request (12, 12); - color_box.margin = 9; - - color = Gdk.RGBA (); - color.parse (data["color"]); - try { - var style = new Gtk.CssProvider (); - style.load_from_data ( - "* {background-color: %s;}".printf (color.to_string ()), - -1 - ); - color_box.get_style_context ().add_provider ( - style, - Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - ); - } catch (Error e) { - debug ( - "Internal error loading session chooser style: %s", - e.message - ); - } - - title = new Gtk.Label (data["title"]); - title.get_style_context ().add_class ("text-bold"); - title.halign = Gtk.Align.START; - title.ellipsize = Pango.EllipsizeMode.END; - title.margin_end = 9; - title.set_line_wrap (true); - title.hexpand = true; - - box.attach (color_box, 0, 0, 1, 1); - box.attach (title, 1, 0, 1, 1); - - connect_button = new Gtk.ModelButton (); - connect_button.text = _("Connect"); - - var edit_button = new Gtk.ModelButton (); - edit_button.text = _("Edit Connection"); - - var delete_button = new Gtk.ModelButton (); - delete_button.text = _("Delete Connection"); - - var open_menu = new Gtk.MenuButton (); - open_menu.set_image ( - new Gtk.Image.from_icon_name ( - "view-more-symbolic", - Gtk.IconSize.SMALL_TOOLBAR - ) - ); - open_menu.get_style_context ().add_class ("library-btn"); - open_menu.tooltip_text = _("Options"); - - var menu_separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); - menu_separator.margin_top = 6; - menu_separator.margin_bottom = 6; - - var menu_grid = new Gtk.Grid (); - menu_grid.expand = true; - menu_grid.margin_top = 3; - menu_grid.margin_bottom = 3; - menu_grid.orientation = Gtk.Orientation.VERTICAL; - - menu_grid.attach (connect_button, 0, 1, 1, 1); - menu_grid.attach (edit_button, 0, 2, 1, 1); - menu_grid.attach (menu_separator, 0, 3, 1, 1); - menu_grid.attach (delete_button, 0, 4, 1, 1); - menu_grid.show_all (); - - var menu_popover = new Gtk.Popover (null); - menu_popover.add (menu_grid); - - open_menu.popover = menu_popover; - open_menu.relief = Gtk.ReliefStyle.NONE; - open_menu.valign = Gtk.Align.CENTER; - - spinner = new Gtk.Spinner (); - - box.attach (spinner, 2, 0, 1, 1); - box.attach (open_menu, 3, 0, 1, 1); - - var motion_grid = new Gtk.Grid (); + public signal void edit_dialog (Gee.HashMap data); + public signal void confirm_delete ( + Gtk.ListBoxRow item, + Gee.HashMap data + ); + public signal void connect_to ( + Gee.HashMap data, + Gtk.Spinner spinner, + Gtk.ModelButton button + ); + + // Datatype restrictions on DnD (Gtk.TargetFlags). + const Gtk.TargetEntry[] TARGET_ENTRIES_LABEL = { + { "LIBRARYITEM", Gtk.TargetFlags.SAME_APP, 0 } + }; + + public LibraryItem (Gee.HashMap data) { + Object ( + data: data + ); + + get_style_context ().add_class ("library-box"); + expand = true; + + var box = new Gtk.Grid (); + box.get_style_context ().add_class ("library-inner-box"); + box.margin = 3; + + var color_box = new Gtk.Grid (); + color_box.get_style_context ().add_class ("library-colorbox"); + color_box.set_size_request (12, 12); + color_box.margin = 9; + + color = Gdk.RGBA (); + color.parse (data["color"]); + try { + var style = new Gtk.CssProvider (); + style.load_from_data ( + "* {background-color: %s;}".printf (color.to_string ()), + -1 + ); + color_box.get_style_context ().add_provider ( + style, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION + ); + } catch (Error e) { + debug ( + "Internal error loading session chooser style: %s", + e.message + ); + } + + title = new Gtk.Label (data["title"]); + title.get_style_context ().add_class ("text-bold"); + title.halign = Gtk.Align.START; + title.ellipsize = Pango.EllipsizeMode.END; + title.margin_end = 9; + title.set_line_wrap (true); + title.hexpand = true; + + box.attach (color_box, 0, 0, 1, 1); + box.attach (title, 1, 0, 1, 1); + + connect_button = new Gtk.ModelButton (); + connect_button.text = _("Connect"); + + var edit_button = new Gtk.ModelButton (); + edit_button.text = _("Edit Connection"); + + var delete_button = new Gtk.ModelButton (); + delete_button.text = _("Delete Connection"); + + var open_menu = new Gtk.MenuButton (); + open_menu.set_image ( + new Gtk.Image.from_icon_name ( + "view-more-symbolic", + Gtk.IconSize.SMALL_TOOLBAR + ) + ); + open_menu.get_style_context ().add_class ("library-btn"); + open_menu.tooltip_text = _("Options"); + + var menu_separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); + menu_separator.margin_top = 6; + menu_separator.margin_bottom = 6; + + var menu_grid = new Gtk.Grid (); + menu_grid.expand = true; + menu_grid.margin_top = 3; + menu_grid.margin_bottom = 3; + menu_grid.orientation = Gtk.Orientation.VERTICAL; + + menu_grid.attach (connect_button, 0, 1, 1, 1); + menu_grid.attach (edit_button, 0, 2, 1, 1); + menu_grid.attach (menu_separator, 0, 3, 1, 1); + menu_grid.attach (delete_button, 0, 4, 1, 1); + menu_grid.show_all (); + + var menu_popover = new Gtk.Popover (null); + menu_popover.add (menu_grid); + + open_menu.popover = menu_popover; + open_menu.relief = Gtk.ReliefStyle.NONE; + open_menu.valign = Gtk.Align.CENTER; + + spinner = new Gtk.Spinner (); + + box.attach (spinner, 2, 0, 1, 1); + box.attach (open_menu, 3, 0, 1, 1); + + var motion_grid = new Gtk.Grid (); motion_grid.margin = 6; motion_grid.get_style_context ().add_class ("grid-motion"); motion_grid.height_request = 18; motion_revealer = new Gtk.Revealer (); motion_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN; - motion_revealer.add (motion_grid); + motion_revealer.add (motion_grid); - box.attach (motion_revealer, 0, 1, 4, 1); + box.attach (motion_revealer, 0, 1, 4, 1); - var event_box = new Gtk.EventBox (); - event_box.add (box); + var event_box = new Gtk.EventBox (); + event_box.add (box); - main_revealer = new Gtk.Revealer (); + main_revealer = new Gtk.Revealer (); main_revealer.reveal_child = true; main_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN; main_revealer.add (event_box); add (main_revealer); - delete_button.clicked.connect (() => { - confirm_delete (this, data); - }); - - edit_button.clicked.connect (() => { - edit_dialog (data); - }); - - connect_button.clicked.connect (() => { - spinner.start (); - connect_button.sensitive = false; - connect_to (data, spinner, connect_button); - }); - - event_box.enter_notify_event.connect (event => { - box.set_state_flags (Gtk.StateFlags.PRELIGHT, true); - return false; - }); - - event_box.leave_notify_event.connect (event => { - if (event.detail != Gdk.NotifyType.INFERIOR) { - box.set_state_flags (Gtk.StateFlags.NORMAL, true); - } - return false; - }); - - open_menu.clicked.connect (event => { - box.set_state_flags (Gtk.StateFlags.PRELIGHT, true); - }); - - menu_popover.closed.connect (event => { - box.set_state_flags (Gtk.StateFlags.NORMAL, true); - }); - - build_drag_and_drop (); - } - - private void build_drag_and_drop () { - // Make this a draggable widget - Gtk.drag_source_set ( - this, - Gdk.ModifierType.BUTTON1_MASK, - TARGET_ENTRIES_LABEL, - Gdk.DragAction.MOVE - ); - - drag_begin.connect (on_drag_begin); - drag_data_get.connect (on_drag_data_get); - - // Make this widget a DnD destination. + delete_button.clicked.connect (() => { + confirm_delete (this, data); + }); + + edit_button.clicked.connect (() => { + edit_dialog (data); + }); + + connect_button.clicked.connect (() => { + spinner.start (); + connect_button.sensitive = false; + connect_to (data, spinner, connect_button); + }); + + event_box.enter_notify_event.connect (event => { + box.set_state_flags (Gtk.StateFlags.PRELIGHT, true); + return false; + }); + + event_box.leave_notify_event.connect (event => { + if (event.detail != Gdk.NotifyType.INFERIOR) { + box.set_state_flags (Gtk.StateFlags.NORMAL, true); + } + return false; + }); + + open_menu.clicked.connect (event => { + box.set_state_flags (Gtk.StateFlags.PRELIGHT, true); + }); + + menu_popover.closed.connect (event => { + box.set_state_flags (Gtk.StateFlags.NORMAL, true); + }); + + build_drag_and_drop (); + } + + private void build_drag_and_drop () { + // Make this a draggable widget + Gtk.drag_source_set ( + this, + Gdk.ModifierType.BUTTON1_MASK, + TARGET_ENTRIES_LABEL, + Gdk.DragAction.MOVE + ); + + drag_begin.connect (on_drag_begin); + drag_data_get.connect (on_drag_data_get); + + // Make this widget a DnD destination. Gtk.drag_dest_set ( - this, - Gtk.DestDefaults.MOTION, - TARGET_ENTRIES_LABEL, - Gdk.DragAction.MOVE - ); + this, + Gtk.DestDefaults.MOTION, + TARGET_ENTRIES_LABEL, + Gdk.DragAction.MOVE + ); - drag_motion.connect (on_drag_motion); + drag_motion.connect (on_drag_motion); drag_leave.connect (on_drag_leave); drag_end.connect (clear_indicator); - } + } - private void on_drag_begin (Gtk.Widget widget, Gdk.DragContext context) { + private void on_drag_begin (Gtk.Widget widget, Gdk.DragContext context) { var row = (Partials.LibraryItem) widget; Gtk.Allocation alloc; @@ -257,9 +257,9 @@ public class Sequeler.Partials.LibraryItem : Gtk.ListBoxRow { row.draw (cr); Gtk.drag_set_icon_surface (context, surface); main_revealer.reveal_child = false; - } + } - private void on_drag_data_get (Gtk.Widget widget, Gdk.DragContext context, + private void on_drag_data_get (Gtk.Widget widget, Gdk.DragContext context, Gtk.SelectionData selection_data, uint target_type, uint time) { uchar[] data = new uchar[(sizeof (Partials.LibraryItem))]; ((Gtk.Widget[])data)[0] = widget; @@ -267,13 +267,13 @@ public class Sequeler.Partials.LibraryItem : Gtk.ListBoxRow { selection_data.set ( Gdk.Atom.intern_static_string ("LIBRARYITEM"), 32, data ); - } + } - public void clear_indicator (Gdk.DragContext context) { + public void clear_indicator (Gdk.DragContext context) { main_revealer.reveal_child = true; - } + } - public bool on_drag_motion (Gdk.DragContext context, int x, int y, uint time) { + public bool on_drag_motion (Gdk.DragContext context, int x, int y, uint time) { motion_revealer.reveal_child = true; int index = get_index (); diff --git a/src/Partials/TreeBuilder.vala b/src/Partials/TreeBuilder.vala index 868f5f8b..ebae7387 100644 --- a/src/Partials/TreeBuilder.vala +++ b/src/Partials/TreeBuilder.vala @@ -20,166 +20,166 @@ */ public class Sequeler.Partials.TreeBuilder : Gtk.TreeView { - public weak Sequeler.Window window { get; construct; } - public Gda.DataModel data { get; construct; } - public int per_page { get; construct; } - public int current_page { get; construct; } - public Gtk.ListStore store; - public string? error_message { get; set; default = null; } - public string background; - public int tot_columns; - - private string bg_light = "rgba(255,255,255,0.05)"; - private string bg_dark = "rgba(0,0,0,0.05)"; - - public TreeBuilder (Gda.DataModel response, Sequeler.Window main_window, int per_page = 0, int current_page = 0) { - Object ( - window: main_window, - data: response, - per_page: per_page, - current_page: current_page - ); - } - - construct { - Gtk.TreeViewColumn column; - var renderer = new Gtk.CellRendererText (); - renderer.single_paragraph_mode = true; - - tot_columns = data.get_n_columns (); - - var theTypes = new GLib.Type[tot_columns+1]; - for (int col = 0; col < tot_columns; col++) { - theTypes[col] = data.describe_column (col).get_g_type (); - - var title = data.get_column_title (col).replace ("_", "__"); - column = new Gtk.TreeViewColumn.with_attributes (title, renderer, "text", col, "background", tot_columns, null); - column.clickable = true; - column.resizable = true; - column.expand = true; - column.sort_column_id = col; - if (col > 0) { - column.sizing = Gtk.TreeViewColumnSizing.FIXED; - column.fixed_width = 150; - } - - column.clicked.connect (redraw); - append_column (column); - } - - theTypes[tot_columns] = typeof (string); - - store = new Gtk.ListStore.newv (theTypes); - Gda.DataModelIter _iter = data.create_iter (); - Gtk.TreeIter iter; - - if (per_page != 0 && data.get_n_rows () > per_page) { - int counter = 1; - int offset = (per_page * (current_page - 1)); - - if (current_page != 0 && offset != 0) { - _iter.move_to_row ((offset - 1)); - } - - while (counter <= per_page && _iter.move_next ()) { - append_value (_iter, iter); - counter++; - } - } else { - while (_iter.move_next ()) { - append_value (_iter, iter); - } - } - - if (error_message != null) { - window.main.connection_manager.query_warning (error_message); - error_message = null; - } - - set_model (store); - } - - private void append_value (Gda.DataModelIter _iter, Gtk.TreeIter iter) { - background = _iter.get_row () % 2 == 0 ? bg_light : bg_dark; - store.append (out iter); - - for (int i = 0; i < tot_columns; i++) { - var placeholder_type = data.describe_column (i).get_g_type (); - - try { - var raw_value = _iter.get_value_at_e (i); - var sanitized_value = raw_value.strdup_contents () != "NULL" ? - raw_value : GLib.Value (placeholder_type); - - store.set_value (iter, i, sanitized_value); - } catch (Error e) { - error_message = "%s %s %s %s: %s".printf (_("Error"), e.code.to_string (), _("on Column"), data.get_column_title (i), e.message.to_string ()); - } - } - store.set_value (iter, tot_columns, background); - } - - public void redraw () { - Gtk.TreeIter iter; - var i = 0; - - for (bool next = store.get_iter_first (out iter); next; next = store.iter_next (ref iter)) { - background = i % 2 == 0 ? bg_light : bg_dark; - store.set_value (iter, tot_columns, background); - i++; - } - } - - private void copy_column_data (Gdk.EventButton event, Gtk.TreePath path, Gtk.TreeViewColumn column) { - if (path == null || column == null) { - return; - } - - Value val; - Gtk.TreeIter iter; - - Gdk.Display display = Gdk.Display.get_default (); - Gtk.Clipboard clipboard = Gtk.Clipboard.get_default (display); - model.get_iter (out iter, path); - model.get_value (iter, column.get_sort_column_id (), out val); - - Gda.DataHandler handler = Gda.DataHandler.get_default (val.type ()); - string? column_data = handler.get_str_from_value (val); - - if (column_data == null) { - column_data = ""; - } - - clipboard.set_text (column_data, -1); - } - - private Gtk.Menu create_context_menu (Gdk.EventButton event, Gtk.TreePath path, Gtk.TreeViewColumn column) { - Gtk.Menu menu = new Gtk.Menu (); - Gtk.MenuItem item = new Gtk.MenuItem.with_label (_("Copy %s").printf (column.get_title ())); - item.activate.connect (() => { copy_column_data (event, path, column); }); - item.show (); - menu.append (item); - - /* Wayland complains if not set */ - menu.realize.connect (() => { - Gdk.Window child = menu.get_window (); - child.set_type_hint (Gdk.WindowTypeHint.POPUP_MENU); - }); - - return menu; - } - - public override bool button_press_event (Gdk.EventButton event) { - if (event.triggers_context_menu () && event.type == Gdk.EventType.BUTTON_PRESS) { - Gtk.TreePath path; - Gtk.TreeViewColumn column; - get_path_at_pos ((int) event.x, (int) event.y, out path, out column, null, null); - var menu = create_context_menu (event, path, column); - menu.popup_at_pointer (event); - - return true; - } - - return base.button_press_event (event); - } + public weak Sequeler.Window window { get; construct; } + public Gda.DataModel data { get; construct; } + public int per_page { get; construct; } + public int current_page { get; construct; } + public Gtk.ListStore store; + public string? error_message { get; set; default = null; } + public string background; + public int tot_columns; + + private string bg_light = "rgba(255,255,255,0.05)"; + private string bg_dark = "rgba(0,0,0,0.05)"; + + public TreeBuilder (Gda.DataModel response, Sequeler.Window main_window, int per_page = 0, int current_page = 0) { + Object ( + window: main_window, + data: response, + per_page: per_page, + current_page: current_page + ); + } + + construct { + Gtk.TreeViewColumn column; + var renderer = new Gtk.CellRendererText (); + renderer.single_paragraph_mode = true; + + tot_columns = data.get_n_columns (); + + var the_types = new GLib.Type [tot_columns + 1]; + for (int col = 0; col < tot_columns; col++) { + the_types[col] = data.describe_column (col).get_g_type (); + + var title = data.get_column_title (col).replace ("_", "__"); + column = new Gtk.TreeViewColumn.with_attributes (title, renderer, "text", col, "background", tot_columns, null); + column.clickable = true; + column.resizable = true; + column.expand = true; + column.sort_column_id = col; + if (col > 0) { + column.sizing = Gtk.TreeViewColumnSizing.FIXED; + column.fixed_width = 150; + } + + column.clicked.connect (redraw); + append_column (column); + } + + the_types[tot_columns] = typeof (string); + + store = new Gtk.ListStore.newv (the_types); + Gda.DataModelIter _iter = data.create_iter (); + Gtk.TreeIter iter; + + if (per_page != 0 && data.get_n_rows () > per_page) { + int counter = 1; + int offset = (per_page * (current_page - 1)); + + if (current_page != 0 && offset != 0) { + _iter.move_to_row ((offset - 1)); + } + + while (counter <= per_page && _iter.move_next ()) { + append_value (_iter, iter); + counter++; + } + } else { + while (_iter.move_next ()) { + append_value (_iter, iter); + } + } + + if (error_message != null) { + window.main.connection_manager.query_warning (error_message); + error_message = null; + } + + set_model (store); + } + + private void append_value (Gda.DataModelIter _iter, Gtk.TreeIter iter) { + background = _iter.get_row () % 2 == 0 ? bg_light : bg_dark; + store.append (out iter); + + for (int i = 0; i < tot_columns; i++) { + var placeholder_type = data.describe_column (i).get_g_type (); + + try { + var raw_value = _iter.get_value_at_e (i); + var sanitized_value = raw_value.strdup_contents () != "NULL" ? + raw_value : GLib.Value (placeholder_type); + + store.set_value (iter, i, sanitized_value); + } catch (Error e) { + error_message = "%s %s %s %s: %s".printf (_("Error"), e.code.to_string (), _("on Column"), data.get_column_title (i), e.message.to_string ()); + } + } + store.set_value (iter, tot_columns, background); + } + + public void redraw () { + Gtk.TreeIter iter; + var i = 0; + + for (bool next = store.get_iter_first (out iter); next; next = store.iter_next (ref iter)) { + background = i % 2 == 0 ? bg_light : bg_dark; + store.set_value (iter, tot_columns, background); + i++; + } + } + + private void copy_column_data (Gdk.EventButton event, Gtk.TreePath path, Gtk.TreeViewColumn column) { + if (path == null || column == null) { + return; + } + + Value val; + Gtk.TreeIter iter; + + Gdk.Display display = Gdk.Display.get_default (); + Gtk.Clipboard clipboard = Gtk.Clipboard.get_default (display); + model.get_iter (out iter, path); + model.get_value (iter, column.get_sort_column_id (), out val); + + Gda.DataHandler handler = Gda.DataHandler.get_default (val.type ()); + string? column_data = handler.get_str_from_value (val); + + if (column_data == null) { + column_data = ""; + } + + clipboard.set_text (column_data, -1); + } + + private Gtk.Menu create_context_menu (Gdk.EventButton event, Gtk.TreePath path, Gtk.TreeViewColumn column) { + Gtk.Menu menu = new Gtk.Menu (); + Gtk.MenuItem item = new Gtk.MenuItem.with_label (_("Copy %s").printf (column.get_title ())); + item.activate.connect (() => { copy_column_data (event, path, column); }); + item.show (); + menu.append (item); + + /* Wayland complains if not set */ + menu.realize.connect (() => { + Gdk.Window child = menu.get_window (); + child.set_type_hint (Gdk.WindowTypeHint.POPUP_MENU); + }); + + return menu; + } + + public override bool button_press_event (Gdk.EventButton event) { + if (event.triggers_context_menu () && event.type == Gdk.EventType.BUTTON_PRESS) { + Gtk.TreePath path; + Gtk.TreeViewColumn column; + get_path_at_pos ((int) event.x, (int) event.y, out path, out column, null, null); + var menu = create_context_menu (event, path, column); + menu.popup_at_pointer (event); + + return true; + } + + return base.button_press_event (event); + } } diff --git a/src/Services/ActionManager.vala b/src/Services/ActionManager.vala index be83bf07..68d9b3fc 100644 --- a/src/Services/ActionManager.vala +++ b/src/Services/ActionManager.vala @@ -20,209 +20,209 @@ */ public class Sequeler.Services.ActionManager : Object { - public int FONT_SIZE_MAX = 72; - public int FONT_SIZE_MIN = 7; - - public weak Sequeler.Application app { get; construct; } - public weak Sequeler.Window window { get; construct; } - - public SimpleActionGroup actions { get; construct; } - - public const string ACTION_PREFIX = "win."; - public const string ACTION_NEW_WINDOW = "action_new_window"; - public const string ACTION_NEW_CONNECTION = "action_new_connection"; - public const string ACTION_RUN_QUERY = "action_run_query"; - public const string ACTION_LOGOUT = "action_logout"; - public const string ACTION_QUIT = "action_quit"; - public const string ACTION_ZOOM_DEFAULT = "action_zoom_default"; - public const string ACTION_ZOOM_IN = "action_zoom_in"; - public const string ACTION_ZOOM_OUT = "action_zoom_out"; - - public static Gee.MultiMap action_accelerators = new Gee.HashMultiMap (); - - private const ActionEntry[] action_entries = { - { ACTION_NEW_WINDOW, action_new_window }, - { ACTION_NEW_CONNECTION, action_new_connection }, - { ACTION_RUN_QUERY, action_run_query }, - { ACTION_LOGOUT, action_logout }, - { ACTION_QUIT, action_quit }, - { ACTION_ZOOM_DEFAULT, action_set_default_zoom }, - { ACTION_ZOOM_IN, action_zoom_in }, - { ACTION_ZOOM_OUT, action_zoom_out} - }; - - public ActionManager (Sequeler.Application sequeler_app, Sequeler.Window main_window) { - Object ( - app: sequeler_app, - window: main_window - ); - } - - static construct { - action_accelerators.set (ACTION_NEW_WINDOW, "n"); - action_accelerators.set (ACTION_NEW_CONNECTION, "n"); - action_accelerators.set (ACTION_RUN_QUERY, "Return"); - action_accelerators.set (ACTION_LOGOUT, "Escape"); - action_accelerators.set (ACTION_QUIT, "q"); - action_accelerators.set (ACTION_ZOOM_DEFAULT, "0"); - action_accelerators.set (ACTION_ZOOM_DEFAULT, "KP_0"); - action_accelerators.set (ACTION_ZOOM_IN, "plus"); - action_accelerators.set (ACTION_ZOOM_IN, "equal"); - action_accelerators.set (ACTION_ZOOM_IN, "KP_Add"); - action_accelerators.set (ACTION_ZOOM_OUT, "minus"); - action_accelerators.set (ACTION_ZOOM_OUT, "KP_Subtract"); - } - - construct { - actions = new SimpleActionGroup (); - actions.add_action_entries (action_entries, this); - window.insert_action_group ("win", actions); - - foreach (var action in action_accelerators.get_keys ()) { - var accels_array = action_accelerators[action].to_array (); - accels_array += null; - - app.set_accels_for_action (ACTION_PREFIX + action, accels_array); - } - } - - private void action_quit () { - window.before_destroy (); - } - - private void action_logout () { - window.headerbar.toggle_logout.begin (); - window.headerbar.title = APP_NAME; - window.headerbar.subtitle = null; - - if (window.main.database_schema.scroll.get_child () != null) { - window.main.database_schema.scroll.remove (window.main.database_schema.scroll.get_child ()); - } - - window.main.database_view.query.buffer.text = ""; - window.main.database_view.query.export_button.sensitive = false; - - window.main.database_view.structure.reset.begin (); - window.main.database_view.structure.table_name = ""; - - window.main.database_view.content.reset.begin (); - window.main.database_view.content.table_name = ""; - - window.main.database_view.relations.reset.begin (); - window.main.database_view.relations.table_name = ""; - - window.main.connection_closed (); - window.data_manager.data = null; - } - - private void action_new_window () { - app.new_window (); - } - - private void action_new_connection () { - if (window.main.connection_manager != null) { - return; - } - - window.data_manager.data = null; - - if (window.connection_dialog == null) { - window.connection_dialog = new Sequeler.Widgets.ConnectionDialog (window); - window.connection_dialog.show_all (); - - window.connection_dialog.destroy.connect (() => { - window.connection_dialog = null; - }); - } - - window.connection_dialog.present (); - } - - private void action_run_query () { - if (window.main.connection_manager == null) { - return; - } - - var query = window.main.database_view.query.get_text ().strip (); - - if (query == "") { - return; - } - - window.main.database_view.query.run_query (query); - } - - public static void action_from_group (string action_name, ActionGroup? action_group) { - action_group.activate_action (action_name, null); - } - - public void set_default_zoom () { - Sequeler.settings.font = get_current_font () + " " + get_default_font_size ().to_string (); - window.main.database_view.query.update_font_style (); - } - - // Ctrl + scroll - public void action_zoom_in () { - zooming (Gdk.ScrollDirection.UP); - } - - // Ctrl + scroll - public void action_zoom_out () { - zooming (Gdk.ScrollDirection.DOWN); - } - - private void zooming (Gdk.ScrollDirection direction) { - string font = get_current_font (); - int font_size = (int) get_current_font_size (); - if (Sequeler.settings.use_system_font) { - Sequeler.settings.use_system_font = false; - font = get_default_font (); - font_size = (int) get_default_font_size (); - } - - if (direction == Gdk.ScrollDirection.DOWN) { - font_size --; - if (font_size < FONT_SIZE_MIN) { - return; - } - } else if (direction == Gdk.ScrollDirection.UP) { - font_size ++; - if (font_size > FONT_SIZE_MAX) { - return; - } - } - - string new_font = font + " " + font_size.to_string (); - Sequeler.settings.font = new_font; - window.main.database_view.query.update_font_style (); - } - - public string get_current_font () { - string font = Sequeler.settings.font; - string font_family = font.substring (0, font.last_index_of (" ")); - return font_family; - } - - public double get_current_font_size () { - string font = Sequeler.settings.font; - string font_size = font.substring (font.last_index_of (" ") + 1); - return double.parse (font_size); - } - - public string get_default_font () { - string font = window.main.database_view.query.default_font; - string font_family = font.substring (0, font.last_index_of (" ")); - return font_family; - } - - public double get_default_font_size () { - string font = window.main.database_view.query.default_font; - string font_size = font.substring (font.last_index_of (" ") + 1); - return double.parse (font_size); - } - - // Actions functions - private void action_set_default_zoom () { - set_default_zoom (); - } + public const int FONT_SIZE_MAX = 72; + public const int FONT_SIZE_MIN = 7; + + public weak Sequeler.Application app { get; construct; } + public weak Sequeler.Window window { get; construct; } + + public SimpleActionGroup actions { get; construct; } + + public const string ACTION_PREFIX = "win."; + public const string ACTION_NEW_WINDOW = "action_new_window"; + public const string ACTION_NEW_CONNECTION = "action_new_connection"; + public const string ACTION_RUN_QUERY = "action_run_query"; + public const string ACTION_LOGOUT = "action_logout"; + public const string ACTION_QUIT = "action_quit"; + public const string ACTION_ZOOM_DEFAULT = "action_zoom_default"; + public const string ACTION_ZOOM_IN = "action_zoom_in"; + public const string ACTION_ZOOM_OUT = "action_zoom_out"; + + public static Gee.MultiMap action_accelerators = new Gee.HashMultiMap (); + + private const ActionEntry[] ACTION_ENTRIES = { + { ACTION_NEW_WINDOW, action_new_window }, + { ACTION_NEW_CONNECTION, action_new_connection }, + { ACTION_RUN_QUERY, action_run_query }, + { ACTION_LOGOUT, action_logout }, + { ACTION_QUIT, action_quit }, + { ACTION_ZOOM_DEFAULT, action_set_default_zoom }, + { ACTION_ZOOM_IN, action_zoom_in }, + { ACTION_ZOOM_OUT, action_zoom_out} + }; + + public ActionManager (Sequeler.Application sequeler_app, Sequeler.Window main_window) { + Object ( + app: sequeler_app, + window: main_window + ); + } + + static construct { + action_accelerators.set (ACTION_NEW_WINDOW, "n"); + action_accelerators.set (ACTION_NEW_CONNECTION, "n"); + action_accelerators.set (ACTION_RUN_QUERY, "Return"); + action_accelerators.set (ACTION_LOGOUT, "Escape"); + action_accelerators.set (ACTION_QUIT, "q"); + action_accelerators.set (ACTION_ZOOM_DEFAULT, "0"); + action_accelerators.set (ACTION_ZOOM_DEFAULT, "KP_0"); + action_accelerators.set (ACTION_ZOOM_IN, "plus"); + action_accelerators.set (ACTION_ZOOM_IN, "equal"); + action_accelerators.set (ACTION_ZOOM_IN, "KP_Add"); + action_accelerators.set (ACTION_ZOOM_OUT, "minus"); + action_accelerators.set (ACTION_ZOOM_OUT, "KP_Subtract"); + } + + construct { + actions = new SimpleActionGroup (); + actions.add_action_entries (ACTION_ENTRIES, this); + window.insert_action_group ("win", actions); + + foreach (var action in action_accelerators.get_keys ()) { + var accels_array = action_accelerators[action].to_array (); + accels_array += null; + + app.set_accels_for_action (ACTION_PREFIX + action, accels_array); + } + } + + private void action_quit () { + window.before_destroy (); + } + + private void action_logout () { + window.headerbar.toggle_logout.begin (); + window.headerbar.title = APP_NAME; + window.headerbar.subtitle = null; + + if (window.main.database_schema.scroll.get_child () != null) { + window.main.database_schema.scroll.remove (window.main.database_schema.scroll.get_child ()); + } + + window.main.database_view.query.buffer.text = ""; + window.main.database_view.query.export_button.sensitive = false; + + window.main.database_view.structure.reset.begin (); + window.main.database_view.structure.table_name = ""; + + window.main.database_view.content.reset.begin (); + window.main.database_view.content.table_name = ""; + + window.main.database_view.relations.reset.begin (); + window.main.database_view.relations.table_name = ""; + + window.main.connection_closed (); + window.data_manager.data = null; + } + + private void action_new_window () { + app.new_window (); + } + + private void action_new_connection () { + if (window.main.connection_manager != null) { + return; + } + + window.data_manager.data = null; + + if (window.connection_dialog == null) { + window.connection_dialog = new Sequeler.Widgets.ConnectionDialog (window); + window.connection_dialog.show_all (); + + window.connection_dialog.destroy.connect (() => { + window.connection_dialog = null; + }); + } + + window.connection_dialog.present (); + } + + private void action_run_query () { + if (window.main.connection_manager == null) { + return; + } + + var query = window.main.database_view.query.get_text ().strip (); + + if (query == "") { + return; + } + + window.main.database_view.query.run_query (query); + } + + public static void action_from_group (string action_name, ActionGroup? action_group) { + action_group.activate_action (action_name, null); + } + + public void set_default_zoom () { + Sequeler.settings.font = get_current_font () + " " + get_default_font_size ().to_string (); + window.main.database_view.query.update_font_style (); + } + + // Ctrl + scroll + public void action_zoom_in () { + zooming (Gdk.ScrollDirection.UP); + } + + // Ctrl + scroll + public void action_zoom_out () { + zooming (Gdk.ScrollDirection.DOWN); + } + + private void zooming (Gdk.ScrollDirection direction) { + string font = get_current_font (); + int font_size = (int) get_current_font_size (); + if (Sequeler.settings.use_system_font) { + Sequeler.settings.use_system_font = false; + font = get_default_font (); + font_size = (int) get_default_font_size (); + } + + if (direction == Gdk.ScrollDirection.DOWN) { + font_size --; + if (font_size < FONT_SIZE_MIN) { + return; + } + } else if (direction == Gdk.ScrollDirection.UP) { + font_size ++; + if (font_size > FONT_SIZE_MAX) { + return; + } + } + + string new_font = font + " " + font_size.to_string (); + Sequeler.settings.font = new_font; + window.main.database_view.query.update_font_style (); + } + + public string get_current_font () { + string font = Sequeler.settings.font; + string font_family = font.substring (0, font.last_index_of (" ")); + return font_family; + } + + public double get_current_font_size () { + string font = Sequeler.settings.font; + string font_size = font.substring (font.last_index_of (" ") + 1); + return double.parse (font_size); + } + + public string get_default_font () { + string font = window.main.database_view.query.default_font; + string font_family = font.substring (0, font.last_index_of (" ")); + return font_family; + } + + public double get_default_font_size () { + string font = window.main.database_view.query.default_font; + string font_size = font.substring (font.last_index_of (" ") + 1); + return double.parse (font_size); + } + + // Actions functions + private void action_set_default_zoom () { + set_default_zoom (); + } } diff --git a/src/Services/ConnectionManager.vala b/src/Services/ConnectionManager.vala index 84b79a16..3802bf2e 100644 --- a/src/Services/ConnectionManager.vala +++ b/src/Services/ConnectionManager.vala @@ -20,511 +20,511 @@ */ public class Sequeler.Services.ConnectionManager : Object { - public weak Sequeler.Window window { get; construct; } - public Gee.HashMap data { get; construct; } - private Object _db_type; + public weak Sequeler.Window window { get; construct; } + public Gee.HashMap data { get; construct; } + private Object _db_type; - public signal void ssh_tunnel_ready (); + public signal void ssh_tunnel_ready (); - public Object db_type { - get { return _db_type; } - set { _db_type = value; } - } + public Object db_type { + get { return _db_type; } + set { _db_type = value; } + } - public Gda.Connection? connection { get; set; default = null; } - public Gda.DataModel? output_select; + public Gda.Connection? connection { get; set; default = null; } + public Gda.DataModel? output_select; - public SSH2.Session session; - int sock; - int listensock; - int forwardsock; - bool ssh_tunnel_alive = false; + public SSH2.Session session; + int sock; + int listensock; + int forwardsock; + bool ssh_tunnel_alive = false; [Flags] - enum Auth { - NONE, - PASSWORD, - PUBLICKEY - } - - public ConnectionManager (Sequeler.Window window, Gee.HashMap data) { - Object ( - window: window, - data: data - ); - } - - construct { - switch (data["type"]) { - case "MySQL": - db_type = new Sequeler.Services.Types.MySQL (); - break; - case "MariaDB": - db_type = new Sequeler.Services.Types.MySQL (); - break; - case "PostgreSQL": - db_type = new Sequeler.Services.Types.PostgreSQL (); - break; - case "SQLite": - db_type = new Sequeler.Services.Types.SQLite (); - break; - } - - fetch_password (); - } - - public void fetch_password () { - if (data["password"] == null) { - data["password"] = ""; - - var loop = new MainLoop (); - password_mngr.get_password_async.begin (data["id"], (obj, res) => { - try { - data["password"] = password_mngr.get_password_async.end (res); - } catch (Error e) { - debug ("Unable to get the password from libsecret"); - } - loop.quit (); - }); - - loop.run (); - } - - if (data["has_ssh"] == "true") { - data["ssh_password"] = ""; - - var ssh_loop = new MainLoop (); - password_mngr.get_password_async.begin (data["id"] + "9999", (obj, res) => { - try { - data["ssh_password"] = password_mngr.get_password_async.end (res); - } catch (Error e) { - debug ("Unable to get the SSH password from libsecret"); - } - ssh_loop.quit (); - }); - - ssh_loop.run (); - } - } - - public void test () throws Error { - if (data["password"] == null) { - fetch_password (); - } - - var connection_string = (db_type as DataBaseType).connection_string (data); - debug ("connection string %s", connection_string); - - try { - connection = Gda.Connection.open_from_string (null, connection_string, null, Gda.ConnectionOptions.NONE); - } catch (Error e) { - throw e; - } - - if (connection.is_opened ()) { - connection.close (); - } - } - - public void open () throws Error { - if (data["password"] == null) { - fetch_password (); - } - - var connection_string = (db_type as DataBaseType).connection_string (data); - debug ("connection string %s", connection_string); - - try { - connection = Gda.Connection.open_from_string (null, connection_string, null, Gda.ConnectionOptions.NONE); - } catch (Error e) { - throw e; - } - debug ("open ends"); - } - - public void ssh_tunnel_init (bool is_real) throws Error { - try { - ssh_tunnel_open (is_real); - } catch (Error e) { - debug (e.message); - throw e; - } - } - - private void ssh_tunnel_open (bool is_real) throws Error { - debug ("Opening tunnel %p", Thread.self ()); - - ssh_tunnel_alive = true; - - Quark q = Quark.from_string ("ssh-error-str"); - var home_dir = Environment.get_home_dir (); - - // private key file - var keyfile2 = home_dir + "/.ssh/id_rsa"; - if (data.has_key("ssh_identity_file") && data["ssh_identity_file"] != "") { - keyfile2 = data["ssh_identity_file"]; - } - - // public key file - var keyfile1 = keyfile2 + ".pub"; - - - // SSH credentials if password authentication is required - var username = data["ssh_username"]; - var password = data["ssh_password"]; - - // SSH HOST address and Port - var server_ip = data["ssh_host"]; - var server_port = data["ssh_port"] != "" ? (uint16) int.parse (data["ssh_port"]) : 22; - - // The IP address where the DB is available on your SSH - var local_listenip = "127.0.0.1"; - - // The Port used by the DB on your SSH host - uint16 local_listenport = 9000; - - // Default vars for TCPIP Tunnelling - var remote_desthost = data["host"] != "" ? data["host"] : "127.0.0.1"; - var remote_destport = data["port"] != "" ? int.parse (data["port"]) : 3306; - - var rc = SSH2.init (0); - if (rc != SSH2.Error.NONE) { - debug ("libssh2 initialization failed (%d)", rc); - throw new Error.literal (q, 1, _("Libssh2 initialization failed (%d)").printf (rc)); - } - - debug ("Socket params: %s %d", server_ip, server_port); - - /* Connect to SSH server */ - sock = Posix.socket (Posix.AF_INET, Posix.SOCK_STREAM, Posix.IPProto.TCP); - if (sock == -1) { - debug ("Failed to open socket"); - throw new Error.literal (q, 1, _("Failed to open socket")); - } - - Posix.SockAddrIn sin = Posix.SockAddrIn(); - sin.sin_family = Posix.AF_INET; - sin.sin_addr.s_addr = Posix.inet_addr (server_ip); - sin.sin_port = Posix.htons (server_port); - if (Posix.connect (sock, &sin, sizeof (Posix.SockAddrIn)) != 0) { - debug ("Failed to connect!"); - throw new Error.literal (q, 1, _("Failed to connect!")); - } - - /* Create a session instance */ - session = SSH2.Session.create (); - - /* ... start it up. This will trade welcome banners, exchange keys, - * and setup crypto, compression, and MAC layers - */ - rc = session.handshake (sock); - if (rc != SSH2.Error.NONE) { - debug ("Error when starting up SSH session: %d", rc); - throw new Error.literal (q, 1, _("Error when starting up SSH session: %d").printf (rc)); - } - - /* check what authentication methods are available */ - int auth_pw = 0; - var userauthlist = session.list_authentication (username.data); - debug ("Authentication methods: %s", userauthlist); - if ("password" in userauthlist) { - auth_pw |= Auth.PASSWORD; - } - - if ("publickey" in userauthlist) { - auth_pw |= Auth.PUBLICKEY; - } - - if ((auth_pw & Auth.PASSWORD) != 0) { - if (session.auth_password (username, password) != SSH2.Error.NONE) { - debug ("Authentication by password failed."); - ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - throw new Error.literal (q, 1, _("Authentication by password failed!")); - } - } else if ((auth_pw & Auth.PUBLICKEY) != 0) { - if (session.auth_publickey_from_file (username, - keyfile1, - keyfile2, - password - ) != SSH2.Error.NONE) { - debug ("Authentication by public key failed!"); - ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - throw new Error.literal (q, 1, _("Authentication by public key failed!")); - } - - debug ("Authentication by public key succeeded."); - } else { - debug ("No supported authentication methods found!"); - ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - throw new Error.literal (q, 1, _("No supported authentication methods found!")); - } - - listensock = Posix.socket (Posix.AF_INET, Posix.SOCK_STREAM, Posix.IPProto.TCP); - if (listensock == -1) { - debug ("failed to open listen socket"); - ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - throw new Error.literal (q, 1, _("Failed to open listen socket")); - } - - debug ("listensock %d", listensock); - - sin = Posix.SockAddrIn (); - sin.sin_family = Posix.AF_INET; - sin.sin_addr.s_addr = Posix.inet_addr (local_listenip); - sin.sin_port = Posix.htons (local_listenport); - - var sockopt = 1; - Posix.setsockopt (listensock, Linux.Socket.SOL_SOCKET, Linux.Socket.SO_REUSEADDR, &sockopt, (Posix.socklen_t) sizeof (int)); - if (Posix.bind (listensock, &sin, sizeof (Posix.SockAddrIn)) == -1) { - debug ("Failed to bind!"); - ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - throw new Error.literal (q, 1, _("Failed to bind. Your Database Port may be wrong!")); - } - - if (Posix.listen (listensock, 2) == -1) { - debug ("Failed to listen!"); - ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - throw new Error.literal (q, 1, _("Failed to listen!")); - } - - debug ("Waiting for TCP connection on %s:%d...", local_listenip, local_listenport); - - bool signal_launched = false; - while (ssh_tunnel_alive) { - - if (!signal_launched) { - signal_launched = true; - ssh_tunnel_ready (); - } else { - if (!is_real) { - ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - return; - } - } - - debug ("Waiting for remote connection %p", Thread.self ()); - - forwardsock = Posix.accept (listensock, null, null); - - debug ("forwardsock %d", forwardsock); - - if (forwardsock == -1) { - debug ("Failed to accept!"); - ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - throw new Error.literal (q, 1, _("Failed to accept remote connection!")); - } - - debug ("Forwarding connection from %s:%d here to remote %s:%d", local_listenip, local_listenport, remote_desthost, remote_destport); - - var channel = session.direct_tcpip (remote_desthost, remote_destport, local_listenip, local_listenport); - if (channel == null) { - debug ("Could not open the direct-tcpip channel! (Note that this can be a problem at the server! Please review the server logs.)"); - ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - throw new Error.literal (q, 1, _("Could not open the direct-tcpip channel! (Note that this can be a problem at the server! Please review the server logs.)")); - } - - session.blocking = false; - - uint8[] buf = new uint8[16384]; - while (ssh_tunnel_alive) { - Posix.fd_set fds; - Posix.FD_ZERO (out fds); - Posix.FD_SET (forwardsock, ref fds); - Posix.timeval tv = {0, 100000}; - var res = Posix.select (forwardsock + 1, &fds, null, null, tv); - - if (-1 == res) { - debug ("Error on select!"); - if (is_real) { - ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - } - // direct_shutdown (); - break; - } - - if (res > 0 && Posix.FD_ISSET (forwardsock, fds) > 0) { - var len = Posix.recv (forwardsock, buf, 16384, 0); - if (len < 0) { - debug ("Error reading from the forwardsock!"); - ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - break; - } else if (0 == len) { - debug ("The client at %s:%d disconnected!", local_listenip, local_listenport); - debug ("connection manager %p", this); - if (is_real) { - direct_shutdown (); - } - break; - } - ssize_t wr = 0; - ssize_t i = 0; - do { - i = channel.write (buf[wr:len]); - if (i < 0) { - debug ("Error writing on the SSH channel: %s", i.to_string ()); - ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - // direct_shutdown (); - break; - } - wr += i; - } while (i > 0 && wr < len); - } - - while (ssh_tunnel_alive) { - ssize_t len = channel.read (buf); - if (SSH2.Error.AGAIN == len) - break; - else if (len < 0) { - debug ("Error reading from the SSH channel: %d", (int) len); - ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - // direct_shutdown (); - break; - } - ssize_t wr = 0; - while (wr < len) { - ssize_t i = Posix.send (forwardsock, buf[wr:buf.length], len - wr, 0); - if (i <= 0) { - debug ("Error writing on the forwardsock!"); - ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - // direct_shutdown (); - break; - } - wr += i; - } - if (channel.eof () != SSH2.Error.NONE) { - debug ("The remote client at %s:%d disconnected!", remote_desthost, remote_destport); - if (is_real) { - ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - // direct_shutdown (); - } - break; - } - } - } - } - } - - public void ssh_tunnel_close (string from = "Unknown") { - debug ("closing ssh tunnel from: %s %p", from, Thread.self ()); - ssh_tunnel_alive = false; - - // debug ("closing listensock: %d", listensock); - Posix.close (listensock); - listensock = -1; - // debug ("listensock closed: %d", listensock); - // debug ("closing forwardsock: %d", forwardsock); - Posix.close (forwardsock); - forwardsock = -1; - // debug ("forwardsock closed: %d", forwardsock); - - if (session != null) { - session.disconnect ("Client disconnecting normally"); - session.blocking = false; - session = null; - } - - Posix.close (sock); - sock = -1; - SSH2.exit (); - } - - private void direct_shutdown () { - session.blocking = true; - Posix.close (forwardsock); - forwardsock = -1; - } - - public async int run_query (string query) throws Error requires (connection.is_opened ()) { - return connection.execute_non_select_command (query); - } - - public Gda.DataModel? run_select (string query) throws Error { - return connection.execute_select_command (query); - } - - public async Gee.HashMap init_connection () throws ThreadError { - var output = new Gee.HashMap (); - output["status"] = "false"; - SourceFunc callback = init_connection.callback; - - new Thread (null, () => { - bool result = true; - string msg = ""; - - try { - open (); - debug ("pass init connection"); - } catch (Error e) { - result = false; - msg = e.message; - } - - Idle.add ((owned) callback); - output["msg"] = msg; - output["status"] = result.to_string (); - - return null; - }); - - yield; - - return output; - } - - public async Gda.DataModel? init_select_query (string query) { - Gda.DataModel? result = null; - SourceFunc callback = init_select_query.callback; - var error = ""; - - new Thread (null, () => { - try { - result = run_select (query); - } catch (Error e) { - error = e.message; - result = null; - } - Idle.add((owned) callback); - return null; - }); - - yield; - - if (error != "") { - query_warning (error); - return null; - } - - return result; - } - - public async int? init_query (string query) { - int result = 0; - var error = ""; - - try { - result = yield run_query (query); - } catch (Error e) { - error = e.message; - } - - if (error != "") { - query_warning (error); - return null; - } - - return result; - } - - public void query_warning (string message) { - var message_dialog = new Granite.MessageDialog.with_image_from_icon_name (_("Error!"), message, "dialog-error", Gtk.ButtonsType.NONE); - message_dialog.transient_for = window; - - var suggested_button = new Gtk.Button.with_label ("Close"); - message_dialog.add_action_widget (suggested_button, Gtk.ResponseType.ACCEPT); - - message_dialog.show_all (); - if (message_dialog.run () == Gtk.ResponseType.ACCEPT) {} - - message_dialog.destroy (); - } + enum Auth { + NONE, + PASSWORD, + PUBLICKEY + } + + public ConnectionManager (Sequeler.Window window, Gee.HashMap data) { + Object ( + window: window, + data: data + ); + } + + construct { + switch (data["type"]) { + case "MySQL": + db_type = new Sequeler.Services.Types.MySQL (); + break; + case "MariaDB": + db_type = new Sequeler.Services.Types.MySQL (); + break; + case "PostgreSQL": + db_type = new Sequeler.Services.Types.PostgreSQL (); + break; + case "SQLite": + db_type = new Sequeler.Services.Types.SQLite (); + break; + } + + fetch_password (); + } + + public void fetch_password () { + if (data["password"] == null) { + data["password"] = ""; + + var loop = new MainLoop (); + password_mngr.get_password_async.begin (data["id"], (obj, res) => { + try { + data["password"] = password_mngr.get_password_async.end (res); + } catch (Error e) { + debug ("Unable to get the password from libsecret"); + } + loop.quit (); + }); + + loop.run (); + } + + if (data["has_ssh"] == "true") { + data["ssh_password"] = ""; + + var ssh_loop = new MainLoop (); + password_mngr.get_password_async.begin (data["id"] + "9999", (obj, res) => { + try { + data["ssh_password"] = password_mngr.get_password_async.end (res); + } catch (Error e) { + debug ("Unable to get the SSH password from libsecret"); + } + ssh_loop.quit (); + }); + + ssh_loop.run (); + } + } + + public void test () throws Error { + if (data["password"] == null) { + fetch_password (); + } + + var connection_string = (db_type as DataBaseType).connection_string (data); + debug ("connection string %s", connection_string); + + try { + connection = Gda.Connection.open_from_string (null, connection_string, null, Gda.ConnectionOptions.NONE); + } catch (Error e) { + throw e; + } + + if (connection.is_opened ()) { + connection.close (); + } + } + + public void open () throws Error { + if (data["password"] == null) { + fetch_password (); + } + + var connection_string = (db_type as DataBaseType).connection_string (data); + debug ("connection string %s", connection_string); + + try { + connection = Gda.Connection.open_from_string (null, connection_string, null, Gda.ConnectionOptions.NONE); + } catch (Error e) { + throw e; + } + debug ("open ends"); + } + + public void ssh_tunnel_init (bool is_real) throws Error { + try { + ssh_tunnel_open (is_real); + } catch (Error e) { + debug (e.message); + throw e; + } + } + + private void ssh_tunnel_open (bool is_real) throws Error { + debug ("Opening tunnel %p", Thread.self ()); + + ssh_tunnel_alive = true; + + Quark q = Quark.from_string ("ssh-error-str"); + var home_dir = Environment.get_home_dir (); + + // private key file + var keyfile2 = home_dir + "/.ssh/id_rsa"; + if (data.has_key ("ssh_identity_file") && data["ssh_identity_file"] != "") { + keyfile2 = data["ssh_identity_file"]; + } + + // public key file + var keyfile1 = keyfile2 + ".pub"; + + + // SSH credentials if password authentication is required + var username = data["ssh_username"]; + var password = data["ssh_password"]; + + // SSH HOST address and Port + var server_ip = data["ssh_host"]; + var server_port = data["ssh_port"] != "" ? (uint16) int.parse (data["ssh_port"]) : 22; + + // The IP address where the DB is available on your SSH + var local_listenip = "127.0.0.1"; + + // The Port used by the DB on your SSH host + uint16 local_listenport = 9000; + + // Default vars for TCPIP Tunnelling + var remote_desthost = data["host"] != "" ? data["host"] : "127.0.0.1"; + var remote_destport = data["port"] != "" ? int.parse (data["port"]) : 3306; + + var rc = SSH2.init (0); + if (rc != SSH2.Error.NONE) { + debug ("libssh2 initialization failed (%d)", rc); + throw new Error.literal (q, 1, _("Libssh2 initialization failed (%d)").printf (rc)); + } + + debug ("Socket params: %s %d", server_ip, server_port); + + /* Connect to SSH server */ + sock = Posix.socket (Posix.AF_INET, Posix.SOCK_STREAM, Posix.IPProto.TCP); + if (sock == -1) { + debug ("Failed to open socket"); + throw new Error.literal (q, 1, _("Failed to open socket")); + } + + Posix.SockAddrIn sin = Posix.SockAddrIn (); + sin.sin_family = Posix.AF_INET; + sin.sin_addr.s_addr = Posix.inet_addr (server_ip); + sin.sin_port = Posix.htons (server_port); + if (Posix.connect (sock, &sin, sizeof (Posix.SockAddrIn)) != 0) { + debug ("Failed to connect!"); + throw new Error.literal (q, 1, _("Failed to connect!")); + } + + /* Create a session instance */ + session = SSH2.Session.create (); + + /* …start it up. This will trade welcome banners, exchange keys, + * and setup crypto, compression, and MAC layers + */ + rc = session.handshake (sock); + if (rc != SSH2.Error.NONE) { + debug ("Error when starting up SSH session: %d", rc); + throw new Error.literal (q, 1, _("Error when starting up SSH session: %d").printf (rc)); + } + + /* check what authentication methods are available */ + int auth_pw = 0; + var userauthlist = session.list_authentication (username.data); + debug ("Authentication methods: %s", userauthlist); + if ("password" in userauthlist) { + auth_pw |= Auth.PASSWORD; + } + + if ("publickey" in userauthlist) { + auth_pw |= Auth.PUBLICKEY; + } + + if ((auth_pw & Auth.PASSWORD) != 0) { + if (session.auth_password (username, password) != SSH2.Error.NONE) { + debug ("Authentication by password failed."); + ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + throw new Error.literal (q, 1, _("Authentication by password failed!")); + } + } else if ((auth_pw & Auth.PUBLICKEY) != 0) { + if (session.auth_publickey_from_file (username, + keyfile1, + keyfile2, + password + ) != SSH2.Error.NONE) { + debug ("Authentication by public key failed!"); + ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + throw new Error.literal (q, 1, _("Authentication by public key failed!")); + } + + debug ("Authentication by public key succeeded."); + } else { + debug ("No supported authentication methods found!"); + ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + throw new Error.literal (q, 1, _("No supported authentication methods found!")); + } + + listensock = Posix.socket (Posix.AF_INET, Posix.SOCK_STREAM, Posix.IPProto.TCP); + if (listensock == -1) { + debug ("failed to open listen socket"); + ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + throw new Error.literal (q, 1, _("Failed to open listen socket")); + } + + debug ("listensock %d", listensock); + + sin = Posix.SockAddrIn (); + sin.sin_family = Posix.AF_INET; + sin.sin_addr.s_addr = Posix.inet_addr (local_listenip); + sin.sin_port = Posix.htons (local_listenport); + + var sockopt = 1; + Posix.setsockopt (listensock, Linux.Socket.SOL_SOCKET, Linux.Socket.SO_REUSEADDR, &sockopt, (Posix.socklen_t) sizeof (int)); + if (Posix.bind (listensock, &sin, sizeof (Posix.SockAddrIn)) == -1) { + debug ("Failed to bind!"); + ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + throw new Error.literal (q, 1, _("Failed to bind. Your Database Port may be wrong!")); + } + + if (Posix.listen (listensock, 2) == -1) { + debug ("Failed to listen!"); + ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + throw new Error.literal (q, 1, _("Failed to listen!")); + } + + debug ("Waiting for TCP connection on %s:%d…", local_listenip, local_listenport); + + bool signal_launched = false; + while (ssh_tunnel_alive) { + + if (!signal_launched) { + signal_launched = true; + ssh_tunnel_ready (); + } else { + if (!is_real) { + ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + return; + } + } + + debug ("Waiting for remote connection %p", Thread.self ()); + + forwardsock = Posix.accept (listensock, null, null); + + debug ("forwardsock %d", forwardsock); + + if (forwardsock == -1) { + debug ("Failed to accept!"); + ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + throw new Error.literal (q, 1, _("Failed to accept remote connection!")); + } + + debug ("Forwarding connection from %s:%d here to remote %s:%d", local_listenip, local_listenport, remote_desthost, remote_destport); + + var channel = session.direct_tcpip (remote_desthost, remote_destport, local_listenip, local_listenport); + if (channel == null) { + debug ("Could not open the direct-tcpip channel! (Note that this can be a problem at the server! Please review the server logs.)"); + ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + throw new Error.literal (q, 1, _("Could not open the direct-tcpip channel! (Note that this can be a problem at the server! Please review the server logs.)")); + } + + session.blocking = false; + + uint8[] buf = new uint8[16384]; + while (ssh_tunnel_alive) { + Posix.fd_set fds; + Posix.FD_ZERO (out fds); + Posix.FD_SET (forwardsock, ref fds); + Posix.timeval tv = {0, 100000}; + var res = Posix.select (forwardsock + 1, &fds, null, null, tv); + + if (-1 == res) { + debug ("Error on select!"); + if (is_real) { + ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + } + // direct_shutdown (); + break; + } + + if (res > 0 && Posix.FD_ISSET (forwardsock, fds) > 0) { + var len = Posix.recv (forwardsock, buf, 16384, 0); + if (len < 0) { + debug ("Error reading from the forwardsock!"); + ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + break; + } else if (0 == len) { + debug ("The client at %s:%d disconnected!", local_listenip, local_listenport); + debug ("connection manager %p", this); + if (is_real) { + direct_shutdown (); + } + break; + } + ssize_t wr = 0; + ssize_t i = 0; + do { + i = channel.write (buf[wr:len]); + if (i < 0) { + debug ("Error writing on the SSH channel: %s", i.to_string ()); + ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + // direct_shutdown (); + break; + } + wr += i; + } while (i > 0 && wr < len); + } + + while (ssh_tunnel_alive) { + ssize_t len = channel.read (buf); + if (SSH2.Error.AGAIN == len) + break; + else if (len < 0) { + debug ("Error reading from the SSH channel: %d", (int) len); + ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + // direct_shutdown (); + break; + } + ssize_t wr = 0; + while (wr < len) { + ssize_t i = Posix.send (forwardsock, buf[wr:buf.length], len - wr, 0); + if (i <= 0) { + debug ("Error writing on the forwardsock!"); + ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + // direct_shutdown (); + break; + } + wr += i; + } + if (channel.eof () != SSH2.Error.NONE) { + debug ("The remote client at %s:%d disconnected!", remote_desthost, remote_destport); + if (is_real) { + ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + // direct_shutdown (); + } + break; + } + } + } + } + } + + public void ssh_tunnel_close (string from = "Unknown") { + debug ("closing ssh tunnel from: %s %p", from, Thread.self ()); + ssh_tunnel_alive = false; + + // debug ("closing listensock: %d", listensock); + Posix.close (listensock); + listensock = -1; + // debug ("listensock closed: %d", listensock); + // debug ("closing forwardsock: %d", forwardsock); + Posix.close (forwardsock); + forwardsock = -1; + // debug ("forwardsock closed: %d", forwardsock); + + if (session != null) { + session.disconnect ("Client disconnecting normally"); + session.blocking = false; + session = null; + } + + Posix.close (sock); + sock = -1; + SSH2.exit (); + } + + private void direct_shutdown () { + session.blocking = true; + Posix.close (forwardsock); + forwardsock = -1; + } + + public async int run_query (string query) throws Error requires (connection.is_opened ()) { + return connection.execute_non_select_command (query); + } + + public Gda.DataModel? run_select (string query) throws Error { + return connection.execute_select_command (query); + } + + public async Gee.HashMap init_connection () throws ThreadError { + var output = new Gee.HashMap (); + output["status"] = "false"; + SourceFunc callback = init_connection.callback; + + new Thread (null, () => { + bool result = true; + string msg = ""; + + try { + open (); + debug ("pass init connection"); + } catch (Error e) { + result = false; + msg = e.message; + } + + Idle.add ((owned) callback); + output["msg"] = msg; + output["status"] = result.to_string (); + + return null; + }); + + yield; + + return output; + } + + public async Gda.DataModel? init_select_query (string query) { + Gda.DataModel? result = null; + SourceFunc callback = init_select_query.callback; + var error = ""; + + new Thread (null, () => { + try { + result = run_select (query); + } catch (Error e) { + error = e.message; + result = null; + } + Idle.add ((owned) callback); + return null; + }); + + yield; + + if (error != "") { + query_warning (error); + return null; + } + + return result; + } + + public async int? init_query (string query) { + int result = 0; + var error = ""; + + try { + result = yield run_query (query); + } catch (Error e) { + error = e.message; + } + + if (error != "") { + query_warning (error); + return null; + } + + return result; + } + + public void query_warning (string message) { + var message_dialog = new Granite.MessageDialog.with_image_from_icon_name (_("Error!"), message, "dialog-error", Gtk.ButtonsType.NONE); + message_dialog.transient_for = window; + + var suggested_button = new Gtk.Button.with_label ("Close"); + message_dialog.add_action_widget (suggested_button, Gtk.ResponseType.ACCEPT); + + message_dialog.show_all (); + if (message_dialog.run () == Gtk.ResponseType.ACCEPT) {} + + message_dialog.destroy (); + } } diff --git a/src/Services/DataManager.vala b/src/Services/DataManager.vala index 6c93a67b..21fd52dd 100644 --- a/src/Services/DataManager.vala +++ b/src/Services/DataManager.vala @@ -20,10 +20,10 @@ */ public class Sequeler.Services.DataManager : Object { - private Gee.HashMap? _data = null; + private Gee.HashMap? _data = null; - public Gee.HashMap? data { - get { return _data; } - set { _data = value; } - } -} \ No newline at end of file + public Gee.HashMap? data { + get { return _data; } + set { _data = value; } + } +} diff --git a/src/Services/PasswordManager.vala b/src/Services/PasswordManager.vala index a7c726e0..2eebfc37 100644 --- a/src/Services/PasswordManager.vala +++ b/src/Services/PasswordManager.vala @@ -21,58 +21,62 @@ public class Sequeler.Services.PasswordManager : Object { - // Store Password Async - public virtual async void store_password_async (string id, string password) throws Error { - var attributes = new GLib.HashTable (str_hash, str_equal); - attributes["id"] = id; - attributes["schema"] = Constants.PROJECT_NAME; + // Store Password Async + public virtual async void store_password_async (string id, string password) throws Error { + var attributes = new GLib.HashTable (str_hash, str_equal); + attributes["id"] = id; + attributes["schema"] = Constants.PROJECT_NAME; - var key_name = Constants.PROJECT_NAME + "." + id; + var key_name = Constants.PROJECT_NAME + "." + id; - bool result = yield Secret.password_storev (schema, attributes, Secret.COLLECTION_DEFAULT, key_name, password, null); + bool result = yield Secret.password_storev (schema, attributes, Secret.COLLECTION_DEFAULT, key_name, password, null); - if (! result) - debug("Unable to store password for \"%s\" in libsecret keyring", key_name); - } + if (! result) { + debug ("Unable to store password for \"%s\" in libsecret keyring", key_name); + } + } - // Get Password Async - public virtual async string? get_password_async (string id) throws Error { - var attributes = new GLib.HashTable (str_hash, str_equal); - attributes["id"] = id; - attributes["schema"] = Constants.PROJECT_NAME; + // Get Password Async + public virtual async string? get_password_async (string id) throws Error { + var attributes = new GLib.HashTable (str_hash, str_equal); + attributes["id"] = id; + attributes["schema"] = Constants.PROJECT_NAME; - var key_name = Constants.PROJECT_NAME + "." + id; + var key_name = Constants.PROJECT_NAME + "." + id; - string? password = yield Secret.password_lookupv (schema, attributes, null); + string? password = yield Secret.password_lookupv (schema, attributes, null); - if (password == null) - debug("Unable to fetch password in libsecret keyring for %s", key_name); + if (password == null) { + debug ("Unable to fetch password in libsecret keyring for %s", key_name); + } - return password; - } + return password; + } - // Delete Password Async - public virtual async void clear_password_async (string id) throws Error { - var attributes = new GLib.HashTable (str_hash, str_equal); - attributes["id"] = id; - attributes["schema"] = Constants.PROJECT_NAME; + // Delete Password Async + public virtual async void clear_password_async (string id) throws Error { + var attributes = new GLib.HashTable (str_hash, str_equal); + attributes["id"] = id; + attributes["schema"] = Constants.PROJECT_NAME; - var key_name = Constants.PROJECT_NAME + "." + id; + var key_name = Constants.PROJECT_NAME + "." + id; - bool removed = yield Secret.password_clearv (schema, attributes, null); + bool removed = yield Secret.password_clearv (schema, attributes, null); - if (! removed) - debug("Unable to clear password in libsecret keyring for %s", key_name); - } + if (! removed) { + debug ("Unable to clear password in libsecret keyring for %s", key_name); + } + } - // Delete All Passwords - public virtual async void clear_all_passwords_async () throws Error { - var attributes = new GLib.HashTable (str_hash, str_equal); - attributes["schema"] = Constants.PROJECT_NAME; + // Delete All Passwords + public virtual async void clear_all_passwords_async () throws Error { + var attributes = new GLib.HashTable (str_hash, str_equal); + attributes["schema"] = Constants.PROJECT_NAME; - bool removed = yield Secret.password_clearv (schema, attributes, null); + bool removed = yield Secret.password_clearv (schema, attributes, null); - if (! removed) - debug("Unable to clear all passwords in libsecret"); - } + if (! removed) { + debug ("Unable to clear all passwords in libsecret"); + } + } } diff --git a/src/Services/Settings.vala b/src/Services/Settings.vala index c06e718c..461ee2db 100644 --- a/src/Services/Settings.vala +++ b/src/Services/Settings.vala @@ -20,153 +20,153 @@ */ public class Sequeler.Services.Settings : Granite.Services.Settings { - public int pos_x { get; set; } - public int pos_y { get; set; } - public int window_width { get; set; } - public int window_height { get; set; } - public int sidebar_width { get; set; } - public string[] saved_connections { get; set; } - public int tot_connections { get; set; } - public int limit_results { get; set; } - public bool dark_theme { get; set; } - public bool save_quick { get; set; } - public string version { get; set; } - public bool use_system_font { get; set; } - public string font { get; set; } - public string style_scheme { get; set; } - public int query_area { get; set; } - - public Settings () { - base (Constants.PROJECT_NAME); - } - - public void add_connection (Gee.HashMap data) { - Gee.List existing_connections = new Gee.ArrayList (); - existing_connections.add_all_array (saved_connections); - - if (data["type"] != "SQLite") { - update_password.begin (data); - data.unset ("password"); - data.unset ("ssh_password"); - } - - var position = existing_connections.size; - existing_connections.insert (position, stringify_data (data)); - saved_connections = existing_connections.to_array (); - tot_connections = tot_connections + 1; - } - - public void edit_connection (Gee.HashMap new_data, string old_data) { - var position = 0; - Gee.List existing_connections = new Gee.ArrayList (); - existing_connections.add_all_array (saved_connections); - - if (existing_connections.contains (old_data)) { - position = existing_connections.index_of (old_data); - existing_connections.remove (old_data); - } - - if (new_data["type"] != "SQLite") { - update_password.begin (new_data); - new_data.unset ("password"); - - if (new_data["has_ssh"] == "true" && new_data["ssh_password"] != null) { - update_ssh_password.begin (new_data); - new_data.unset ("ssh_password"); - } - } - - existing_connections.insert (position, stringify_data (new_data)); - saved_connections = existing_connections.to_array (); - } - - public void delete_connection (Gee.HashMap data) { - Gee.List existing_connections = new Gee.ArrayList (); - existing_connections.add_all_array (saved_connections); - - if (data["type"] != "SQLite") { - delete_password.begin (data); - } - - foreach (var conn in saved_connections) { - var check = arraify_data (conn); - if (check["id"] == data["id"]) { - existing_connections.remove (conn); - } - } - - saved_connections = existing_connections.to_array (); - } - - public void clear_connections () { - Gee.List empty_connection = new Gee.ArrayList (); - saved_connections = empty_connection.to_array (); - tot_connections = 0; - - delete_all_passwords.begin (); - } - - public void reorder_connection (Gee.HashMap source, int position) { - var data = stringify_data (source); - Gee.List existing_connections = new Gee.ArrayList (); - existing_connections.add_all_array (saved_connections); - - foreach (var conn in saved_connections) { - var check = arraify_data (conn); - if (check["id"] == source["id"]) { - existing_connections.remove (conn); - } - } - - existing_connections.insert (position, data); - saved_connections = existing_connections.to_array (); - } - - public string stringify_data (Gee.HashMap data) { - string result = ""; - - foreach (var entry in data.entries) { - string values = "%s=%s\n".printf (entry.key, entry.value); - result = result + values; - } - - return result; - } - - public Gee.HashMap arraify_data (string connection) { - var array = new Gee.HashMap (); - var data = connection.split ("\n"); - - foreach (var d in data) { - var d2 = d.split ("=", 2); - - if (d2[0] == null) { - continue; - } - - array.set (d2[0], d2[1]); - } - - return array; - } - - public async void update_password (Gee.HashMap data) throws Error { - yield password_mngr.store_password_async (data["id"], data["password"]); - } - - public async void update_ssh_password (Gee.HashMap data) throws Error { - yield password_mngr.store_password_async (data["id"] + "9999", data["ssh_password"]); - } - - public async void delete_password (Gee.HashMap data) throws Error { - yield password_mngr.clear_password_async (data["id"]); - - if (data["has_ssh"] == "true" && data["ssh_password"] != null) { - yield password_mngr.clear_password_async (data["id"] + "9999"); - } - } - - public async void delete_all_passwords () throws Error { - yield password_mngr.clear_all_passwords_async (); - } + public int pos_x { get; set; } + public int pos_y { get; set; } + public int window_width { get; set; } + public int window_height { get; set; } + public int sidebar_width { get; set; } + public string[] saved_connections { get; set; } + public int tot_connections { get; set; } + public int limit_results { get; set; } + public bool dark_theme { get; set; } + public bool save_quick { get; set; } + public string version { get; set; } + public bool use_system_font { get; set; } + public string font { get; set; } + public string style_scheme { get; set; } + public int query_area { get; set; } + + public Settings () { + base (Constants.PROJECT_NAME); + } + + public void add_connection (Gee.HashMap data) { + Gee.List existing_connections = new Gee.ArrayList (); + existing_connections.add_all_array (saved_connections); + + if (data["type"] != "SQLite") { + update_password.begin (data); + data.unset ("password"); + data.unset ("ssh_password"); + } + + var position = existing_connections.size; + existing_connections.insert (position, stringify_data (data)); + saved_connections = existing_connections.to_array (); + tot_connections = tot_connections + 1; + } + + public void edit_connection (Gee.HashMap new_data, string old_data) { + var position = 0; + Gee.List existing_connections = new Gee.ArrayList (); + existing_connections.add_all_array (saved_connections); + + if (existing_connections.contains (old_data)) { + position = existing_connections.index_of (old_data); + existing_connections.remove (old_data); + } + + if (new_data["type"] != "SQLite") { + update_password.begin (new_data); + new_data.unset ("password"); + + if (new_data["has_ssh"] == "true" && new_data["ssh_password"] != null) { + update_ssh_password.begin (new_data); + new_data.unset ("ssh_password"); + } + } + + existing_connections.insert (position, stringify_data (new_data)); + saved_connections = existing_connections.to_array (); + } + + public void delete_connection (Gee.HashMap data) { + Gee.List existing_connections = new Gee.ArrayList (); + existing_connections.add_all_array (saved_connections); + + if (data["type"] != "SQLite") { + delete_password.begin (data); + } + + foreach (var conn in saved_connections) { + var check = arraify_data (conn); + if (check["id"] == data["id"]) { + existing_connections.remove (conn); + } + } + + saved_connections = existing_connections.to_array (); + } + + public void clear_connections () { + Gee.List empty_connection = new Gee.ArrayList (); + saved_connections = empty_connection.to_array (); + tot_connections = 0; + + delete_all_passwords.begin (); + } + + public void reorder_connection (Gee.HashMap source, int position) { + var data = stringify_data (source); + Gee.List existing_connections = new Gee.ArrayList (); + existing_connections.add_all_array (saved_connections); + + foreach (var conn in saved_connections) { + var check = arraify_data (conn); + if (check["id"] == source["id"]) { + existing_connections.remove (conn); + } + } + + existing_connections.insert (position, data); + saved_connections = existing_connections.to_array (); + } + + public string stringify_data (Gee.HashMap data) { + string result = ""; + + foreach (var entry in data.entries) { + string values = "%s=%s\n".printf (entry.key, entry.value); + result = result + values; + } + + return result; + } + + public Gee.HashMap arraify_data (string connection) { + var array = new Gee.HashMap (); + var data = connection.split ("\n"); + + foreach (var d in data) { + var d2 = d.split ("=", 2); + + if (d2[0] == null) { + continue; + } + + array.set (d2[0], d2[1]); + } + + return array; + } + + public async void update_password (Gee.HashMap data) throws Error { + yield password_mngr.store_password_async (data["id"], data["password"]); + } + + public async void update_ssh_password (Gee.HashMap data) throws Error { + yield password_mngr.store_password_async (data["id"] + "9999", data["ssh_password"]); + } + + public async void delete_password (Gee.HashMap data) throws Error { + yield password_mngr.clear_password_async (data["id"]); + + if (data["has_ssh"] == "true" && data["ssh_password"] != null) { + yield password_mngr.clear_password_async (data["id"] + "9999"); + } + } + + public async void delete_all_passwords () throws Error { + yield password_mngr.clear_all_passwords_async (); + } } diff --git a/src/Services/Types/DataBaseType.vala b/src/Services/Types/DataBaseType.vala index bdeb52a7..aa018aaf 100644 --- a/src/Services/Types/DataBaseType.vala +++ b/src/Services/Types/DataBaseType.vala @@ -20,38 +20,38 @@ */ public interface DataBaseType : Object { - /* - * Connect to the database - */ - public abstract string connection_string (Gee.HashMap data); + /* + * Connect to the database + */ + public abstract string connection_string (Gee.HashMap data); - /* - * Populate dropdown database selection - */ - public abstract string show_schema (); + /* + * Populate dropdown database selection + */ + public abstract string show_schema (); - /* - * Populate sidebar with table list - */ - public abstract string show_table_list (string name); + /* + * Populate sidebar with table list + */ + public abstract string show_table_list (string name); - /* - * Update table name - */ - public abstract string edit_table_name (string old_table, string new_table); + /* + * Update table name + */ + public abstract string edit_table_name (string old_table, string new_table); - /* - * Show table structure - */ - public abstract string show_table_structure (string table); + /* + * Show table structure + */ + public abstract string show_table_structure (string table); - /* - * Show table content - */ - public abstract string show_table_content (string table, int? count, int? page = null); + /* + * Show table content + */ + public abstract string show_table_content (string table, int? count, int? page = null); - /* - * Show table relations - */ - public abstract string show_table_relations (string table, string? database); + /* + * Show table relations + */ + public abstract string show_table_relations (string table, string? database); } diff --git a/src/Services/Types/MySQL.vala b/src/Services/Types/MySQL.vala index 3aefc087..823547d2 100644 --- a/src/Services/Types/MySQL.vala +++ b/src/Services/Types/MySQL.vala @@ -20,55 +20,55 @@ */ public class Sequeler.Services.Types.MySQL : Object, DataBaseType { - public string port { set; get; default = "3306"; } - public string host { set; get; default = "127.0.0.1"; } + public string port { set; get; default = "3306"; } + public string host { set; get; default = "127.0.0.1"; } - public string connection_string (Gee.HashMap data) { - var username = Gda.rfc1738_encode (data["username"]); - var password = Gda.rfc1738_encode (data["password"]); - var name = Gda.rfc1738_encode (data["name"]); - if (data["has_ssh"] == "true") { - port = "9000"; - host = "127.0.0.1"; - } else { - port = data["port"] != "" ? data["port"] : port; - host = data["host"] != "" ? Gda.rfc1738_encode (data["host"]) : host; - } + public string connection_string (Gee.HashMap data) { + var username = Gda.rfc1738_encode (data["username"]); + var password = Gda.rfc1738_encode (data["password"]); + var name = Gda.rfc1738_encode (data["name"]); + if (data["has_ssh"] == "true") { + port = "9000"; + host = "127.0.0.1"; + } else { + port = data["port"] != "" ? data["port"] : port; + host = data["host"] != "" ? Gda.rfc1738_encode (data["host"]) : host; + } - return "MySQL://" + username + ":" + password + "@DB_NAME=" + name + ";HOST=" + host + ";PORT=" + port; - } + return "MySQL://" + username + ":" + password + "@DB_NAME=" + name + ";HOST=" + host + ";PORT=" + port; + } - public string show_schema () { - return "SHOW SCHEMAS"; - } + public string show_schema () { + return "SHOW SCHEMAS"; + } - public string show_table_list (string name) { - return "SELECT table_name, table_rows FROM information_schema.TABLES WHERE TABLE_SCHEMA = '%s'".printf (name); - } + public string show_table_list (string name) { + return "SELECT table_name, table_rows FROM information_schema.TABLES WHERE TABLE_SCHEMA = '%s'".printf (name); + } - public string edit_table_name (string old_table, string new_table) { - return "RENAME TABLE %s TO %s".printf (old_table, new_table); - } + public string edit_table_name (string old_table, string new_table) { + return "RENAME TABLE %s TO %s".printf (old_table, new_table); + } - public string show_table_structure (string table) { - return "DESCRIBE %s".printf (table); - } + public string show_table_structure (string table) { + return "DESCRIBE %s".printf (table); + } - public string show_table_content (string table, int? count = null, int? page = null) { - var output = "SELECT * FROM %s".printf (table); + public string show_table_content (string table, int? count = null, int? page = null) { + var output = "SELECT * FROM %s".printf (table); - if (count != null && count > settings.limit_results) { - output += " LIMIT %i".printf (settings.limit_results); - } + if (count != null && count > settings.limit_results) { + output += " LIMIT %i".printf (settings.limit_results); + } - if (page != null && page > 1) { - output += " OFFSET %i".printf (settings.limit_results * (page - 1)); - } + if (page != null && page > 1) { + output += " OFFSET %i".printf (settings.limit_results * (page - 1)); + } - return output; - } + return output; + } - public string show_table_relations (string table, string? database) { - return "SELECT COLUMN_NAME, CONSTRAINT_NAME, REFERENCED_COLUMN_NAME, REFERENCED_TABLE_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_NAME = '%s' AND TABLE_SCHEMA = '%s'".printf (table, database); - } + public string show_table_relations (string table, string? database) { + return "SELECT COLUMN_NAME, CONSTRAINT_NAME, REFERENCED_COLUMN_NAME, REFERENCED_TABLE_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_NAME = '%s' AND TABLE_SCHEMA = '%s'".printf (table, database); + } } diff --git a/src/Services/Types/PostgreSQL.vala b/src/Services/Types/PostgreSQL.vala index 9b746c28..d3e31cc0 100644 --- a/src/Services/Types/PostgreSQL.vala +++ b/src/Services/Types/PostgreSQL.vala @@ -56,17 +56,17 @@ public class Sequeler.Services.Types.PostgreSQL : Object, DataBaseType { public string show_table_content (string table, int? count, int? page = null) { var output = "SELECT * FROM \"%s\"".printf (table); - if (count != null && count > settings.limit_results) { - output += " LIMIT %i".printf (settings.limit_results); - } + if (count != null && count > settings.limit_results) { + output += " LIMIT %i".printf (settings.limit_results); + } - if (page != null && page > 1) { - output += " OFFSET %i".printf (settings.limit_results * (page - 1)); - } + if (page != null && page > 1) { + output += " OFFSET %i".printf (settings.limit_results * (page - 1)); + } - return output; + return output; } - + public string show_table_relations (string table, string? database) { return "SELECT ccu.column_name as \"COLUMN_NAME\", tc.constraint_name as \"CONSTRAINT_NAME\", kcu.column_name as \"REFERENCED_COLUMN_NAME\", tc.table_name as \"REFERENCED_TABLE\" FROM information_schema.table_constraints tc JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name JOIN information_schema.constraint_column_usage ccu ON ccu.constraint_name = tc.constraint_name WHERE constraint_type = 'FOREIGN KEY' AND ccu.table_name='%s' AND ccu.table_schema = '%s'".printf (table, database); } diff --git a/src/Services/Types/SQLite.vala b/src/Services/Types/SQLite.vala index ceff1f5f..6dd6f52d 100644 --- a/src/Services/Types/SQLite.vala +++ b/src/Services/Types/SQLite.vala @@ -21,47 +21,47 @@ public class Sequeler.Services.Types.SQLite : Object, DataBaseType { - public string connection_string (Gee.HashMap data) { - var file_path = data["file_path"].replace ("file://", ""); - var last_slash = file_path.last_index_of ("/", 0) + 1; + public string connection_string (Gee.HashMap data) { + var file_path = data["file_path"].replace ("file://", ""); + var last_slash = file_path.last_index_of ("/", 0) + 1; - var dir = Gda.rfc1738_encode (file_path.substring (0, last_slash)); - var name = Gda.rfc1738_encode (file_path.substring (last_slash, -1)); + var dir = Gda.rfc1738_encode (file_path.substring (0, last_slash)); + var name = Gda.rfc1738_encode (file_path.substring (last_slash, -1)); - return "SQLite://DB_DIR=" + dir + ";DB_NAME=" + name; - } + return "SQLite://DB_DIR=" + dir + ";DB_NAME=" + name; + } - public string show_schema () { - return "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;"; - } + public string show_schema () { + return "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;"; + } - public string show_table_list (string name) { - return "SELECT COUNT(*) FROM %s".printf (name); - } + public string show_table_list (string name) { + return "SELECT COUNT(*) FROM %s".printf (name); + } - public string edit_table_name (string old_table, string new_table) { - return "ALTER TABLE %s RENAME TO %s".printf (old_table, new_table); - } + public string edit_table_name (string old_table, string new_table) { + return "ALTER TABLE %s RENAME TO %s".printf (old_table, new_table); + } - public string show_table_structure (string table) { - return "PRAGMA table_info('%s')".printf (table); - } + public string show_table_structure (string table) { + return "PRAGMA table_info('%s')".printf (table); + } - public string show_table_content (string table, int? count, int? page = null) { - var output = "SELECT * FROM %s".printf (table); + public string show_table_content (string table, int? count, int? page = null) { + var output = "SELECT * FROM %s".printf (table); - if (count != null && count > settings.limit_results) { - output += " LIMIT %i".printf (settings.limit_results); - } + if (count != null && count > settings.limit_results) { + output += " LIMIT %i".printf (settings.limit_results); + } - if (page != null && page > 1) { - output += " OFFSET %i".printf (settings.limit_results * (page - 1)); - } + if (page != null && page > 1) { + output += " OFFSET %i".printf (settings.limit_results * (page - 1)); + } - return output; - } + return output; + } - public string show_table_relations (string table, string? database) { - return "PRAGMA foreign_key_list('%s')".printf (table); - } + public string show_table_relations (string table, string? database) { + return "PRAGMA foreign_key_list('%s')".printf (table); + } } diff --git a/src/Services/UpgradeManager.vala b/src/Services/UpgradeManager.vala index 2505ff85..f38f6624 100644 --- a/src/Services/UpgradeManager.vala +++ b/src/Services/UpgradeManager.vala @@ -20,37 +20,37 @@ */ public class Sequeler.Services.UpgradeManager : Object { - construct { - string version = settings.version; + construct { + string version = settings.version; - switch (version) { - case "": - upgrade_passwords_to_libsecret.begin (); - case Constants.VERSION: - debug ("Current Version"); - } + switch (version) { + case "": + upgrade_passwords_to_libsecret.begin (); + case Constants.VERSION: + debug ("Current Version"); + } - settings.version = Constants.VERSION; - } + settings.version = Constants.VERSION; + } - public virtual async void upgrade_passwords_to_libsecret () throws Error { - var current_connections = settings.saved_connections; + public virtual async void upgrade_passwords_to_libsecret () throws Error { + var current_connections = settings.saved_connections; - Gee.List existing_connections = new Gee.ArrayList (); - existing_connections.add_all_array (current_connections); + Gee.List existing_connections = new Gee.ArrayList (); + existing_connections.add_all_array (current_connections); - foreach (var conn in settings.saved_connections) { - var check = settings.arraify_data (conn); + foreach (var conn in settings.saved_connections) { + var check = settings.arraify_data (conn); - if (check["type"] != "SQLite" && check.has_key ("password")) { - settings.update_password.begin (check); - check.unset ("password"); + if (check["type"] != "SQLite" && check.has_key ("password")) { + settings.update_password.begin (check); + check.unset ("password"); - existing_connections.remove (conn); - existing_connections.insert (0, settings.stringify_data (check)); - } - } + existing_connections.remove (conn); + existing_connections.insert (0, settings.stringify_data (check)); + } + } - settings.saved_connections = existing_connections.to_array (); - } + settings.saved_connections = existing_connections.to_array (); + } } diff --git a/src/Widgets/ConnectionDialog.vala b/src/Widgets/ConnectionDialog.vala index 5926497d..a6a3b00e 100644 --- a/src/Widgets/ConnectionDialog.vala +++ b/src/Widgets/ConnectionDialog.vala @@ -20,713 +20,725 @@ */ public class Sequeler.Widgets.ConnectionDialog : Gtk.Dialog { - public weak Sequeler.Window window { get; construct; } - private Sequeler.Services.ConnectionManager? connection_manager { get; set; default = null; } - - public Sequeler.Partials.ButtonClass test_button; - public Sequeler.Partials.ButtonClass connect_button; - - private Gtk.Label header_title; - private Gtk.ColorButton color_picker; - private Gtk.InfoBar infobar; - private Gtk.Label infobar_label; - private string infobar_label_missing_private_key = _("Missing SSH Key file!"); - private string infobar_label_missing_public_key = _("Missing SSH public key!"); - - private Sequeler.Partials.LabelForm db_file_label; - private Sequeler.Partials.LabelForm db_host_label; - private Sequeler.Partials.LabelForm db_name_label; - private Sequeler.Partials.LabelForm db_username_label; - private Sequeler.Partials.LabelForm db_password_label; - private Sequeler.Partials.LabelForm db_port_label; - - private Gtk.Entry connection_id; - private Sequeler.Partials.Entry title_entry; - private Gee.HashMap db_types; - private Gtk.ComboBox db_type_entry; - private Sequeler.Partials.Entry db_host_entry; - private Sequeler.Partials.Entry db_name_entry; - private Sequeler.Partials.Entry db_username_entry; - private Sequeler.Partials.Entry db_password_entry; - private Sequeler.Partials.Entry db_port_entry; - private Gtk.FileChooserButton db_file_entry; - - private string keyfile1; - private string keyfile2; - private Sequeler.Partials.LabelForm ssh_switch_label; - private Gtk.Grid ssh_switch_container; - private Gtk.Switch ssh_switch; - private Sequeler.Partials.LabelForm ssh_host_label; - private Sequeler.Partials.Entry ssh_host_entry; - private Sequeler.Partials.LabelForm ssh_username_label; - private Sequeler.Partials.Entry ssh_username_entry; - private Sequeler.Partials.LabelForm ssh_password_label; - private Sequeler.Partials.Entry ssh_password_entry; - private Sequeler.Partials.LabelForm ssh_port_label; - private Sequeler.Partials.Entry ssh_port_entry; - private Sequeler.Partials.LabelForm ssh_identity_file_label; - private Gtk.FileChooserButton ssh_identity_file_entry; - - private Gtk.Spinner spinner; - private Sequeler.Partials.ResponseMessage response_msg; - - enum Column { - DBTYPE - } - - enum Action { - TEST, - SAVE, - CANCEL, - CONNECT - } - - public ConnectionDialog (Sequeler.Window? parent) { - Object ( - border_width: 5, - deletable: false, - resizable: false, - title: _("Connection"), - transient_for: parent, - window: parent - ); - } - - construct { - set_id (); - build_content (); - toggle_ssh_fields (false); - build_actions (); - populate_data.begin (); - change_sensitivity (); - - response.connect (on_response); - } - - private void set_id () { - var id = settings.tot_connections; - - connection_id = new Gtk.Entry (); - connection_id.text = id.to_string (); - } - - private void build_content () { - var body = get_content_area (); - - db_types = new Gee.HashMap (); - db_types.set (0,"MySQL"); - db_types.set (1,"MariaDB"); - db_types.set (2,"PostgreSQL"); - db_types.set (3,"SQLite"); - - var header_grid = new Gtk.Grid (); - header_grid.margin_start = 30; - header_grid.margin_end = 30; - header_grid.margin_bottom = 10; - - var image = new Gtk.Image.from_icon_name ("office-database", Gtk.IconSize.DIALOG); - image.margin_end = 10; - - header_title = new Gtk.Label (_("New Connection")); - header_title.get_style_context ().add_class (Granite.STYLE_CLASS_H2_LABEL); - header_title.halign = Gtk.Align.START; - header_title.ellipsize = Pango.EllipsizeMode.END; - header_title.margin_end = 10; - header_title.set_line_wrap (true); - header_title.hexpand = true; - - color_picker = new Gtk.ColorButton.with_rgba ({ 222, 222, 222, 255 }); - color_picker.get_style_context ().add_class ("color-picker"); - color_picker.can_focus = false; - - header_grid.attach (image, 0, 0, 1, 2); - header_grid.attach (header_title, 1, 0, 1, 2); - header_grid.attach (color_picker, 2, 0, 1, 1); - - body.add (header_grid); - - var form_grid = new Gtk.Grid (); - form_grid.margin = 30; - form_grid.row_spacing = 12; - form_grid.column_spacing = 20; - - var ssh_grid = new Gtk.Grid (); - ssh_grid.margin = 30; - ssh_grid.row_spacing = 12; - ssh_grid.column_spacing = 20; - - var ssh_switch_grid = new Gtk.Grid (); - ssh_switch_grid.halign = Gtk.Align.CENTER; - ssh_switch_grid.column_spacing = 20; - ssh_switch_grid.margin_bottom = 12; - - var title_label = new Sequeler.Partials.LabelForm (_("Connection Name:")); - title_entry = new Sequeler.Partials.Entry (_("Connection's name"), _("New Connection")); - title_entry.changed.connect (() => { - header_title.label = title_entry.text; - }); - form_grid.attach (title_label, 0, 0, 1, 1); - form_grid.attach (title_entry, 1, 0, 1, 1); - - var db_type_label = new Sequeler.Partials.LabelForm (_("Database Type:")); - var list_store = new Gtk.ListStore (1, typeof (string)); - - for (int i = 0; i < db_types.size; i++){ - Gtk.TreeIter iter; - list_store.append (out iter); - list_store.set (iter, Column.DBTYPE, db_types[i]); - } - - db_type_entry = new Gtk.ComboBox.with_model (list_store); - var cell = new Gtk.CellRendererText (); - db_type_entry.pack_start (cell, false); - - db_type_entry.set_attributes (cell, "text", Column.DBTYPE); - db_type_entry.set_active (0); - db_type_entry.changed.connect (() => { - db_type_changed (); - }); - - form_grid.attach (db_type_label, 0, 1, 1, 1); - form_grid.attach (db_type_entry, 1, 1, 1, 1); - - db_host_label = new Sequeler.Partials.LabelForm (_("Host:")); - db_host_entry = new Sequeler.Partials.Entry ("127.0.0.1", null); - - form_grid.attach (db_host_label, 0, 2, 1, 1); - form_grid.attach (db_host_entry, 1, 2, 1, 1); - - db_name_label = new Sequeler.Partials.LabelForm (_("Database Name:")); - db_name_entry = new Sequeler.Partials.Entry ("", null); - db_name_entry.changed.connect (change_sensitivity); - - form_grid.attach (db_name_label, 0, 3, 1, 1); - form_grid.attach (db_name_entry, 1, 3, 1, 1); - - db_username_label = new Sequeler.Partials.LabelForm (_("Username:")); - db_username_entry = new Sequeler.Partials.Entry ("", null); - - form_grid.attach (db_username_label, 0, 4, 1, 1); - form_grid.attach (db_username_entry, 1, 4, 1, 1); - - db_password_label = new Sequeler.Partials.LabelForm (_("Password:")); - db_password_entry = new Sequeler.Partials.Entry ("", null); - db_password_entry.visibility = false; - db_password_entry.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "changes-prevent-symbolic"); - db_password_entry.icon_press.connect ((pos, event) => { - if (pos == Gtk.EntryIconPosition.SECONDARY) { - db_password_entry.visibility = !db_password_entry.visibility; - } - if (db_password_entry.visibility) { - db_password_entry.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "changes-allow-symbolic"); - } else { - db_password_entry.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "changes-prevent-symbolic"); - } - }); - - form_grid.attach (db_password_label, 0, 5, 1, 1); - form_grid.attach (db_password_entry, 1, 5, 1, 1); - - db_port_label = new Sequeler.Partials.LabelForm (_("Port:")); - db_port_entry = new Sequeler.Partials.Entry ("3306", null); - - form_grid.attach (db_port_label, 0, 6, 1, 1); - form_grid.attach (db_port_entry, 1, 6, 1, 1); - - db_file_label = new Sequeler.Partials.LabelForm (_("File Path:")); - db_file_entry = new Gtk.FileChooserButton (_("Select Your SQLite File\u2026"), Gtk.FileChooserAction.OPEN); - var filter = new Gtk.FileFilter (); - filter.set_filter_name ("Database File"); - filter.add_pattern ("*.db"); - filter.add_pattern ("*.sqlite"); - filter.add_pattern ("*.sqlite3"); - db_file_entry.add_filter (filter); - - db_file_entry.selection_changed.connect (change_sensitivity); - - form_grid.attach (db_file_label, 0, 7, 1, 1); - form_grid.attach (db_file_entry, 1, 7, 1, 1); - db_file_label.visible = false; - db_file_label.no_show_all = true; - db_file_entry.visible = false; - db_file_entry.no_show_all = true; - - ssh_switch = new Gtk.Switch (); - ssh_switch_container = new Gtk.Grid (); - ssh_switch_container.add (ssh_switch); - ssh_switch_label = new Sequeler.Partials.LabelForm (_("Connect via SSH Tunnel:")); - - ssh_switch.notify["active"].connect (() => { - toggle_ssh_fields (ssh_switch.get_active ()); - }); - - ssh_switch_grid.attach (ssh_switch_label, 0, 0, 1, 1); - ssh_switch_grid.attach (ssh_switch_container, 1, 0, 1, 1); - ssh_grid.attach (ssh_switch_grid, 0, 0, 2, 1); - - ssh_host_label = new Sequeler.Partials.LabelForm (_("SSH Host:"));; - ssh_host_entry = new Sequeler.Partials.Entry ("", null); - ssh_grid.attach (ssh_host_label, 0, 2, 1, 1); - ssh_grid.attach (ssh_host_entry, 1, 2, 1, 1); - - ssh_username_label = new Sequeler.Partials.LabelForm (_("SSH Username:"));; - ssh_username_entry = new Sequeler.Partials.Entry ("", null); - ssh_grid.attach (ssh_username_label, 0, 3, 1, 1); - ssh_grid.attach (ssh_username_entry, 1, 3, 1, 1); - - ssh_password_label = new Sequeler.Partials.LabelForm (_("SSH Password:"));; - ssh_password_entry = new Sequeler.Partials.Entry ("", null); - ssh_password_entry.visibility = false; - ssh_password_entry.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "changes-prevent-symbolic"); - ssh_password_entry.icon_press.connect ((pos, event) => { - if (pos == Gtk.EntryIconPosition.SECONDARY) { - ssh_password_entry.visibility = !ssh_password_entry.visibility; - } - if (ssh_password_entry.visibility) { - ssh_password_entry.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "changes-allow-symbolic"); - } else { - ssh_password_entry.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "changes-prevent-symbolic"); - } - }); - ssh_grid.attach (ssh_password_label, 0, 4, 1, 1); - ssh_grid.attach (ssh_password_entry, 1, 4, 1, 1); - - ssh_port_label = new Sequeler.Partials.LabelForm (_("SSH Port:"));; - ssh_port_entry = new Sequeler.Partials.Entry (_("Optional"), null); - ssh_grid.attach (ssh_port_label, 0, 5, 1, 1); - ssh_grid.attach (ssh_port_entry, 1, 5, 1, 1); - - ssh_identity_file_label = new Sequeler.Partials.LabelForm(_("SSH Identity")); - ssh_identity_file_entry = new Gtk.FileChooserButton (_("Select Your Identity File\u2026"), Gtk.FileChooserAction.OPEN); - ssh_identity_file_entry.set_filename (this.get_default_ssh_identity_filename ()); - ssh_identity_file_entry.file_set.connect (this.verify_ssh_file_entry); - ssh_grid.attach(ssh_identity_file_label, 0, 6, 1, 1); - ssh_grid.attach(ssh_identity_file_entry, 1, 6, 1, 1); - - infobar_label = new Gtk.Label (infobar_label_missing_private_key); - infobar_label.show (); - - infobar = new Gtk.InfoBar (); - infobar.message_type = Gtk.MessageType.WARNING; - infobar.get_style_context ().add_class ("inline"); - infobar.get_content_area ().add (infobar_label); - infobar.show_close_button = false; - infobar.add_button (_("Generate SSH Key"), 0); - infobar.revealed = false; - - infobar.response.connect ((response) => { - if (response == 0) { - try { - ssh_switch.active = false; - AppInfo.launch_default_for_uri ("https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/", null); + public weak Sequeler.Window window { get; construct; } + private Sequeler.Services.ConnectionManager? connection_manager { get; set; default = null; } + + public Sequeler.Partials.ButtonClass test_button; + public Sequeler.Partials.ButtonClass connect_button; + + private Gtk.Label header_title; + private Gtk.ColorButton color_picker; + private Gtk.InfoBar infobar; + private Gtk.Label infobar_label; + private string infobar_label_missing_private_key = _("Missing SSH Key file!"); + private string infobar_label_missing_public_key = _("Missing SSH public key!"); + + private Sequeler.Partials.LabelForm db_file_label; + private Sequeler.Partials.LabelForm db_host_label; + private Sequeler.Partials.LabelForm db_name_label; + private Sequeler.Partials.LabelForm db_username_label; + private Sequeler.Partials.LabelForm db_password_label; + private Sequeler.Partials.LabelForm db_port_label; + + private Gtk.Entry connection_id; + private Sequeler.Partials.Entry title_entry; + private Gee.HashMap db_types; + private Gtk.ComboBox db_type_entry; + private Sequeler.Partials.Entry db_host_entry; + private Sequeler.Partials.Entry db_name_entry; + private Sequeler.Partials.Entry db_username_entry; + private Sequeler.Partials.Entry db_password_entry; + private Sequeler.Partials.Entry db_port_entry; + private Gtk.FileChooserButton db_file_entry; + + private string keyfile1; + private string keyfile2; + private Sequeler.Partials.LabelForm ssh_switch_label; + private Gtk.Grid ssh_switch_container; + private Gtk.Switch ssh_switch; + private Sequeler.Partials.LabelForm ssh_host_label; + private Sequeler.Partials.Entry ssh_host_entry; + private Sequeler.Partials.LabelForm ssh_username_label; + private Sequeler.Partials.Entry ssh_username_entry; + private Sequeler.Partials.LabelForm ssh_password_label; + private Sequeler.Partials.Entry ssh_password_entry; + private Sequeler.Partials.LabelForm ssh_port_label; + private Sequeler.Partials.Entry ssh_port_entry; + private Sequeler.Partials.LabelForm ssh_identity_file_label; + private Gtk.FileChooserButton ssh_identity_file_entry; + + private Gtk.Spinner spinner; + private Sequeler.Partials.ResponseMessage response_msg; + + enum Column { + DBTYPE + } + + enum Action { + TEST, + SAVE, + CANCEL, + CONNECT + } + + public ConnectionDialog (Sequeler.Window? parent) { + Object ( + border_width: 5, + deletable: false, + resizable: false, + title: _("Connection"), + transient_for: parent, + window: parent + ); + } + + construct { + set_id (); + build_content (); + toggle_ssh_fields (false); + build_actions (); + populate_data.begin (); + change_sensitivity (); + + response.connect (on_response); + } + + private void set_id () { + var id = settings.tot_connections; + + connection_id = new Gtk.Entry (); + connection_id.text = id.to_string (); + } + + private void build_content () { + var body = get_content_area (); + + db_types = new Gee.HashMap (); + db_types.set (0, "MySQL"); + db_types.set (1, "MariaDB"); + db_types.set (2, "PostgreSQL"); + db_types.set (3, "SQLite"); + + var header_grid = new Gtk.Grid (); + header_grid.margin_start = 30; + header_grid.margin_end = 30; + header_grid.margin_bottom = 10; + + var image = new Gtk.Image.from_icon_name ("office-database", Gtk.IconSize.DIALOG); + image.margin_end = 10; + + header_title = new Gtk.Label (_("New Connection")); + header_title.get_style_context ().add_class (Granite.STYLE_CLASS_H2_LABEL); + header_title.halign = Gtk.Align.START; + header_title.ellipsize = Pango.EllipsizeMode.END; + header_title.margin_end = 10; + header_title.set_line_wrap (true); + header_title.hexpand = true; + + color_picker = new Gtk.ColorButton.with_rgba ({ 222, 222, 222, 255 }); + color_picker.get_style_context ().add_class ("color-picker"); + color_picker.can_focus = false; + + header_grid.attach (image, 0, 0, 1, 2); + header_grid.attach (header_title, 1, 0, 1, 2); + header_grid.attach (color_picker, 2, 0, 1, 1); + + body.add (header_grid); + + var form_grid = new Gtk.Grid (); + form_grid.margin = 30; + form_grid.row_spacing = 12; + form_grid.column_spacing = 20; + + var ssh_grid = new Gtk.Grid (); + ssh_grid.margin = 30; + ssh_grid.row_spacing = 12; + ssh_grid.column_spacing = 20; + + var ssh_switch_grid = new Gtk.Grid (); + ssh_switch_grid.halign = Gtk.Align.CENTER; + ssh_switch_grid.column_spacing = 20; + ssh_switch_grid.margin_bottom = 12; + + var title_label = new Sequeler.Partials.LabelForm (_("Connection Name:")); + title_entry = new Sequeler.Partials.Entry (_("Connection's name"), _("New Connection")); + title_entry.changed.connect (() => { + header_title.label = title_entry.text; + }); + form_grid.attach (title_label, 0, 0, 1, 1); + form_grid.attach (title_entry, 1, 0, 1, 1); + + var db_type_label = new Sequeler.Partials.LabelForm (_("Database Type:")); + var list_store = new Gtk.ListStore (1, typeof (string)); + + for (int i = 0; i < db_types.size; i++) { + Gtk.TreeIter iter; + list_store.append (out iter); + list_store.set (iter, Column.DBTYPE, db_types[i]); + } + + db_type_entry = new Gtk.ComboBox.with_model (list_store); + var cell = new Gtk.CellRendererText (); + db_type_entry.pack_start (cell, false); + + db_type_entry.set_attributes (cell, "text", Column.DBTYPE); + db_type_entry.set_active (0); + db_type_entry.changed.connect (() => { + db_type_changed (); + }); + + form_grid.attach (db_type_label, 0, 1, 1, 1); + form_grid.attach (db_type_entry, 1, 1, 1, 1); + + db_host_label = new Sequeler.Partials.LabelForm (_("Host:")); + db_host_entry = new Sequeler.Partials.Entry ("127.0.0.1", null); + + form_grid.attach (db_host_label, 0, 2, 1, 1); + form_grid.attach (db_host_entry, 1, 2, 1, 1); + + db_name_label = new Sequeler.Partials.LabelForm (_("Database Name:")); + db_name_entry = new Sequeler.Partials.Entry ("", null); + db_name_entry.changed.connect (change_sensitivity); + + form_grid.attach (db_name_label, 0, 3, 1, 1); + form_grid.attach (db_name_entry, 1, 3, 1, 1); + + db_username_label = new Sequeler.Partials.LabelForm (_("Username:")); + db_username_entry = new Sequeler.Partials.Entry ("", null); + + form_grid.attach (db_username_label, 0, 4, 1, 1); + form_grid.attach (db_username_entry, 1, 4, 1, 1); + + db_password_label = new Sequeler.Partials.LabelForm (_("Password:")); + db_password_entry = new Sequeler.Partials.Entry ("", null); + db_password_entry.visibility = false; + db_password_entry.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "changes-prevent-symbolic"); + db_password_entry.icon_press.connect ((pos, event) => { + if (pos == Gtk.EntryIconPosition.SECONDARY) { + db_password_entry.visibility = !db_password_entry.visibility; + } + if (db_password_entry.visibility) { + db_password_entry.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "changes-allow-symbolic"); + } else { + db_password_entry.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "changes-prevent-symbolic"); + } + }); + + form_grid.attach (db_password_label, 0, 5, 1, 1); + form_grid.attach (db_password_entry, 1, 5, 1, 1); + + db_port_label = new Sequeler.Partials.LabelForm (_("Port:")); + db_port_entry = new Sequeler.Partials.Entry ("3306", null); + + form_grid.attach (db_port_label, 0, 6, 1, 1); + form_grid.attach (db_port_entry, 1, 6, 1, 1); + + db_file_label = new Sequeler.Partials.LabelForm (_("File Path:")); + db_file_entry = new Gtk.FileChooserButton (_("Select Your SQLite File\u2026"), Gtk.FileChooserAction.OPEN); + var filter = new Gtk.FileFilter (); + filter.set_filter_name ("Database File"); + filter.add_pattern ("*.db"); + filter.add_pattern ("*.sqlite"); + filter.add_pattern ("*.sqlite3"); + db_file_entry.add_filter (filter); + + db_file_entry.selection_changed.connect (change_sensitivity); + + form_grid.attach (db_file_label, 0, 7, 1, 1); + form_grid.attach (db_file_entry, 1, 7, 1, 1); + db_file_label.visible = false; + db_file_label.no_show_all = true; + db_file_entry.visible = false; + db_file_entry.no_show_all = true; + + ssh_switch = new Gtk.Switch (); + ssh_switch_container = new Gtk.Grid (); + ssh_switch_container.add (ssh_switch); + ssh_switch_label = new Sequeler.Partials.LabelForm (_("Connect via SSH Tunnel:")); + + ssh_switch.notify["active"].connect (() => { + toggle_ssh_fields (ssh_switch.get_active ()); + }); + + ssh_switch_grid.attach (ssh_switch_label, 0, 0, 1, 1); + ssh_switch_grid.attach (ssh_switch_container, 1, 0, 1, 1); + ssh_grid.attach (ssh_switch_grid, 0, 0, 2, 1); + + ssh_host_label = new Sequeler.Partials.LabelForm (_("SSH Host:")); + ssh_host_entry = new Sequeler.Partials.Entry ("", null); + ssh_grid.attach (ssh_host_label, 0, 2, 1, 1); + ssh_grid.attach (ssh_host_entry, 1, 2, 1, 1); + + ssh_username_label = new Sequeler.Partials.LabelForm (_("SSH Username:")); + ssh_username_entry = new Sequeler.Partials.Entry ("", null); + ssh_grid.attach (ssh_username_label, 0, 3, 1, 1); + ssh_grid.attach (ssh_username_entry, 1, 3, 1, 1); + + ssh_password_label = new Sequeler.Partials.LabelForm (_("SSH Password:")); + ssh_password_entry = new Sequeler.Partials.Entry ("", null); + ssh_password_entry.visibility = false; + ssh_password_entry.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "changes-prevent-symbolic"); + ssh_password_entry.icon_press.connect ((pos, event) => { + if (pos == Gtk.EntryIconPosition.SECONDARY) { + ssh_password_entry.visibility = !ssh_password_entry.visibility; + } + if (ssh_password_entry.visibility) { + ssh_password_entry.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "changes-allow-symbolic"); + } else { + ssh_password_entry.set_icon_from_icon_name ( + Gtk.EntryIconPosition.SECONDARY, + "changes-prevent-symbolic" + ); + } + }); + ssh_grid.attach (ssh_password_label, 0, 4, 1, 1); + ssh_grid.attach (ssh_password_entry, 1, 4, 1, 1); + + ssh_port_label = new Sequeler.Partials.LabelForm (_("SSH Port:")); + ssh_port_entry = new Sequeler.Partials.Entry (_("Optional"), null); + ssh_grid.attach (ssh_port_label, 0, 5, 1, 1); + ssh_grid.attach (ssh_port_entry, 1, 5, 1, 1); + + ssh_identity_file_label = new Sequeler.Partials.LabelForm (_("SSH Identity")); + ssh_identity_file_entry = new Gtk.FileChooserButton ( + _("Select Your Identity File\u2026"), + Gtk.FileChooserAction.OPEN + ); + ssh_identity_file_entry.set_filename (this.get_default_ssh_identity_filename ()); + ssh_identity_file_entry.file_set.connect (this.verify_ssh_file_entry); + ssh_grid.attach (ssh_identity_file_label, 0, 6, 1, 1); + ssh_grid.attach (ssh_identity_file_entry, 1, 6, 1, 1); + + infobar_label = new Gtk.Label (infobar_label_missing_private_key); + infobar_label.show (); + + infobar = new Gtk.InfoBar (); + infobar.message_type = Gtk.MessageType.WARNING; + infobar.get_style_context ().add_class ("inline"); + infobar.get_content_area ().add (infobar_label); + infobar.show_close_button = false; + infobar.add_button (_("Generate SSH Key"), 0); + infobar.revealed = false; + + infobar.response.connect ((response) => { + if (response == 0) { + try { + ssh_switch.active = false; + AppInfo.launch_default_for_uri ( + "https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/", + null + ); } catch (Error e) { warning ("%s\n", e.message); } - } - }); - ssh_grid.attach (infobar, 0, 7, 2, 1); - - - var stack_grid = new Gtk.Grid (); - stack_grid.expand = true; - stack_grid.margin_top = 20; - - var stackswitcher = new Gtk.StackSwitcher (); - stackswitcher.halign = Gtk.Align.CENTER; - stack_grid.attach (stackswitcher, 0, 0, 1, 1); - - var stack = new Gtk.Stack (); - stack.expand = true; - stackswitcher.stack = stack; - - stack.add_titled (form_grid, "connection", _("Connection")); - stack.add_titled (ssh_grid, "ssh", _("SSH Tunnel")); - stack_grid.attach (stack, 0, 1, 1, 1); - - body.add (stack_grid); - - spinner = new Gtk.Spinner (); - response_msg = new Sequeler.Partials.ResponseMessage (); - - body.add (spinner); - body.add (response_msg); - } - - private string get_default_ssh_identity_filename () { - var home_dir = Environment.get_home_dir (); - return home_dir + "/.ssh/id_rsa"; - } - - private void verify_ssh_file_entry (Gtk.FileChooserButton file_entry) { - keyfile2 = file_entry.get_filename (); - keyfile1 = keyfile2 + ".pub"; - - var public_key_exists = File.new_for_path (keyfile1).query_exists (); - var private_key_exists = File.new_for_path (keyfile2).query_exists (); - - infobar.revealed = ! private_key_exists || ! public_key_exists; - - // missing_public_key message is more specific - if (! public_key_exists && private_key_exists) { - infobar_label.set_text (infobar_label_missing_public_key); - } - else if (! private_key_exists) { - infobar_label.set_text (infobar_label_missing_private_key); - } - } - - private void toggle_ssh_fields (bool toggle) { - if (toggle) { - this.verify_ssh_file_entry (ssh_identity_file_entry); - } - else { - infobar.revealed = false; - } - - ssh_host_label.visible = toggle; - ssh_host_label.no_show_all = !toggle; - ssh_host_entry.visible = toggle; - ssh_host_entry.no_show_all = !toggle; - - ssh_username_label.visible = toggle; - ssh_username_label.no_show_all = !toggle; - ssh_username_entry.visible = toggle; - ssh_username_entry.no_show_all = !toggle; - - ssh_password_label.visible = toggle; - ssh_password_label.no_show_all = !toggle; - ssh_password_entry.visible = toggle; - ssh_password_entry.no_show_all = !toggle; - - ssh_port_label.visible = toggle; - ssh_port_label.no_show_all = !toggle; - ssh_port_entry.visible = toggle; - ssh_port_entry.no_show_all = !toggle; - - ssh_identity_file_label.visible = toggle; - ssh_identity_file_label.no_show_all = !toggle; - ssh_identity_file_entry.visible = toggle; - ssh_identity_file_entry.no_show_all = !toggle; - } - - private void build_actions () { - var cancel_button = new Sequeler.Partials.ButtonClass (_("Close"), null); - var save_button = new Sequeler.Partials.ButtonClass (_("Save Connection"), null); - - test_button = new Sequeler.Partials.ButtonClass (_("Test Connection"), null); - - connect_button = new Sequeler.Partials.ButtonClass (_("Connect"), "suggested-action"); - - add_action_widget (test_button, Action.TEST); - add_action_widget (save_button, Action.SAVE); - add_action_widget (cancel_button, Action.CANCEL); - add_action_widget (connect_button, Action.CONNECT); - } - - private async void populate_data () { - if (window.data_manager.data == null || window.data_manager.data.size == 0) { - return; - } - - var update_data = window.data_manager.data; - string? old_password = ""; - - try { - old_password = yield password_mngr.get_password_async (update_data["id"]); - } catch (Error e) { - debug ("Unable to get the password from libsecret"); - } - - connection_id.text = update_data["id"]; - title_entry.text = update_data["title"]; - - var color = Gdk.RGBA (); - color.parse (update_data["color"]); - color_picker.rgba = color; - - foreach (var entry in db_types.entries) { - if (entry.value == update_data["type"]) { - db_type_entry.set_active (entry.key); - } - } - - db_host_entry.text = update_data["host"]; - db_name_entry.text = update_data["name"]; - db_username_entry.text = update_data["username"]; - db_password_entry.text = old_password != null ? old_password : ""; - - if (update_data["file_path"] != null) { - db_file_entry.set_uri (update_data["file_path"]); - } - - if (update_data["type"] == "SQLite" && update_data["file_path"] == null) { - var update_file_path = update_data["host"] + "/" + update_data["name"] + ".db"; - - try { - db_file_entry.set_file (File.new_for_path (update_file_path)); - } catch (Error e) { - write_response (e.message); - } - } - - if (update_data["port"] != null) { - db_port_entry.text = update_data["port"]; - } - - if (update_data["has_ssh"] == "true") { - string? old_ssh_password = ""; - - try { - old_ssh_password = yield password_mngr.get_password_async (update_data["id"] + "9999"); - } catch (Error e) { - debug ("Unable to get the password from libsecret"); - } - - ssh_switch.active = bool.parse (update_data["has_ssh"]); - - ssh_host_entry.text = (update_data["ssh_host"] != null) ? update_data["ssh_host"] : ""; - ssh_username_entry.text = (update_data["ssh_username"] != null) ? update_data["ssh_username"] : ""; - ssh_password_entry.text = (old_ssh_password != null) ? old_ssh_password : ""; - ssh_port_entry.text = (update_data["ssh_port"] != null) ? update_data["ssh_port"] : ""; - if (update_data["ssh_identity_file"] != null) { - ssh_identity_file_entry.set_filename (update_data["ssh_identity_file"]); - } - } - } - - private void db_type_changed () { - var toggle = db_type_entry.get_active () == 3 ? true : false; - toggle_database_info (toggle); - change_sensitivity (); - - if (db_type_entry.get_active () == 2) { - db_port_entry.placeholder_text = "5432"; - } else { - db_port_entry.placeholder_text = "3306"; - } - } - - private void toggle_database_info (bool toggle) { - db_file_label.visible = toggle; - db_file_label.no_show_all = !toggle; - db_file_entry.visible = toggle; - db_file_entry.no_show_all = !toggle; - - db_host_label.visible = !toggle; - db_host_label.no_show_all = toggle; - db_host_entry.visible = !toggle; - db_host_entry.no_show_all = toggle; - db_name_label.visible = !toggle; - db_name_label.no_show_all = toggle; - db_name_entry.visible = !toggle; - db_name_entry.no_show_all = toggle; - db_username_label.visible = !toggle; - db_username_label.no_show_all = toggle; - db_username_entry.visible = !toggle; - db_username_entry.no_show_all = toggle; - db_password_label.visible = !toggle; - db_password_label.no_show_all = toggle; - db_password_entry.visible = !toggle; - db_password_entry.no_show_all = toggle; - db_port_label.visible = !toggle; - db_port_label.no_show_all = toggle; - db_port_entry.visible = !toggle; - db_port_entry.no_show_all = toggle; - - if (toggle) ssh_switch.active = false; - - ssh_switch_container.visible = !toggle; - ssh_switch_container.no_show_all = toggle; - ssh_switch_label.visible = !toggle; - ssh_switch_label.no_show_all = toggle; - } - - private void change_sensitivity () { - if (db_type_entry.get_active () != 3 || (db_type_entry.get_active () == 3 && db_file_entry.get_uri () != null)) { - test_button.sensitive = true; - connect_button.sensitive = true; - return; - } - - test_button.sensitive = false; - connect_button.sensitive = false; - } - - private void on_response (Gtk.Dialog source, int response_id) { - switch (response_id) { - case Action.TEST: - if (ssh_switch.active) { - open_ssh_connection.begin (false); - } else { - test_connection.begin (); - } - break; - case Action.SAVE: - save_connection (); - break; - case Action.CANCEL: - if (connection_manager != null) { - connection_manager.ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); - } - destroy (); - break; - case Action.CONNECT: - debug ("init connection"); - if (ssh_switch.active) { - open_ssh_connection.begin (true); - } else { - init_connection.begin (); - } - break; - } - } - - public void test_connection_callback () { - test_connection.begin (); - } - - public void init_connection_callback () { - init_connection.begin (); - } - - public async void open_ssh_connection (bool is_real) throws ThreadError { - toggle_spinner (true); - write_response (_("Opening SSH Tunnel\u2026")); - - var data = package_data (); - connection_manager = new Sequeler.Services.ConnectionManager (window, data); - - if (is_real) { - connection_manager.ssh_tunnel_ready.connect (init_connection_callback); - } else { - connection_manager.ssh_tunnel_ready.connect (test_connection_callback); - } - - SourceFunc callback = open_ssh_connection.callback; - - new Thread (null, () => { - try { - connection_manager.ssh_tunnel_init (is_real); - } catch (Error e) { - write_response (e.message); - } - - Idle.add ((owned) callback); - toggle_spinner (false); - return null; - }); - - yield; - } - - private async void test_connection () throws ThreadError { - toggle_spinner (true); - write_response (_("Testing Connection\u2026")); - - if (connection_manager == null) { - connection_manager = new Sequeler.Services.ConnectionManager (window, package_data ()); - } - - SourceFunc callback = test_connection.callback; - - new Thread (null, () => { - try { - connection_manager.test (); - write_response (_("Successfully Connected!")); - } catch (Error e) { - write_response (e.message); - } - - Idle.add ((owned) callback); - connection_manager = null; - toggle_spinner (false); - return null; - }); - - yield; - } - - private void save_connection () { - var data = package_data (); - - toggle_spinner (true); - write_response (_("Saving Connection\u2026")); - - window.main.library.check_add_item.begin (data); - - toggle_spinner (false); - write_response (_("Connection Saved!")); - } - - private async void init_connection () { - var data = package_data (); - var result = new Gee.HashMap (); - - toggle_spinner (true); - write_response (_("Connecting\u2026")); - - if (connection_manager == null) { - connection_manager = new Sequeler.Services.ConnectionManager (window, data); - } - - try { - result = yield connection_manager.init_connection (); - } catch (ThreadError e) { - connection_manager = null; - write_response (e.message); - toggle_spinner (false); - } - - if (result["status"] == "true") { - if (settings.save_quick) { - window.main.library.check_add_item.begin (data); - } - - window.data_manager.data = data; - window.main.connection_opened.begin (connection_manager); - - destroy (); - } else { - connection_manager = null; - write_response (result["msg"]); - toggle_spinner (false); - } - } - - private Gee.HashMap package_data () { - var packaged_data = new Gee.HashMap (); - - packaged_data.set ("id", connection_id.text); - packaged_data.set ("title", title_entry.text); - packaged_data.set ("color", color_picker.rgba.to_string ()); - packaged_data.set ("type", db_types[db_type_entry.get_active ()]); - packaged_data.set ("host", db_host_entry.text); - packaged_data.set ("name", db_name_entry.text); - packaged_data.set ("file_path", db_file_entry.get_uri () != null ? db_file_entry.get_uri () : ""); - packaged_data.set ("username", db_username_entry.text); - packaged_data.set ("password", db_password_entry.text); - packaged_data.set ("port", db_port_entry.text); - - packaged_data.set ("has_ssh", ssh_switch.active.to_string ()); - packaged_data.set ("ssh_host", ssh_switch.active ? ssh_host_entry.text : ""); - packaged_data.set ("ssh_username", ssh_switch.active ? ssh_username_entry.text : ""); - packaged_data.set ("ssh_password", ssh_switch.active ? ssh_password_entry.text : ""); - packaged_data.set ("ssh_port", ssh_switch.active ? ssh_port_entry.text : ""); - packaged_data.set ("ssh_identity_file", ssh_identity_file_entry.get_filename () ?? ""); - - return packaged_data; - } - - public void toggle_spinner (bool type) { - if (type == true) { - spinner.start (); - return; - } - - spinner.stop (); - } - - public void write_response (string? response_text) { - response_msg.label = response_text; - } + } + }); + ssh_grid.attach (infobar, 0, 7, 2, 1); + + + var stack_grid = new Gtk.Grid (); + stack_grid.expand = true; + stack_grid.margin_top = 20; + + var stackswitcher = new Gtk.StackSwitcher (); + stackswitcher.halign = Gtk.Align.CENTER; + stack_grid.attach (stackswitcher, 0, 0, 1, 1); + + var stack = new Gtk.Stack (); + stack.expand = true; + stackswitcher.stack = stack; + + stack.add_titled (form_grid, "connection", _("Connection")); + stack.add_titled (ssh_grid, "ssh", _("SSH Tunnel")); + stack_grid.attach (stack, 0, 1, 1, 1); + + body.add (stack_grid); + + spinner = new Gtk.Spinner (); + response_msg = new Sequeler.Partials.ResponseMessage (); + + body.add (spinner); + body.add (response_msg); + } + + private string get_default_ssh_identity_filename () { + var home_dir = Environment.get_home_dir (); + return home_dir + "/.ssh/id_rsa"; + } + + private void verify_ssh_file_entry (Gtk.FileChooserButton file_entry) { + keyfile2 = file_entry.get_filename (); + keyfile1 = keyfile2 + ".pub"; + + var public_key_exists = File.new_for_path (keyfile1).query_exists (); + var private_key_exists = File.new_for_path (keyfile2).query_exists (); + + infobar.revealed = ! private_key_exists || ! public_key_exists; + + // missing_public_key message is more specific + if (! public_key_exists && private_key_exists) { + infobar_label.set_text (infobar_label_missing_public_key); + } + else if (! private_key_exists) { + infobar_label.set_text (infobar_label_missing_private_key); + } + } + + private void toggle_ssh_fields (bool toggle) { + if (toggle) { + this.verify_ssh_file_entry (ssh_identity_file_entry); + } + else { + infobar.revealed = false; + } + + ssh_host_label.visible = toggle; + ssh_host_label.no_show_all = !toggle; + ssh_host_entry.visible = toggle; + ssh_host_entry.no_show_all = !toggle; + + ssh_username_label.visible = toggle; + ssh_username_label.no_show_all = !toggle; + ssh_username_entry.visible = toggle; + ssh_username_entry.no_show_all = !toggle; + + ssh_password_label.visible = toggle; + ssh_password_label.no_show_all = !toggle; + ssh_password_entry.visible = toggle; + ssh_password_entry.no_show_all = !toggle; + + ssh_port_label.visible = toggle; + ssh_port_label.no_show_all = !toggle; + ssh_port_entry.visible = toggle; + ssh_port_entry.no_show_all = !toggle; + + ssh_identity_file_label.visible = toggle; + ssh_identity_file_label.no_show_all = !toggle; + ssh_identity_file_entry.visible = toggle; + ssh_identity_file_entry.no_show_all = !toggle; + } + + private void build_actions () { + var cancel_button = new Sequeler.Partials.ButtonClass (_("Close"), null); + var save_button = new Sequeler.Partials.ButtonClass (_("Save Connection"), null); + + test_button = new Sequeler.Partials.ButtonClass (_("Test Connection"), null); + + connect_button = new Sequeler.Partials.ButtonClass (_("Connect"), "suggested-action"); + + add_action_widget (test_button, Action.TEST); + add_action_widget (save_button, Action.SAVE); + add_action_widget (cancel_button, Action.CANCEL); + add_action_widget (connect_button, Action.CONNECT); + } + + private async void populate_data () { + if (window.data_manager.data == null || window.data_manager.data.size == 0) { + return; + } + + var update_data = window.data_manager.data; + string? old_password = ""; + + try { + old_password = yield password_mngr.get_password_async (update_data["id"]); + } catch (Error e) { + debug ("Unable to get the password from libsecret"); + } + + connection_id.text = update_data["id"]; + title_entry.text = update_data["title"]; + + var color = Gdk.RGBA (); + color.parse (update_data["color"]); + color_picker.rgba = color; + + foreach (var entry in db_types.entries) { + if (entry.value == update_data["type"]) { + db_type_entry.set_active (entry.key); + } + } + + db_host_entry.text = update_data["host"]; + db_name_entry.text = update_data["name"]; + db_username_entry.text = update_data["username"]; + db_password_entry.text = old_password != null ? old_password : ""; + + if (update_data["file_path"] != null) { + db_file_entry.set_uri (update_data["file_path"]); + } + + if (update_data["type"] == "SQLite" && update_data["file_path"] == null) { + var update_file_path = update_data["host"] + "/" + update_data["name"] + ".db"; + + try { + db_file_entry.set_file (File.new_for_path (update_file_path)); + } catch (Error e) { + write_response (e.message); + } + } + + if (update_data["port"] != null) { + db_port_entry.text = update_data["port"]; + } + + if (update_data["has_ssh"] == "true") { + string? old_ssh_password = ""; + + try { + old_ssh_password = yield password_mngr.get_password_async (update_data["id"] + "9999"); + } catch (Error e) { + debug ("Unable to get the password from libsecret"); + } + + ssh_switch.active = bool.parse (update_data["has_ssh"]); + + ssh_host_entry.text = (update_data["ssh_host"] != null) ? update_data["ssh_host"] : ""; + ssh_username_entry.text = (update_data["ssh_username"] != null) ? update_data["ssh_username"] : ""; + ssh_password_entry.text = (old_ssh_password != null) ? old_ssh_password : ""; + ssh_port_entry.text = (update_data["ssh_port"] != null) ? update_data["ssh_port"] : ""; + if (update_data["ssh_identity_file"] != null) { + ssh_identity_file_entry.set_filename (update_data["ssh_identity_file"]); + } + } + } + + private void db_type_changed () { + var toggle = db_type_entry.get_active () == 3 ? true : false; + toggle_database_info (toggle); + change_sensitivity (); + + if (db_type_entry.get_active () == 2) { + db_port_entry.placeholder_text = "5432"; + } else { + db_port_entry.placeholder_text = "3306"; + } + } + + private void toggle_database_info (bool toggle) { + db_file_label.visible = toggle; + db_file_label.no_show_all = !toggle; + db_file_entry.visible = toggle; + db_file_entry.no_show_all = !toggle; + + db_host_label.visible = !toggle; + db_host_label.no_show_all = toggle; + db_host_entry.visible = !toggle; + db_host_entry.no_show_all = toggle; + db_name_label.visible = !toggle; + db_name_label.no_show_all = toggle; + db_name_entry.visible = !toggle; + db_name_entry.no_show_all = toggle; + db_username_label.visible = !toggle; + db_username_label.no_show_all = toggle; + db_username_entry.visible = !toggle; + db_username_entry.no_show_all = toggle; + db_password_label.visible = !toggle; + db_password_label.no_show_all = toggle; + db_password_entry.visible = !toggle; + db_password_entry.no_show_all = toggle; + db_port_label.visible = !toggle; + db_port_label.no_show_all = toggle; + db_port_entry.visible = !toggle; + db_port_entry.no_show_all = toggle; + + if (toggle) ssh_switch.active = false; + + ssh_switch_container.visible = !toggle; + ssh_switch_container.no_show_all = toggle; + ssh_switch_label.visible = !toggle; + ssh_switch_label.no_show_all = toggle; + } + + private void change_sensitivity () { + if (db_type_entry.get_active () != 3 + || (db_type_entry.get_active () == 3 + && db_file_entry.get_uri () != null) + ) { + test_button.sensitive = true; + connect_button.sensitive = true; + return; + } + + test_button.sensitive = false; + connect_button.sensitive = false; + } + + private void on_response (Gtk.Dialog source, int response_id) { + switch (response_id) { + case Action.TEST: + if (ssh_switch.active) { + open_ssh_connection.begin (false); + } else { + test_connection.begin (); + } + break; + case Action.SAVE: + save_connection (); + break; + case Action.CANCEL: + if (connection_manager != null) { + connection_manager.ssh_tunnel_close (Log.FILE + ":" + Log.LINE.to_string ()); + } + destroy (); + break; + case Action.CONNECT: + debug ("init connection"); + if (ssh_switch.active) { + open_ssh_connection.begin (true); + } else { + init_connection.begin (); + } + break; + } + } + + public void test_connection_callback () { + test_connection.begin (); + } + + public void init_connection_callback () { + init_connection.begin (); + } + + public async void open_ssh_connection (bool is_real) throws ThreadError { + toggle_spinner (true); + write_response (_("Opening SSH Tunnel\u2026")); + + var data = package_data (); + connection_manager = new Sequeler.Services.ConnectionManager (window, data); + + if (is_real) { + connection_manager.ssh_tunnel_ready.connect (init_connection_callback); + } else { + connection_manager.ssh_tunnel_ready.connect (test_connection_callback); + } + + SourceFunc callback = open_ssh_connection.callback; + + new Thread (null, () => { + try { + connection_manager.ssh_tunnel_init (is_real); + } catch (Error e) { + write_response (e.message); + } + + Idle.add ((owned) callback); + toggle_spinner (false); + return null; + }); + + yield; + } + + private async void test_connection () throws ThreadError { + toggle_spinner (true); + write_response (_("Testing Connection\u2026")); + + if (connection_manager == null) { + connection_manager = new Sequeler.Services.ConnectionManager (window, package_data ()); + } + + SourceFunc callback = test_connection.callback; + + new Thread (null, () => { + try { + connection_manager.test (); + write_response (_("Successfully Connected!")); + } catch (Error e) { + write_response (e.message); + } + + Idle.add ((owned) callback); + connection_manager = null; + toggle_spinner (false); + return null; + }); + + yield; + } + + private void save_connection () { + var data = package_data (); + + toggle_spinner (true); + write_response (_("Saving Connection\u2026")); + + window.main.library.check_add_item.begin (data); + + toggle_spinner (false); + write_response (_("Connection Saved!")); + } + + private async void init_connection () { + var data = package_data (); + var result = new Gee.HashMap (); + + toggle_spinner (true); + write_response (_("Connecting\u2026")); + + if (connection_manager == null) { + connection_manager = new Sequeler.Services.ConnectionManager (window, data); + } + + try { + result = yield connection_manager.init_connection (); + } catch (ThreadError e) { + connection_manager = null; + write_response (e.message); + toggle_spinner (false); + } + + if (result["status"] == "true") { + if (settings.save_quick) { + window.main.library.check_add_item.begin (data); + } + + window.data_manager.data = data; + window.main.connection_opened.begin (connection_manager); + + destroy (); + } else { + connection_manager = null; + write_response (result["msg"]); + toggle_spinner (false); + } + } + + private Gee.HashMap package_data () { + var packaged_data = new Gee.HashMap (); + + packaged_data.set ("id", connection_id.text); + packaged_data.set ("title", title_entry.text); + packaged_data.set ("color", color_picker.rgba.to_string ()); + packaged_data.set ("type", db_types[db_type_entry.get_active ()]); + packaged_data.set ("host", db_host_entry.text); + packaged_data.set ("name", db_name_entry.text); + packaged_data.set ("file_path", db_file_entry.get_uri () != null ? db_file_entry.get_uri () : ""); + packaged_data.set ("username", db_username_entry.text); + packaged_data.set ("password", db_password_entry.text); + packaged_data.set ("port", db_port_entry.text); + + packaged_data.set ("has_ssh", ssh_switch.active.to_string ()); + packaged_data.set ("ssh_host", ssh_switch.active ? ssh_host_entry.text : ""); + packaged_data.set ("ssh_username", ssh_switch.active ? ssh_username_entry.text : ""); + packaged_data.set ("ssh_password", ssh_switch.active ? ssh_password_entry.text : ""); + packaged_data.set ("ssh_port", ssh_switch.active ? ssh_port_entry.text : ""); + packaged_data.set ("ssh_identity_file", ssh_identity_file_entry.get_filename () ?? ""); + + return packaged_data; + } + + public void toggle_spinner (bool type) { + if (type == true) { + spinner.start (); + return; + } + + spinner.stop (); + } + + public void write_response (string? response_text) { + response_msg.label = response_text; + } } diff --git a/src/Window.vala b/src/Window.vala index f01a7965..581bd345 100644 --- a/src/Window.vala +++ b/src/Window.vala @@ -20,86 +20,86 @@ */ public class Sequeler.Window : Gtk.ApplicationWindow { - public weak Sequeler.Application app { get; construct; } + public weak Sequeler.Application app { get; construct; } - public Sequeler.Layouts.Main main; - public Sequeler.Layouts.HeaderBar headerbar; - public Sequeler.Services.ActionManager action_manager; - public Sequeler.Services.DataManager data_manager; - public Sequeler.Widgets.ConnectionDialog? connection_dialog = null; + public Sequeler.Layouts.Main main; + public Sequeler.Layouts.HeaderBar headerbar; + public Sequeler.Services.ActionManager action_manager; + public Sequeler.Services.DataManager data_manager; + public Sequeler.Widgets.ConnectionDialog? connection_dialog = null; - public Gtk.AccelGroup accel_group { get; construct; } + public Gtk.AccelGroup accel_group { get; construct; } - public Window (Sequeler.Application sequeler_app) { - Object ( - application: sequeler_app, - app: sequeler_app, - icon_name: Constants.PROJECT_NAME - ); - } + public Window (Sequeler.Application sequeler_app) { + Object ( + application: sequeler_app, + app: sequeler_app, + icon_name: Constants.PROJECT_NAME + ); + } - construct { - accel_group = new Gtk.AccelGroup (); - add_accel_group (accel_group); + construct { + accel_group = new Gtk.AccelGroup (); + add_accel_group (accel_group); - main = new Sequeler.Layouts.Main (this); - headerbar = new Sequeler.Layouts.HeaderBar (this); - action_manager = new Sequeler.Services.ActionManager (app, this); - data_manager = new Sequeler.Services.DataManager (); + main = new Sequeler.Layouts.Main (this); + headerbar = new Sequeler.Layouts.HeaderBar (this); + action_manager = new Sequeler.Services.ActionManager (app, this); + data_manager = new Sequeler.Services.DataManager (); - build_ui (); + build_ui (); - move (settings.pos_x, settings.pos_y); - resize (settings.window_width, settings.window_height); + move (settings.pos_x, settings.pos_y); + resize (settings.window_width, settings.window_height); - show_app (); - } + show_app (); + } - public Sequeler.Window get_instance () { - return this; - } + public Sequeler.Window get_instance () { + return this; + } - private void build_ui () { - Gtk.Settings.get_default ().gtk_application_prefer_dark_theme = settings.dark_theme; + private void build_ui () { + Gtk.Settings.get_default ().gtk_application_prefer_dark_theme = settings.dark_theme; - var css_provider = new Gtk.CssProvider (); - css_provider.load_from_resource ("/com/github/alecaddd/sequeler/stylesheet.css"); + var css_provider = new Gtk.CssProvider (); + css_provider.load_from_resource ("/com/github/alecaddd/sequeler/stylesheet.css"); - Gtk.StyleContext.add_provider_for_screen ( - Gdk.Screen.get_default (), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - ); + Gtk.StyleContext.add_provider_for_screen ( + Gdk.Screen.get_default (), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION + ); - set_titlebar (headerbar); - set_border_width (0); + set_titlebar (headerbar); + set_border_width (0); - delete_event.connect (before_destroy); + delete_event.connect (before_destroy); - add (main); - } + add (main); + } - public bool before_destroy () { - update_status (); - app.get_active_window ().destroy (); - return true; - } + public bool before_destroy () { + update_status (); + app.get_active_window ().destroy (); + return true; + } - private void update_status () { - int width, height, x, y; + private void update_status () { + int width, height, x, y; - get_size (out width, out height); - get_position (out x, out y); + get_size (out width, out height); + get_position (out x, out y); - settings.pos_x = x; - settings.pos_y = y; - settings.window_width = width; - settings.window_height = height; - settings.sidebar_width = main.get_position (); - settings.query_area = main.database_view.query.panels.get_position (); - } + settings.pos_x = x; + settings.pos_y = y; + settings.window_width = width; + settings.window_height = height; + settings.sidebar_width = main.get_position (); + settings.query_area = main.database_view.query.panels.get_position (); + } - public void show_app () { - show_all (); - show (); - present (); - } + public void show_app () { + show_all (); + show (); + present (); + } }