diff --git a/docs/en_US/keyboard_shortcuts.rst b/docs/en_US/keyboard_shortcuts.rst index d4a3a558f..1f0ee04c9 100644 --- a/docs/en_US/keyboard_shortcuts.rst +++ b/docs/en_US/keyboard_shortcuts.rst @@ -26,7 +26,20 @@ When using main browser window, the following keyboard shortcuts are available: | Alt+Shift+[ | Move tabbed panel backward/forward | | Alt+Shift+] | | +---------------------------+--------------------------------------------------------+ - +| Alt+Shift+Q | Open the Query Tool in the current database | ++---------------------------+--------------------------------------------------------+ +| Alt+Shift+V | View Data in the selected table/view | ++---------------------------+--------------------------------------------------------+ +| Alt+Shift+C | Open the context menu | ++---------------------------+--------------------------------------------------------+ +| Alt+Shift+N | Create an object | ++---------------------------+--------------------------------------------------------+ +| Alt+Shift+E | Edit object properties | ++---------------------------+--------------------------------------------------------+ +| Alt+Shift+D | Delete the object | ++---------------------------+--------------------------------------------------------+ +| Alt+Shift+G | Direct debugging | ++---------------------------+--------------------------------------------------------+ **SQL Editors** diff --git a/web/pgadmin/browser/__init__.py b/web/pgadmin/browser/__init__.py index d3df08453..04065f5c1 100644 --- a/web/pgadmin/browser/__init__.py +++ b/web/pgadmin/browser/__init__.py @@ -324,6 +324,112 @@ class BrowserModule(PgAdminModule): category_label=gettext('Keyboard shortcuts'), fields=fields ) + + self.preference.register( + 'keyboard_shortcuts', + 'sub_menu_query_tool', + gettext('Open query tool'), + 'keyboardshortcut', + { + 'alt': True, + 'shift': True, + 'control': False, + 'key': {'key_code': 81, 'char': 'q'} + }, + category_label=gettext('Keyboard shortcuts'), + fields=fields + ) + + self.preference.register( + 'keyboard_shortcuts', + 'sub_menu_view_data', + gettext('View data'), + 'keyboardshortcut', + { + 'alt': True, + 'shift': True, + 'control': False, + 'key': {'key_code': 86, 'char': 'v'} + }, + category_label=gettext('Keyboard shortcuts'), + fields=fields + ) + + self.preference.register( + 'keyboard_shortcuts', + 'sub_menu_create', + gettext('Create object'), + 'keyboardshortcut', + { + 'alt': True, + 'shift': True, + 'control': False, + 'key': {'key_code': 78, 'char': 'n'} + }, + category_label=gettext('Keyboard shortcuts'), + fields=fields + ) + + self.preference.register( + 'keyboard_shortcuts', + 'sub_menu_properties', + gettext('Edit object properties'), + 'keyboardshortcut', + { + 'alt': True, + 'shift': True, + 'control': False, + 'key': {'key_code': 69, 'char': 'e'} + }, + category_label=gettext('Keyboard shortcuts'), + fields=fields + ) + + self.preference.register( + 'keyboard_shortcuts', + 'sub_menu_delete', + gettext('Delete object'), + 'keyboardshortcut', + { + 'alt': True, + 'shift': True, + 'control': False, + 'key': {'key_code': 68, 'char': 'd'} + }, + category_label=gettext('Keyboard shortcuts'), + fields=fields + ) + + self.preference.register( + 'keyboard_shortcuts', + 'context_menu', + gettext('Open context menu'), + 'keyboardshortcut', + { + 'alt': True, + 'shift': True, + 'control': False, + 'key': {'key_code': 67, 'char': 'c'} + }, + category_label=gettext('Keyboard shortcuts'), + fields=fields + ) + + self.preference.register( + 'keyboard_shortcuts', + 'direct_debugging', + gettext('Direct debugging'), + 'keyboardshortcut', + { + 'alt': True, + 'shift': True, + 'control': False, + 'key': {'key_code': 71, 'char': 'g'} + }, + category_label=gettext('Keyboard shortcuts'), + fields=fields + ) + def get_exposed_url_endpoints(self): """ Returns: diff --git a/web/pgadmin/browser/static/js/browser.js b/web/pgadmin/browser/static/js/browser.js index a6213902e..13af4ea0e 100644 --- a/web/pgadmin/browser/static/js/browser.js +++ b/web/pgadmin/browser/static/js/browser.js @@ -428,6 +428,12 @@ define('pgadmin.browser', [ items: context_menu, }; }, + events: { + hide: function() { + // Return focus to the tree + obj.keyboardNavigation.bindLeftTree(); + }, + }, }); // Treeview event handler diff --git a/web/pgadmin/browser/static/js/keyboard.js b/web/pgadmin/browser/static/js/keyboard.js index 250d0d348..95b77dbf5 100644 --- a/web/pgadmin/browser/static/js/keyboard.js +++ b/web/pgadmin/browser/static/js/keyboard.js @@ -12,14 +12,22 @@ function(_, S, pgAdmin, $, Mousetrap) { init: function() { Mousetrap.reset(); if (pgBrowser.preferences_cache.length > 0) { + var getShortcut = this.parseShortcutValue; this.keyboardShortcut = { - 'file_shortcut': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'main_menu_file').value), - 'object_shortcut': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'main_menu_object').value), - 'tools_shortcut': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'main_menu_tools').value), - 'help_shortcut': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'main_menu_help').value), - 'left_tree_shortcut': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'browser_tree').value), - 'tabbed_panel_backward': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'tabbed_panel_backward').value), - 'tabbed_panel_forward': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'tabbed_panel_forward').value) + 'file_shortcut': getShortcut(pgBrowser.get_preference('browser', 'main_menu_file').value), + 'object_shortcut': getShortcut(pgBrowser.get_preference('browser', 'main_menu_object').value), + 'tools_shortcut': getShortcut(pgBrowser.get_preference('browser', 'main_menu_tools').value), + 'help_shortcut': getShortcut(pgBrowser.get_preference('browser', 'main_menu_help').value), + 'left_tree_shortcut': getShortcut(pgBrowser.get_preference('browser', 'browser_tree').value), + 'tabbed_panel_backward': getShortcut(pgBrowser.get_preference('browser', 'tabbed_panel_backward').value), + 'tabbed_panel_forward': getShortcut(pgBrowser.get_preference('browser', 'tabbed_panel_forward').value), + 'sub_menu_query_tool': getShortcut(pgBrowser.get_preference('browser', 'sub_menu_query_tool').value), + 'sub_menu_view_data': getShortcut(pgBrowser.get_preference('browser', 'sub_menu_view_data').value), + 'sub_menu_properties': getShortcut(pgBrowser.get_preference('browser', 'sub_menu_properties').value), + 'sub_menu_create': getShortcut(pgBrowser.get_preference('browser', 'sub_menu_create').value), + 'sub_menu_delete': getShortcut(pgBrowser.get_preference('browser', 'sub_menu_delete').value), + 'context_menu': getShortcut(pgBrowser.get_preference('browser', 'context_menu').value), + 'direct_debugging': getShortcut(pgBrowser.get_preference('browser', 'direct_debugging').value) }; this.shortcutMethods = { 'bindMainMenu': {'shortcuts': [this.keyboardShortcut.file_shortcut, @@ -29,7 +37,14 @@ function(_, S, pgAdmin, $, Mousetrap) { 'bindMainMenuLeft': {'shortcuts': 'left', 'bindElem': '.pg-navbar'}, // Main menu 'bindMainMenuRight': {'shortcuts': 'right', 'bindElem': '.pg-navbar'}, // Main menu 'bindMainMenuUpDown': {'shortcuts': ['up', 'down']}, // Main menu - 'bindLeftTree': {'shortcuts': this.keyboardShortcut.left_tree_shortcut}, // Main menu + 'bindLeftTree': {'shortcuts': this.keyboardShortcut.left_tree_shortcut}, // Main menu, + 'bindSubMenuQueryTool': {'shortcuts': this.keyboardShortcut.sub_menu_query_tool}, // Sub menu - Open Query Tool, + 'bindSubMenuViewData': {'shortcuts': this.keyboardShortcut.sub_menu_view_data}, // Sub menu - Open View Data, + 'bindSubMenuProperties': {'shortcuts': this.keyboardShortcut.sub_menu_properties}, // Sub menu - Edit Properties, + 'bindSubMenuCreate': {'shortcuts': this.keyboardShortcut.sub_menu_create}, // Sub menu - Create Object, + 'bindSubMenuDelete': {'shortcuts': this.keyboardShortcut.sub_menu_delete}, // Sub menu - Delete object, + 'bindContextMenu': {'shortcuts': this.keyboardShortcut.context_menu}, // Sub menu - Open context menu, + 'bindDirectDebugging': {'shortcuts': this.keyboardShortcut.direct_debugging} // Sub menu - Direct Debugging }; this.bindShortcuts(); } @@ -41,6 +56,7 @@ function(_, S, pgAdmin, $, Mousetrap) { }); }, _bindWithMousetrap: function(shortcuts, callback, bindElem) { + var self = this; if (bindElem) { var elem = document.querySelector(bindElem); Mousetrap(elem).bind(shortcuts, function() { @@ -48,7 +64,7 @@ function(_, S, pgAdmin, $, Mousetrap) { }.bind(elem)); } else { Mousetrap.bind(shortcuts, function() { - callback.apply(this, arguments); + callback.apply(self, arguments); }); } }, @@ -60,7 +76,7 @@ function(_, S, pgAdmin, $, Mousetrap) { else Mousetrap.unbind(shortcut); }, bindMainMenu: function(e, combo) { - var shortcut_obj = pgAdmin.Browser.keyboardNavigation.keyboardShortcut; + var shortcut_obj = this.keyboardShortcut; if (combo == shortcut_obj.file_shortcut) $('#mnu_file a.dropdown-toggle').dropdown('toggle'); if (combo == shortcut_obj.object_shortcut) $('#mnu_obj a.dropdown-toggle').first().dropdown('toggle'); if (combo == shortcut_obj.tools_shortcut) $('#mnu_tools a.dropdown-toggle').dropdown('toggle'); @@ -73,7 +89,7 @@ function(_, S, pgAdmin, $, Mousetrap) { prevPanel = 1, activePanelId = 0, activePanelFlag = false, - shortcut_obj = pgAdmin.Browser.keyboardNavigation.keyboardShortcut; + shortcut_obj = this.keyboardShortcut; _.each(pgAdmin.Browser.docker.findPanels(), function(panel, index){ if (panel.isVisible() && !activePanelFlag && panel._type != 'browser'){ @@ -138,11 +154,83 @@ function(_, S, pgAdmin, $, Mousetrap) { } }, bindLeftTree: function() { - var t = pgAdmin.Browser.tree, - item = t.selected().length > 0 ? t.selected() : t.first(); + var tree = this.getTreeDetails(); + $('#tree').focus(); - t.focus(item); - t.select(item); + tree.t.focus(tree.i); + tree.t.select(tree.i); + }, + bindSubMenuQueryTool: function() { + var tree = this.getTreeDetails(); + + if (!tree.d) + return; + + // Call data grid method to render query tool + pgAdmin.DataGrid.show_query_tool('', tree.i); + }, + bindSubMenuViewData: function() { + var tree = this.getTreeDetails(); + + if (!tree.d) + return; + + // Call data grid method to render view data + pgAdmin.DataGrid.show_data_grid({'mnuid': 1}, tree.i); + }, + bindSubMenuProperties: function() { + var tree = this.getTreeDetails(); + + if (!tree.d || pgAdmin.Browser.Nodes[tree.t.itemData(tree.i)._type].collection_node == true) + return; + + // Open properties dialog in edit mode + pgAdmin.Browser.Node.callbacks.show_obj_properties.call( + pgAdmin.Browser.Nodes[tree.t.itemData(tree.i)._type], {action: 'edit'} + ); + }, + bindSubMenuCreate: function() { + var tree = this.getTreeDetails(); + + if (!tree.d || pgAdmin.Browser.Nodes[tree.t.itemData(tree.i)._type].collection_node == true) + return; + + // Open properties dialog in edit mode + pgAdmin.Browser.Node.callbacks.show_obj_properties.call( + pgAdmin.Browser.Nodes[tree.t.itemData(tree.i)._type], {action: 'create'} + ); + }, + bindSubMenuDelete: function() { + var tree = this.getTreeDetails(); + + if (!tree.d || pgAdmin.Browser.Nodes[tree.t.itemData(tree.i)._type].collection_node == true) + return; + + // Call delete object callback + pgAdmin.Browser.Node.callbacks.delete_obj.call(pgAdmin.Browser.Nodes[tree.t.itemData(tree.i)._type]); + }, + bindContextMenu: function(e) { + var tree = this.getTreeDetails(), + e = window.event, + left = $(e.srcElement).find('.aciTreeEntry').position().left + 70, + top = $(e.srcElement).find('.aciTreeEntry').position().top + 70; + + tree.t.blur(tree.i); + $('#tree').blur(); + // Call context menu and set position + var ctx = tree.i.children().contextMenu({x: left, y:top}); + }, + bindDirectDebugging: function(e) { + var tree = this.getTreeDetails(), + type = tree.t.itemData(tree.i)._type; + + if (!tree.d || (type != 'function' && type != 'procedure')) + return; + + if(pgAdmin.Tools.Debugger.can_debug(tree.d, tree.i, {'debug_type': 'direct'})) { + // Call debugger callback + pgAdmin.Tools.Debugger.get_function_information(pgAdmin.Browser.Nodes[type]); + } }, parseShortcutValue: function(obj) { var shortcut = ""; @@ -151,6 +239,17 @@ function(_, S, pgAdmin, $, Mousetrap) { if (obj.control) { shortcut += 'ctrl+'; } shortcut += String.fromCharCode(obj.key.key_code).toLowerCase(); return shortcut; + }, + getTreeDetails: function() { + var t = pgAdmin.Browser.tree, + i = t.selected().length > 0 ? t.selected() : t.first(), + d = i && i.length == 1 ? t.itemData(i) : undefined; + + return { + t: t, + i: i, + d: d + } } }); diff --git a/web/pgadmin/browser/static/js/node.js b/web/pgadmin/browser/static/js/node.js index a57b2ca36..250bd5db0 100644 --- a/web/pgadmin/browser/static/js/node.js +++ b/web/pgadmin/browser/static/js/node.js @@ -519,7 +519,7 @@ define('pgadmin.browser.node', [ **/ show_obj_properties: function(args, item) { var t = pgBrowser.tree, - i = args.item || item || t.selected(), + i = (args && args.item) || item || t.selected(), d = i && i.length == 1 ? t.itemData(i) : undefined, o = this, l = o.title.apply(this, [d]);