Introduced an ‘Editor’ preferences category and migrated all editor related settings into it. #8861

pull/8995/head
Pravesh Sharma 2025-07-28 14:09:16 +05:30 committed by GitHub
parent e73d8f4532
commit 62eb330423
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 599 additions and 438 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 KiB

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 261 KiB

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

After

Width:  |  Height:  |  Size: 179 KiB

View File

@ -262,6 +262,90 @@ Use the fields on the *Options* panel to manage ERD preferences.
It allows to set the limit on the depth level pgAdmin should traverse
to find the relations. Use -1 to set no limit.
The Editor Node
*****************
Expand the *Editor* node to access panels that allow you to specify your preferences
for the editor across pgAdmin 4
.. image:: images/preferences_editor_keyboard_shortcuts.png
:alt: Preferences editor keyboard shortcuts section
:align: center
Use the fields on the *Keyboard shortcuts* panel to configure shortcuts for the
editor.
.. image:: images/preferences_editor_options.png
:alt: Preferences editor options section
:align: center
Use the fields on the *Options* panel to manage editor preferences.
* Use the *Auto-indent new line?* switch to specify whether the editor will
automatically indent new lines. When set to *True*, the editor will indent
new lines according to the indentation of the previous line.
* When the *Brace matching?* switch is set to *True*, the editor will highlight
pairs of matched braces.
* When the *Code folding?* switch is set to *False*, the editor will disable
code folding. Disabling will improve editor performance with large files.
* Use the *Font family* field to be used for all SQL editors. The specified
font should already be installed on your system. If the font is not found,
the editor will fall back to the default font, Source Code Pro.
* When the *Font ligatures?* switch is set to *True*, ligatures will be
enabled in SQL text boxes and editors provided the configured font family
supports them.
* Use the *Font size* field to specify the font size that will be used in text
boxes and editors.
* When the *Highlight selection matches?* switch is set to *True*, the editor will
highlight matched selected text.
* When the *Insert bracket pairs?* switch is set to *True*, the editor will
automatically insert paired brackets.
* When the *Line wrapping* switch is set to *True*, the editor will implement
line-wrapping behavior.
* When the *Plain text mode?* switch is set to *True*, the editor mode will be
changed to text/plain. Keyword highlighting and code folding will be disabled.
This will improve editor performance with large files.
.. image:: images/preferences_editor_sql_formatting.png
:alt: Preferences SQL Formatting section
:align: center
Use the fields on the *SQL formatting* panel to specify your preferences for
reformatting of SQL.
* Use the *Data type case* option to specify whether to change data types
into upper, lower, or preserve case.
* Use the *Expression width* option to specify maximum number of characters
in parenthesized expressions to be kept on single line.
* Use the *Function case* option to specify whether to change function
names into upper, lower, or preserve case.
* Use the *Identifier case* option to specify whether to change identifiers
(object names) into upper, lower, or capitalized case.
* Use the *Keyword case* option to specify whether to change keywords into
upper, lower, or preserve case.
* Use *Lines between queries* to specify how many empty lines to leave
between SQL statements. If set to zero it puts no new line.
* Use *Logical operator new line* to specify newline placement before or
after logical operators (AND, OR, XOR).
* Use *New line before semicolon?* to specify whether to place query
separator (;) on a separate line.
* Use the *Spaces around operators?* option to specify whether or not to include
spaces on either side of operators.
* Use the *Tab size* option to specify the number of spaces per tab or indent.
* Use the *Use spaces?* option to select whether to use spaces or tabs when
indenting.
The Graphs Node
***************
@ -427,46 +511,6 @@ Tool display.
* When the *Show query success notification?* switch is set to *True*, the Query Tool
will show notifications on successful query execution.
.. image:: images/preferences_sql_editor.png
:alt: Preferences sqleditor editor settings
:align: center
Use the fields on the *Editor* panel to change settings of the query editor.
* Use the *Auto-indent new line?* switch to specify whether the editor will
automatically indent new lines. When set to *True*, the editor will indent
new lines according to the indentation of the previous line.
* When the *Brace matching?* switch is set to *True*, the editor will highlight
pairs of matched braces.
* When the *Code folding?* switch is set to *False*, the editor will disable
code folding. Disabling will improve editor performance with large files.
* Use the *Font family* field to be used for all SQL editors. The specified
font should already be installed on your system. If the font is not found,
the editor will fall back to the default font, Source Code Pro.
* When the *Font ligatures?* switch is set to *True*, ligatures will be
enabled in SQL text boxes and editors provided the configured font family
supports them.
* Use the *Font size* field to specify the font size that will be used in text
boxes and editors.
* When the *Highlight selection matches?* switch is set to *True*, the editor will
highlight matched selected text.
* When the *Insert bracket pairs?* switch is set to *True*, the editor will
automatically insert paired brackets.
* When the *Line wrapping* switch is set to *True*, the editor will implement
line-wrapping behavior.
* When the *Plain text mode?* switch is set to *True*, the editor mode will be
changed to text/plain. Keyword highlighting and code folding will be disabled.
This will improve editor performance with large files.
.. image:: images/preferences_sql_explain.png
:alt: Preferences sqleditor explain options
:align: center
@ -592,34 +636,6 @@ preferences for copied data.
Use the fields on the *Keyboard shortcuts* panel to configure shortcuts for the
Query Tool window navigation.
.. image:: images/preferences_sql_formatting.png
:alt: Preferences SQL Formatting section
:align: center
Use the fields on the *SQL formatting* panel to specify your preferences for
reformatting of SQL.
* Use the *Data type case* option to specify whether to change data types
into upper, lower, or preserve case.
* Use the *Expression width* option to specify maximum number of characters
in parenthesized expressions to be kept on single line.
* Use the *Function case* option to specify whether to change function
names into upper, lower, or preserve case.
* Use the *Identifier case* option to specify whether to change identifiers
(object names) into upper, lower, or capitalized case.
* Use the *Keyword case* option to specify whether to change keywords into
upper, lower, or preserve case.
* Use *Lines between queries* to specify how many empty lines to leave
between SQL statements. If set to zero it puts no new line.
* Use *Logical operator new line* to specify newline placement before or
after logical operators (AND, OR, XOR).
* Use *New line before semicolon?* to specify whether to place query
separator (;) on a separate line.
* Use the *Spaces around operators?* option to specify whether or not to include
spaces on either side of operators.
* Use the *Tab size* option to specify the number of spaces per tab or indent.
* Use the *Use spaces?* option to select whether to use spaces or tabs when
indenting.
The Schema Diff Node
********************

View File

@ -0,0 +1,107 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2025, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""Migrate the user saved preferences from the 'sqleditor' module to
the 'editor' module.
Revision ID: e6ed5dac37c2
Revises: e24b1c4def17
Create Date: 2025-07-15 12:27:48.780562
"""
from alembic import op
from sqlalchemy.orm.session import Session
from pgadmin.model import Preferences, ModulePreference, PreferenceCategory,\
UserPreference
from pgadmin.browser import register_editor_preferences
# revision identifiers, used by Alembic.
revision = 'e6ed5dac37c2'
down_revision = 'e24b1c4def17'
branch_labels = None
depends_on = None
class Migration:
"""
This is a placeholder class for registering editor preferences
"""
def __init__(self, value=None):
self.editor_preference = value
def upgrade():
migration_obj = Migration()
register_editor_preferences(migration_obj, migration_gettext=lambda x: x)
session = Session(bind=op.get_bind())
pref_categories = ['keyboard_shortcuts', 'editor', 'Editor']
new_categories = ['keyboard_shortcuts', 'sql_formatting', 'options']
prefs = ['find', 'replace', 'goto_line_col',
'comment', 'format_sql', 'plain_editor_mode',
'code_folding', 'wrap_code', 'insert_pair_brackets',
'highlight_selection_matches', 'brace_matching', 'sql_font_size',
'sql_font_ligatures', 'sql_font_family', 'indent_new_line',
'keyword_case', 'identifier_case', 'function_case',
'data_type_case', 'spaces_around_operators', 'tab_size',
'use_spaces', 'expression_width', 'logical_operator_new_line',
'lines_between_queries', 'new_line_before_semicolon']
category_ids = []
new_ids = []
pref_map = {}
category_data = session.query(ModulePreference, PreferenceCategory,).join(
PreferenceCategory).filter(
ModulePreference.name == 'sqleditor',
PreferenceCategory.name.in_(pref_categories)).all()
for module_data, pref_cat in category_data:
category_ids.append(pref_cat.id)
new_data = session.query(ModulePreference, PreferenceCategory).join(
PreferenceCategory).filter(
ModulePreference.name == 'editor', PreferenceCategory.name.in_(
new_categories)).all()
for module_data, pref_cat in new_data:
new_ids.append(pref_cat.id)
prefs_data = session.query(Preferences).filter(Preferences.cid.in_(
category_ids), Preferences.name.in_(prefs)).all()
new_prefs_data = session.query(Preferences).filter(Preferences.cid.in_(
new_ids), Preferences.name.in_(prefs)).all()
for pref in prefs_data:
for new_pref in new_prefs_data:
if pref.name == new_pref.name:
pref_map[pref.id] = new_pref.id
for key, val in pref_map.items():
record_to_update = session.query(UserPreference).filter_by(
pid=key).first()
if record_to_update:
record_to_update.pid = val
# Delete the old preferences and categories
session.query(Preferences).filter(Preferences.name.in_(prefs),
Preferences.cid.in_(category_ids)
).delete(synchronize_session=False)
session.query(PreferenceCategory).filter(
PreferenceCategory.name.in_(['editor', 'Editor'])).delete(
synchronize_session=False)
session.commit()
def downgrade():
# pgAdmin only upgrades, downgrade not implemented.
pass

View File

@ -52,6 +52,8 @@ from pgadmin.utils.csrf import pgCSRFProtect
from pgadmin.utils.preferences import Preferences
from pgadmin.browser.register_browser_preferences import \
register_browser_preferences
from pgadmin.browser.register_editor_preferences import \
register_editor_preferences
from pgadmin.utils.master_password import validate_master_password, \
set_masterpass_check_text, cleanup_master_password, get_crypt_key, \
set_crypt_key, process_masterpass_disabled, \
@ -87,6 +89,7 @@ class BrowserModule(PgAdminModule):
def register_preferences(self):
register_browser_preferences(self)
register_editor_preferences(self)
def get_exposed_url_endpoints(self):
"""

View File

@ -0,0 +1,357 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2025, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
from flask_babel import gettext
from pgadmin.utils.preferences import Preferences
from pgadmin.utils.constants import PREF_LABEL_OPTIONS,\
PREF_LABEL_KEYBOARD_SHORTCUTS, PREF_LABEL_SQL_FORMATTING
from pgadmin.utils import SHORTCUT_FIELDS as shortcut_fields
UPPER_CASE_STR = gettext('Upper case')
LOWER_CASE_STR = gettext('Lower case')
PRESERVE_STR = gettext('Preserve')
def register_editor_preferences(self, migration_gettext=None):
"""
Registers the editor preferences
"""
# migration_getttext is used once in case of migration
# In that case gettext will be used from migration_gettext
# instead of flask_babel gettext.
from flask_babel import gettext
if migration_gettext is not None:
gettext = migration_gettext
self.editor_preference = Preferences(
'editor', gettext('Editor')
)
self.editor_preference.register(
'keyboard_shortcuts',
'find',
gettext('Find'),
'keyboardshortcut',
{
'alt': False,
'shift': False,
'control': True,
'ctrl_is_meta': True,
'key': {
'key_code': 70,
'char': 'f'
}
},
category_label=PREF_LABEL_KEYBOARD_SHORTCUTS,
fields=shortcut_fields
)
self.editor_preference.register(
'keyboard_shortcuts',
'replace',
gettext('Replace'),
'keyboardshortcut',
{
'alt': True,
'shift': False,
'control': True,
'ctrl_is_meta': True,
'key': {
'key_code': 70,
'char': 'f'
}
},
category_label=PREF_LABEL_KEYBOARD_SHORTCUTS,
fields=shortcut_fields
)
self.editor_preference.register(
'keyboard_shortcuts',
'goto_line_col',
gettext('Go to line/column'),
'keyboardshortcut',
{
'alt': False,
'shift': False,
'control': True,
'ctrl_is_meta': True,
'key': {
'key_code': 76,
'char': 'l'
}
},
category_label=PREF_LABEL_KEYBOARD_SHORTCUTS,
fields=shortcut_fields
)
self.editor_preference.register(
'keyboard_shortcuts',
'comment',
gettext('Toggle comment'),
'keyboardshortcut',
{
'alt': False,
'shift': False,
'control': True,
'ctrl_is_meta': True,
'key': {
'key_code': 191,
'char': '/'
}
},
category_label=PREF_LABEL_KEYBOARD_SHORTCUTS,
fields=shortcut_fields
)
self.editor_preference.register(
'keyboard_shortcuts',
'format_sql',
gettext('Format SQL'),
'keyboardshortcut',
{
'alt': False,
'shift': False,
'control': True,
'ctrl_is_meta': True,
'key': {
'key_code': 75,
'char': 'k'
}
},
category_label=PREF_LABEL_KEYBOARD_SHORTCUTS,
fields=shortcut_fields
)
self.editor_preference.register(
'options', 'plain_editor_mode',
gettext("Plain text mode?"), 'boolean', False,
category_label=PREF_LABEL_OPTIONS,
help_str=gettext(
'When set to True, keywords won\'t be highlighted and code '
'folding will be disabled. Plain text mode will improve editor '
'performance with large files.'
)
)
self.editor_preference.register(
'options', 'code_folding',
gettext("Code folding?"), 'boolean', True,
category_label=PREF_LABEL_OPTIONS,
help_str=gettext(
'Enable or disable code folding. In plain text mode, this will '
'have no effect as code folding is always disabled in that mode. '
'Disabling will improve editor performance with large files.'
)
)
self.editor_preference.register(
'options', 'wrap_code',
gettext("Line wrapping?"), 'boolean', False,
category_label=PREF_LABEL_OPTIONS,
help_str=gettext(
'Specifies whether or not to wrap SQL code in the editor.'
)
)
self.editor_preference.register(
'options', 'insert_pair_brackets',
gettext("Insert bracket pairs?"), 'boolean', True,
category_label=PREF_LABEL_OPTIONS,
help_str=gettext(
'Specifies whether or not to insert paired brackets in the '
'editor.'
)
)
self.editor_preference.register(
'options', 'highlight_selection_matches',
gettext("Highlight selection matches?"), 'boolean', True,
category_label=PREF_LABEL_OPTIONS,
help_str=gettext(
'Specifies whether or not to highlight matched selected text '
'in the editor.'
)
)
self.editor_preference.register(
'options', 'brace_matching',
gettext("Brace matching?"), 'boolean', True,
category_label=PREF_LABEL_OPTIONS,
help_str=gettext(
'Specifies whether or not to highlight matched braces '
'in the editor.'
)
)
self.editor_preference.register(
'options', 'sql_font_size',
gettext("Font size"), 'numeric', '1',
min_val=0.1,
max_val=10,
category_label=PREF_LABEL_OPTIONS,
help_str=gettext(
'The font size to use for the SQL text boxes and editors. '
'The value specified is in "em" units, in which 1 is the '
'default relative font size. For example, to increase the '
'font size by 20 percent use a value of 1.2, or to reduce '
'by 20 percent, use a value of 0.8. Minimum 0.1, maximum 10.'
)
)
self.editor_preference.register(
'options', 'sql_font_ligatures',
gettext("Font ligatures?"), 'boolean',
False, category_label=PREF_LABEL_OPTIONS,
help_str=gettext(
'If set to true, ligatures will be enabled in SQL text boxes '
'and editors provided the configured font family supports them.'
)
)
self.editor_preference.register(
'options', 'sql_font_family',
gettext("Font family"), 'text', 'Source Code Pro',
category_label=PREF_LABEL_OPTIONS,
help_str=gettext(
'Specify the font family to be used for all SQL editors. '
'The specified font should already be installed on your system. '
'If the font is not found, the editor will fall back to the '
'default font, Source Code Pro.'
)
)
self.editor_preference.register(
'options', 'indent_new_line',
gettext("Auto-indent new line?"), 'boolean', True,
category_label=PREF_LABEL_OPTIONS,
help_str=gettext(
'Specifies whether the newly added line using enter key should '
'be auto-indented or not'
)
)
self.editor_preference.register(
'sql_formatting', 'keyword_case',
gettext("Keyword case"), 'radioModern', 'upper',
options=[{'label': UPPER_CASE_STR, 'value': 'upper'},
{'label': LOWER_CASE_STR, 'value': 'lower'},
{'label': PRESERVE_STR, 'value': 'preserve'}],
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Convert keywords to upper, lower, or preserve casing.'
)
)
self.editor_preference.register(
'sql_formatting', 'identifier_case',
gettext("Identifier case"), 'radioModern', 'upper',
options=[{'label': UPPER_CASE_STR, 'value': 'upper'},
{'label': LOWER_CASE_STR, 'value': 'lower'},
{'label': PRESERVE_STR, 'value': 'preserve'}],
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Convert identifiers to upper, lower, or preserve casing.'
)
)
self.editor_preference.register(
'sql_formatting', 'function_case',
gettext("Function case"), 'radioModern', 'upper',
options=[{'label': UPPER_CASE_STR, 'value': 'upper'},
{'label': LOWER_CASE_STR, 'value': 'lower'},
{'label': PRESERVE_STR, 'value': 'preserve'}],
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Convert function names to upper, lower, or preserve casing.'
)
)
self.editor_preference.register(
'sql_formatting', 'data_type_case',
gettext("Data type case"), 'radioModern', 'upper',
options=[{'label': UPPER_CASE_STR, 'value': 'upper'},
{'label': LOWER_CASE_STR, 'value': 'lower'},
{'label': PRESERVE_STR, 'value': 'preserve'}],
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Convert data types to upper, lower, or preserve casing.'
)
)
self.editor_preference.register(
'sql_formatting', 'spaces_around_operators',
gettext("Spaces around operators?"), 'boolean', True,
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext('If set to True, spaces are used around all '
'operators.')
)
self.editor_preference.register(
'sql_formatting', 'tab_size',
gettext("Tab size"), 'integer', 4,
min_val=2,
max_val=8,
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'The number of spaces per tab. Minimum 2, maximum 8.'
)
)
self.editor_preference.register(
'sql_formatting', 'use_spaces',
gettext("Use spaces?"), 'boolean', False,
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Specifies whether or not to insert spaces instead of tabs '
'when the tab key or auto-indent are used.'
)
)
self.editor_preference.register(
'sql_formatting', 'expression_width',
gettext("Expression Width"), 'integer', 50,
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'maximum number of characters in parenthesized expressions to be '
'kept on single line.'
)
)
self.editor_preference.register(
'sql_formatting', 'logical_operator_new_line',
gettext("Logical operator new line"), 'radioModern', 'before',
options=[{'label': gettext('Before'), 'value': 'before'},
{'label': gettext('After'), 'value': 'after'}],
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Decides newline placement before or after logical operators '
'(AND, OR, XOR).'
)
)
self.editor_preference.register(
'sql_formatting', 'lines_between_queries',
gettext("Lines between queries"), 'integer', 1,
min_val=0,
max_val=5,
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Decides how many empty lines to leave between SQL statements. '
'If zero it puts no new line.'
)
)
self.editor_preference.register(
'sql_formatting', 'new_line_before_semicolon',
gettext("New line before semicolon?"), 'boolean', False,
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Whether to place query separator (;) on a separate line.'
)
)

View File

@ -33,7 +33,7 @@ import config
#
##########################################################################
SCHEMA_VERSION = 46
SCHEMA_VERSION = 47
##########################################################################
#

View File

@ -285,14 +285,15 @@ export default function Editor({
useEffect(() => {
if (!checkIsMounted()) return;
let pref = preferencesStore.getPreferencesForModule('sqleditor');
let editorPref = preferencesStore.getPreferencesForModule('editor');
let newConfigExtn = [];
const fontSize = calcFontSize(pref.sql_font_size);
const fontSize = calcFontSize(editorPref.sql_font_size);
newConfigExtn.push(EditorView.theme({
'& .cm-scroller .cm-content': {
fontSize: fontSize,
fontVariantLigatures: pref.sql_font_ligatures ? 'normal' : 'none',
fontFamily: `${pref.sql_font_family}, ${theme.typography.fontFamilySourceCode}`,
fontVariantLigatures: editorPref.sql_font_ligatures ? 'normal' : 'none',
fontFamily: `${editorPref.sql_font_family}, ${theme.typography.fontFamilySourceCode}`,
},
'.cm-gutters': {
fontSize: fontSize,
@ -336,11 +337,11 @@ export default function Editor({
}
newConfigExtn.push(
EditorState.tabSize.of(pref.tab_size),
EditorState.tabSize.of(editorPref.tab_size),
);
if (pref.use_spaces) {
if (editorPref.use_spaces) {
newConfigExtn.push(
indentUnit.of(' '.repeat(pref.tab_size)),
indentUnit.of(' '.repeat(editorPref.tab_size)),
);
} else {
newConfigExtn.push(
@ -348,34 +349,34 @@ export default function Editor({
);
}
if(pref.indent_new_line) {
if(editorPref.indent_new_line) {
newConfigExtn.push(indentNewLine.of(true));
} else {
newConfigExtn.push(indentNewLine.of(false));
}
if (pref.wrap_code) {
if (editorPref.wrap_code) {
newConfigExtn.push(
EditorView.lineWrapping
);
}
if (pref.insert_pair_brackets) {
if (editorPref.insert_pair_brackets) {
newConfigExtn.push(closeBrackets());
}
if (pref.highlight_selection_matches){
if (editorPref.highlight_selection_matches){
newConfigExtn.push(highlightSelectionMatches());
}
if (pref.brace_matching) {
if (editorPref.brace_matching) {
newConfigExtn.push(bracketMatching());
}
if (pref.underline_query_cursor){
newConfigExtn.push(currentQueryHighlighterExtn());
}
if(!pref.plain_editor_mode) {
if(!editorPref.plain_editor_mode) {
// lang override
if(language == 'json') {
newConfigExtn.push(json());
@ -384,7 +385,7 @@ export default function Editor({
}
}
if(pref.code_folding && finalOptions.foldGutter) {
if(editorPref.code_folding && finalOptions.foldGutter) {
newConfigExtn.push(foldGutter({
markerDOM: (open)=>{
let icon = document.createElement('span');
@ -399,7 +400,7 @@ export default function Editor({
}
// add fold service conditionally
if(!pref.plain_editor_mode && pref.code_folding && language == 'pgsql') {
if(!editorPref.plain_editor_mode && editorPref.code_folding && language == 'pgsql') {
newConfigExtn.push(plpgsqlFoldService);
}

View File

@ -69,6 +69,7 @@ export default function CodeMirror({className, currEditor, showCopyBtn=false, cu
const [showGoto, setShowGoto] = useState(false);
const [showCopy, setShowCopy] = useState(false);
const preferences = usePreferences().getPreferencesForModule('sqleditor');
const editorPrefs = usePreferences().getPreferencesForModule('editor');
const formatSQL = (view)=>{
let selection = true, sql = view.getSelection();
@ -78,17 +79,17 @@ export default function CodeMirror({className, currEditor, showCopyBtn=false, cu
*/
let formatPrefs = {
language: 'postgresql',
keywordCase: preferences.keyword_case === 'capitalize' ? 'preserve' : preferences.keyword_case,
identifierCase: preferences.identifier_case === 'capitalize' ? 'preserve' : preferences.identifier_case,
dataTypeCase: preferences.data_type_case,
functionCase: preferences.function_case,
logicalOperatorNewline: preferences.logical_operator_new_line,
expressionWidth: preferences.expression_width,
linesBetweenQueries: preferences.lines_between_queries,
tabWidth: preferences.tab_size,
useTabs: !preferences.use_spaces,
denseOperators: !preferences.spaces_around_operators,
newlineBeforeSemicolon: preferences.new_line_before_semicolon
keywordCase: editorPrefs.keyword_case === 'capitalize' ? 'preserve' : editorPrefs.keyword_case,
identifierCase: editorPrefs.identifier_case === 'capitalize' ? 'preserve' : editorPrefs.identifier_case,
dataTypeCase: editorPrefs.data_type_case,
functionCase: editorPrefs.function_case,
logicalOperatorNewline: editorPrefs.logical_operator_new_line,
expressionWidth: editorPrefs.expression_width,
linesBetweenQueries: editorPrefs.lines_between_queries,
tabWidth: editorPrefs.tab_size,
useTabs: !editorPrefs.use_spaces,
denseOperators: !editorPrefs.spaces_around_operators,
newlineBeforeSemicolon: editorPrefs.new_line_before_semicolon
};
if(sql == '') {
sql = view.getValue();
@ -103,31 +104,31 @@ export default function CodeMirror({className, currEditor, showCopyBtn=false, cu
};
const finalCustomKeyMap = useMemo(()=>[{
key: toCodeMirrorKey(preferences.find), run: () => {
key: toCodeMirrorKey(editorPrefs.find), run: () => {
setShowFind(prevVal => [true, false, !prevVal[2]]);
},
preventDefault: true,
stopPropagation: true,
}, {
key: toCodeMirrorKey(preferences.replace), run: () => {
key: toCodeMirrorKey(editorPrefs.replace), run: () => {
setShowFind(prevVal => [true, true, !prevVal[2]]);
},
preventDefault: true,
stopPropagation: true,
}, {
key: toCodeMirrorKey(preferences.goto_line_col), run: () => {
key: toCodeMirrorKey(editorPrefs.goto_line_col), run: () => {
setShowGoto(true);
},
preventDefault: true,
stopPropagation: true,
}, {
key: toCodeMirrorKey(preferences.comment), run: () => {
key: toCodeMirrorKey(editorPrefs.comment), run: () => {
editor.current?.execCommand('toggleComment');
},
preventDefault: true,
stopPropagation: true,
},{
key: toCodeMirrorKey(preferences.format_sql), run: formatSQL,
key: toCodeMirrorKey(editorPrefs.format_sql), run: formatSQL,
preventDefault: true,
stopPropagation: true,
},{

View File

@ -123,6 +123,7 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
sqleditor: {...preferencesStore.getPreferencesForModule('sqleditor'), ...FIXED_PREF},
graphs: preferencesStore.getPreferencesForModule('graphs'),
misc: preferencesStore.getPreferencesForModule('misc'),
editor: preferencesStore.getPreferencesForModule('editor'),
},
is_new_tab: window.location == window.parent?.location,
is_visible: true,
@ -467,6 +468,7 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
sqleditor: {...state.getPreferencesForModule('sqleditor'), ...FIXED_PREF},
graphs: state.getPreferencesForModule('graphs'),
misc: state.getPreferencesForModule('misc'),
editor: state.getPreferencesForModule('editor'),
}});
}
), []);

View File

@ -84,6 +84,7 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros, onAddT
const filterMenuRef = React.useRef(null);
const queryToolPref = queryToolCtx.preferences.sqleditor;
const editorPref = queryToolCtx.preferences.editor;
const setDisableButton = useCallback((name, disable=true)=>{
setButtonsDisabled((prev)=>({...prev, [name]: disable}));
}, []);
@ -595,25 +596,25 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros, onAddT
onClose={onMenuClose}
label={gettext('Edit Menu')}
>
<PgMenuItem shortcut={queryToolPref.find}
<PgMenuItem shortcut={editorPref.find}
onClick={()=>{eventBus.fireEvent(QUERY_TOOL_EVENTS.EDITOR_FIND_REPLACE, false);}}>{gettext('Find')}</PgMenuItem>
<PgMenuItem shortcut={queryToolPref.replace}
<PgMenuItem shortcut={editorPref.replace}
onClick={()=>{eventBus.fireEvent(QUERY_TOOL_EVENTS.EDITOR_FIND_REPLACE, true);}}>{gettext('Replace')}</PgMenuItem>
<PgMenuItem shortcut={queryToolPref.goto_line_col}
<PgMenuItem shortcut={editorPref.goto_line_col}
onClick={()=>{executeCmd('gotoLineCol');}}>{gettext('Go to Line/Column')}</PgMenuItem>
<PgMenuDivider />
<PgMenuItem shortcut={queryToolPref.indent}
onClick={()=>{executeCmd('indentMore');}}>{gettext('Indent Selection')}</PgMenuItem>
<PgMenuItem shortcut={queryToolPref.unindent}
onClick={()=>{executeCmd('indentLess');}}>{gettext('Unindent Selection')}</PgMenuItem>
<PgMenuItem shortcut={queryToolPref.comment}
<PgMenuItem shortcut={editorPref.comment}
onClick={()=>{executeCmd('toggleComment');}}>{gettext('Toggle Comment')}</PgMenuItem>
<PgMenuItem shortcut={queryToolPref.toggle_case}
onClick={toggleCase}>{gettext('Toggle Case Of Selected Text')}</PgMenuItem>
<PgMenuItem shortcut={queryToolPref.clear_query}
onClick={clearQuery}>{gettext('Clear Query')}</PgMenuItem>
<PgMenuDivider />
<PgMenuItem shortcut={queryToolPref.format_sql} onClick={()=>{executeCmd('formatSql');}}>{gettext('Format SQL')}</PgMenuItem>
<PgMenuItem shortcut={editorPref.format_sql} onClick={()=>{executeCmd('formatSql');}}>{gettext('Format SQL')}</PgMenuItem>
</PgMenu>
<PgMenu
anchorRef={filterMenuRef}

View File

@ -309,8 +309,8 @@ export default function Query({onTextSelect, setQtStatePartial}) {
};
const unregisterEditorExecCmd = eventBus.registerListener(QUERY_TOOL_EVENTS.EDITOR_EXEC_CMD, (cmd='')=>{
let key = {}, gotolinecol = queryToolCtx.preferences.sqleditor.goto_line_col,
formatSql = queryToolCtx.preferences.sqleditor.format_sql;
let key = {}, gotolinecol = queryToolCtx.preferences.editor.goto_line_col,
formatSql = queryToolCtx.preferences.editor.format_sql;
switch(cmd) {
case 'gotoLineCol':
key = createKeyObjectFromShortcut(gotolinecol);
@ -326,8 +326,8 @@ export default function Query({onTextSelect, setQtStatePartial}) {
});
const unregisterFindReplace = eventBus.registerListener(QUERY_TOOL_EVENTS.EDITOR_FIND_REPLACE, (replace=false)=>{
let findShortcut = queryToolCtx.preferences.sqleditor.find;
let replaceShortcut = queryToolCtx.preferences.sqleditor.replace;
let findShortcut = queryToolCtx.preferences.editor.find;
let replaceShortcut = queryToolCtx.preferences.editor.replace;
let key ={};
editor.current?.focus();
if (!replace) {

View File

@ -11,15 +11,11 @@
from flask_babel import gettext
from pgadmin.utils.constants import PREF_LABEL_DISPLAY,\
PREF_LABEL_KEYBOARD_SHORTCUTS, PREF_LABEL_EXPLAIN, PREF_LABEL_OPTIONS,\
PREF_LABEL_EDITOR, PREF_LABEL_CSV_TXT, PREF_LABEL_RESULTS_GRID,\
PREF_LABEL_SQL_FORMATTING, PREF_LABEL_GRAPH_VISUALISER
PREF_LABEL_CSV_TXT, PREF_LABEL_RESULTS_GRID,\
PREF_LABEL_GRAPH_VISUALISER
from pgadmin.utils import SHORTCUT_FIELDS as shortcut_fields
from config import DATA_RESULT_ROWS_PER_PAGE
UPPER_CASE_STR = gettext('Upper case')
LOWER_CASE_STR = gettext('Lower case')
PRESERVE_STR = gettext('Preserve')
def register_query_tool_preferences(self):
self.explain_verbose = self.preference.register(
@ -188,67 +184,6 @@ def register_query_tool_preferences(self):
)
)
self.preference.register(
'Editor', 'plain_editor_mode',
gettext("Plain text mode?"), 'boolean', False,
category_label=PREF_LABEL_EDITOR,
help_str=gettext(
'When set to True, keywords won\'t be highlighted and code '
'folding will be disabled. Plain text mode will improve editor '
'performance with large files.'
)
)
self.preference.register(
'Editor', 'code_folding',
gettext("Code folding?"), 'boolean', True,
category_label=PREF_LABEL_EDITOR,
help_str=gettext(
'Enable or disable code folding. In plain text mode, this will '
'have no effect as code folding is always disabled in that mode. '
'Disabling will improve editor performance with large files.'
)
)
self.wrap_code = self.preference.register(
'Editor', 'wrap_code',
gettext("Line wrapping?"), 'boolean', False,
category_label=PREF_LABEL_OPTIONS,
help_str=gettext(
'Specifies whether or not to wrap SQL code in the editor.'
)
)
self.insert_pair_brackets = self.preference.register(
'Editor', 'insert_pair_brackets',
gettext("Insert bracket pairs?"), 'boolean', True,
category_label=PREF_LABEL_OPTIONS,
help_str=gettext(
'Specifies whether or not to insert paired brackets in the '
'editor.'
)
)
self.highlight_selection_matches = self.preference.register(
'Editor', 'highlight_selection_matches',
gettext("Highlight selection matches?"), 'boolean', True,
category_label=PREF_LABEL_OPTIONS,
help_str=gettext(
'Specifies whether or not to highlight matched selected text '
'in the editor.'
)
)
self.brace_matching = self.preference.register(
'Editor', 'brace_matching',
gettext("Brace matching?"), 'boolean', True,
category_label=PREF_LABEL_OPTIONS,
help_str=gettext(
'Specifies whether or not to highlight matched braces '
'in the editor.'
)
)
self.csv_quoting = self.preference.register(
'CSV_output', 'csv_quoting',
gettext("CSV quoting"), 'options', 'strings',
@ -394,43 +329,6 @@ def register_query_tool_preferences(self):
' data output cell.')
)
self.sql_font_size = self.preference.register(
'Editor', 'sql_font_size',
gettext("Font size"), 'numeric', '1',
min_val=0.1,
max_val=10,
category_label=PREF_LABEL_DISPLAY,
help_str=gettext(
'The font size to use for the SQL text boxes and editors. '
'The value specified is in "em" units, in which 1 is the '
'default relative font size. For example, to increase the '
'font size by 20 percent use a value of 1.2, or to reduce '
'by 20 percent, use a value of 0.8. Minimum 0.1, maximum 10.'
)
)
self.sql_font_ligatures = self.preference.register(
'Editor', 'sql_font_ligatures',
gettext("Font ligatures?"), 'boolean',
False, category_label=PREF_LABEL_DISPLAY,
help_str=gettext(
'If set to true, ligatures will be enabled in SQL text boxes '
'and editors provided the configured font family supports them.'
)
)
self.sql_font_family = self.preference.register(
'Editor', 'sql_font_family',
gettext("Font family"), 'text', 'Source Code Pro',
category_label=PREF_LABEL_DISPLAY,
help_str=gettext(
'Specify the font family to be used for all SQL editors. '
'The specified font should already be installed on your system. '
'If the font is not found, the editor will fall back to the '
'default font, Source Code Pro.'
)
)
self.display_connection_status = self.preference.register(
'display', 'connection_status',
gettext("Connection status"), 'boolean', True,
@ -884,101 +782,6 @@ def register_query_tool_preferences(self):
fields=shortcut_fields
)
self.preference.register(
'keyboard_shortcuts',
'find',
gettext('Find'),
'keyboardshortcut',
{
'alt': False,
'shift': False,
'control': True,
'ctrl_is_meta': True,
'key': {
'key_code': 70,
'char': 'f'
}
},
category_label=PREF_LABEL_KEYBOARD_SHORTCUTS,
fields=shortcut_fields
)
self.preference.register(
'keyboard_shortcuts',
'replace',
gettext('Replace'),
'keyboardshortcut',
{
'alt': True,
'shift': False,
'control': True,
'ctrl_is_meta': True,
'key': {
'key_code': 70,
'char': 'f'
}
},
category_label=PREF_LABEL_KEYBOARD_SHORTCUTS,
fields=shortcut_fields
)
self.preference.register(
'keyboard_shortcuts',
'goto_line_col',
gettext('Go to line/column'),
'keyboardshortcut',
{
'alt': False,
'shift': False,
'control': True,
'ctrl_is_meta': True,
'key': {
'key_code': 76,
'char': 'l'
}
},
category_label=PREF_LABEL_KEYBOARD_SHORTCUTS,
fields=shortcut_fields
)
self.preference.register(
'keyboard_shortcuts',
'comment',
gettext('Toggle comment'),
'keyboardshortcut',
{
'alt': False,
'shift': False,
'control': True,
'ctrl_is_meta': True,
'key': {
'key_code': 191,
'char': '/'
}
},
category_label=PREF_LABEL_KEYBOARD_SHORTCUTS,
fields=shortcut_fields
)
self.preference.register(
'keyboard_shortcuts',
'format_sql',
gettext('Format SQL'),
'keyboardshortcut',
{
'alt': False,
'shift': False,
'control': True,
'ctrl_is_meta': True,
'key': {
'key_code': 75,
'char': 'k'
}
},
category_label=PREF_LABEL_KEYBOARD_SHORTCUTS,
fields=shortcut_fields
)
self.preference.register(
'keyboard_shortcuts',
'auto_complete',
@ -998,136 +801,6 @@ def register_query_tool_preferences(self):
fields=shortcut_fields
)
self.keyword_case = self.preference.register(
'editor', 'keyword_case',
gettext("Keyword case"), 'radioModern', 'upper',
options=[{'label': UPPER_CASE_STR, 'value': 'upper'},
{'label': LOWER_CASE_STR, 'value': 'lower'},
{'label': PRESERVE_STR, 'value': 'preserve'}],
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Convert keywords to upper, lower, or preserve casing.'
)
)
self.identifier_case = self.preference.register(
'editor', 'identifier_case',
gettext("Identifier case"), 'radioModern', 'upper',
options=[{'label': UPPER_CASE_STR, 'value': 'upper'},
{'label': LOWER_CASE_STR, 'value': 'lower'},
{'label': PRESERVE_STR, 'value': 'preserve'}],
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Convert identifiers to upper, lower, or preserve casing.'
)
)
self.function_case = self.preference.register(
'editor', 'function_case',
gettext("Function case"), 'radioModern', 'upper',
options=[{'label': UPPER_CASE_STR, 'value': 'upper'},
{'label': LOWER_CASE_STR, 'value': 'lower'},
{'label': PRESERVE_STR, 'value': 'preserve'}],
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Convert function names to upper, lower, or preserve casing.'
)
)
self.data_type_case = self.preference.register(
'editor', 'data_type_case',
gettext("Data type case"), 'radioModern', 'upper',
options=[{'label': UPPER_CASE_STR, 'value': 'upper'},
{'label': LOWER_CASE_STR, 'value': 'lower'},
{'label': PRESERVE_STR, 'value': 'preserve'}],
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Convert data types to upper, lower, or preserve casing.'
)
)
self.spaces_around_operators = self.preference.register(
'editor', 'spaces_around_operators',
gettext("Spaces around operators?"), 'boolean', True,
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext('If set to True, spaces are used around all '
'operators.')
)
self.tab_size = self.preference.register(
'editor', 'tab_size',
gettext("Tab size"), 'integer', 4,
min_val=2,
max_val=8,
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'The number of spaces per tab. Minimum 2, maximum 8.'
)
)
self.use_spaces = self.preference.register(
'editor', 'use_spaces',
gettext("Use spaces?"), 'boolean', False,
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Specifies whether or not to insert spaces instead of tabs '
'when the tab key or auto-indent are used.'
)
)
self.preference.register(
'Editor', 'indent_new_line',
gettext("Auto-indent new line?"), 'boolean', True,
category_label=PREF_LABEL_EDITOR,
help_str=gettext(
'Specifies whether the newly added line using enter key should '
'be auto-indented or not'
)
)
self.expression_width = self.preference.register(
'editor', 'expression_width',
gettext("Expression Width"), 'integer', 50,
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'maximum number of characters in parenthesized expressions to be '
'kept on single line.'
)
)
self.logical_operator_new_line = self.preference.register(
'editor', 'logical_operator_new_line',
gettext("Logical operator new line"), 'radioModern', 'before',
options=[{'label': gettext('Before'), 'value': 'before'},
{'label': gettext('After'), 'value': 'after'}],
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Decides newline placement before or after logical operators '
'(AND, OR, XOR).'
)
)
self.lines_between_queries = self.preference.register(
'editor', 'lines_between_queries',
gettext("Lines between queries"), 'integer', 1,
min_val=0,
max_val=5,
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Decides how many empty lines to leave between SQL statements. '
'If zero it puts no new line.'
)
)
self.new_line_before_semicolon = self.preference.register(
'editor', 'new_line_before_semicolon',
gettext("New line before semicolon?"), 'boolean', False,
category_label=PREF_LABEL_SQL_FORMATTING,
help_str=gettext(
'Whether to place query separator (;) on a separate line.'
)
)
self.row_limit = self.preference.register(
'graph_visualiser', 'row_limit',
gettext("Row Limit"), 'integer',

View File

@ -90,7 +90,7 @@ class _Preference():
db.session.add(res)
db.session.commit()
res = PrefTable.query.filter_by(
name=name
name=name, cid=cid
).first()
# Save this id for letter use.