/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2011-2012 Eugene Fradkin (eugene.fradkin@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.ui.preferences;
import org.eclipse.jface.fieldassist.SimpleContentProposalProvider;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.IEditorSite;
import org.jkiss.dbeaver.ModelPreferences;
import org.jkiss.dbeaver.core.DBeaverUI;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.DBPIdentifierCase;
import org.jkiss.dbeaver.model.exec.DBCExecutionContext;
import org.jkiss.dbeaver.model.preferences.DBPPreferenceStore;
import org.jkiss.dbeaver.model.sql.format.external.SQLExternalFormatter;
import org.jkiss.dbeaver.model.sql.format.tokenized.SQLTokenizedFormatter;
import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.dbeaver.ui.editors.StringEditorInput;
import org.jkiss.dbeaver.ui.editors.SubEditorSite;
import org.jkiss.dbeaver.ui.editors.sql.SQLEditorBase;
import org.jkiss.dbeaver.ui.editors.sql.SQLPreferenceConstants;
import org.jkiss.dbeaver.utils.ContentUtils;
import org.jkiss.dbeaver.utils.GeneralUtils;
import org.jkiss.dbeaver.utils.PrefUtils;
import org.jkiss.utils.CommonUtils;
import java.io.InputStream;
import java.util.Locale;
/**
* PrefPageSQLFormat
*/
public class PrefPageSQLFormat extends TargetPrefPage
{
public static final String PAGE_ID = "org.jkiss.dbeaver.preferences.main.sql.format"; //$NON-NLS-1$
private final static String FORMAT_FILE_NAME = "format_preview.sql";
// Auto-close
private Button acSingleQuotesCheck;
private Button acDoubleQuotesCheck;
private Button acBracketsCheck;
// Auto-Format
private Button afKeywordCase;
private Button afExtractFromSource;
// Formatter
private Combo formatterSelector;
private Combo keywordCaseCombo;
private Text externalCmdText;
private Button externalUseFile;
private Spinner externalTimeout;
private SQLEditorBase sqlViewer;
private Composite defaultGroup;
private Composite externalGroup;
public PrefPageSQLFormat()
{
super();
}
@Override
protected boolean hasDataSourceSpecificOptions(DBPDataSourceContainer dataSourceDescriptor)
{
DBPPreferenceStore store = dataSourceDescriptor.getPreferenceStore();
return
store.contains(SQLPreferenceConstants.SQLEDITOR_CLOSE_SINGLE_QUOTES) ||
store.contains(SQLPreferenceConstants.SQLEDITOR_CLOSE_DOUBLE_QUOTES) ||
store.contains(SQLPreferenceConstants.SQLEDITOR_CLOSE_BRACKETS) ||
store.contains(SQLPreferenceConstants.SQL_FORMAT_KEYWORD_CASE_AUTO) ||
store.contains(SQLPreferenceConstants.SQL_FORMAT_EXTRACT_FROM_SOURCE) ||
store.contains(ModelPreferences.SQL_FORMAT_FORMATTER) ||
store.contains(ModelPreferences.SQL_FORMAT_KEYWORD_CASE) ||
store.contains(ModelPreferences.SQL_FORMAT_EXTERNAL_CMD) ||
store.contains(ModelPreferences.SQL_FORMAT_EXTERNAL_FILE) ||
store.contains(ModelPreferences.SQL_FORMAT_EXTERNAL_TIMEOUT)
;
}
@Override
protected boolean supportsDataSourceSpecificOptions()
{
return true;
}
@Override
protected Control createPreferenceContent(Composite parent)
{
Composite composite = UIUtils.createPlaceholder(parent, 2, 5);
// Autoclose
{
Composite acGroup = UIUtils.createControlGroup(composite, "Auto close", 1, GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING, 0);
acSingleQuotesCheck = UIUtils.createCheckbox(acGroup, "Single quotes", false);
acDoubleQuotesCheck = UIUtils.createCheckbox(acGroup, "Double quotes", false);
acBracketsCheck = UIUtils.createCheckbox(acGroup, "Brackets", false);
}
{
// Formatting
Composite afGroup = UIUtils.createControlGroup(composite, "Auto format", 1, GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING, 0);
afKeywordCase = UIUtils.createCheckbox(
afGroup,
"Convert keyword case",
"Auto-convert keywords to upper/lower case on enter",
false, 1);
afExtractFromSource = UIUtils.createCheckbox(
afGroup,
"Extract SQL from source code",
"On source code paste will remove all source language elements like quotes, +, \\n, etc", false, 1);
}
Composite formatterGroup = UIUtils.createControlGroup(composite, "Formatter", 1, GridData.FILL_BOTH, 0);
((GridData)formatterGroup.getLayoutData()).horizontalSpan = 2;
{
Composite formatterPanel = UIUtils.createPlaceholder(formatterGroup, 2);
formatterPanel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
formatterSelector = UIUtils.createLabelCombo(formatterPanel, "Formatter", SWT.DROP_DOWN | SWT.READ_ONLY);
formatterSelector.add(capitalizeCaseName(SQLTokenizedFormatter.FORMATTER_ID));
formatterSelector.add(capitalizeCaseName(SQLExternalFormatter.FORMATTER_ID));
formatterSelector.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
showFormatterSettings();
}
});
formatterSelector.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
}
// Default formatter settings
{
defaultGroup = UIUtils.createPlaceholder(formatterGroup, 2, 0);
defaultGroup.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
keywordCaseCombo = UIUtils.createLabelCombo(defaultGroup, "Keyword case", SWT.DROP_DOWN | SWT.READ_ONLY);
keywordCaseCombo.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
keywordCaseCombo.add("Database");
for (DBPIdentifierCase c :DBPIdentifierCase.values()) {
keywordCaseCombo.add(capitalizeCaseName(c.name()));
}
keywordCaseCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
performApply();
}
});
}
// External formatter
{
externalGroup = UIUtils.createPlaceholder(formatterGroup, 2, 5);
externalGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_BEGINNING));
externalCmdText = UIUtils.createLabelText(externalGroup, "Command line", "");
externalCmdText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
UIUtils.installContentProposal(
externalCmdText,
new TextContentAdapter(),
new SimpleContentProposalProvider(new String[] {
GeneralUtils.variablePattern(SQLExternalFormatter.VAR_FILE)
}));
UIUtils.setContentProposalToolTip(externalCmdText, "External program with parameters", SQLExternalFormatter.VAR_FILE);
externalUseFile = UIUtils.createLabelCheckbox(externalGroup,
"Use temp file",
"Use temporary file to pass SQL text.\nTo pass file name in command line use parameter " + GeneralUtils.variablePattern(SQLExternalFormatter.VAR_FILE),
false);
externalTimeout = UIUtils.createLabelSpinner(externalGroup,
"Exec timeout",
"Time to wait until formatter process finish (ms)",
100, 100, 10000);
}
{
// SQL preview
Composite previewGroup = new Composite(formatterGroup, SWT.BORDER);
previewGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
previewGroup.setLayout(new FillLayout());
sqlViewer = new SQLEditorBase() {
@Override
public DBCExecutionContext getExecutionContext() {
final DBPDataSourceContainer container = getDataSourceContainer();
if (container != null) {
final DBPDataSource dataSource = container.getDataSource();
if (dataSource != null) {
return dataSource.getDefaultContext(false);
}
}
return null;
}
};
try {
try (final InputStream sqlStream = getClass().getResourceAsStream(FORMAT_FILE_NAME)) {
final String sqlText = ContentUtils.readToString(sqlStream, GeneralUtils.DEFAULT_ENCODING);
IEditorSite subSite = new SubEditorSite(DBeaverUI.getActiveWorkbenchWindow().getActivePage().getActivePart().getSite());
StringEditorInput sqlInput = new StringEditorInput("SQL preview", sqlText, true, GeneralUtils.getDefaultFileEncoding());
sqlViewer.init(subSite, sqlInput);
}
} catch (Exception e) {
log.error(e);
}
sqlViewer.createPartControl(previewGroup);
Object text = sqlViewer.getAdapter(Control.class);
if (text instanceof StyledText) {
((StyledText) text).setWordWrap(true);
}
sqlViewer.reloadSyntaxRules();
previewGroup.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
sqlViewer.dispose();
}
});
}
return composite;
}
@Override
protected void loadPreferences(DBPPreferenceStore store)
{
acSingleQuotesCheck.setSelection(store.getBoolean(SQLPreferenceConstants.SQLEDITOR_CLOSE_SINGLE_QUOTES));
acDoubleQuotesCheck.setSelection(store.getBoolean(SQLPreferenceConstants.SQLEDITOR_CLOSE_DOUBLE_QUOTES));
acBracketsCheck.setSelection(store.getBoolean(SQLPreferenceConstants.SQLEDITOR_CLOSE_BRACKETS));
afKeywordCase.setSelection(store.getBoolean(SQLPreferenceConstants.SQL_FORMAT_KEYWORD_CASE_AUTO));
afExtractFromSource.setSelection(store.getBoolean(SQLPreferenceConstants.SQL_FORMAT_EXTRACT_FROM_SOURCE));
UIUtils.setComboSelection(formatterSelector, capitalizeCaseName(store.getString(ModelPreferences.SQL_FORMAT_FORMATTER)));
final String caseName = store.getString(ModelPreferences.SQL_FORMAT_KEYWORD_CASE);
if (CommonUtils.isEmpty(caseName)) {
keywordCaseCombo.select(0);
} else {
UIUtils.setComboSelection(keywordCaseCombo, capitalizeCaseName(caseName));
}
externalCmdText.setText(store.getString(ModelPreferences.SQL_FORMAT_EXTERNAL_CMD));
externalUseFile.setSelection(store.getBoolean(ModelPreferences.SQL_FORMAT_EXTERNAL_FILE));
externalTimeout.setSelection(store.getInt(ModelPreferences.SQL_FORMAT_EXTERNAL_TIMEOUT));
formatSQL();
showFormatterSettings();
}
@Override
protected void savePreferences(DBPPreferenceStore store)
{
store.setValue(SQLPreferenceConstants.SQLEDITOR_CLOSE_SINGLE_QUOTES, acSingleQuotesCheck.getSelection());
store.setValue(SQLPreferenceConstants.SQLEDITOR_CLOSE_DOUBLE_QUOTES, acDoubleQuotesCheck.getSelection());
store.setValue(SQLPreferenceConstants.SQLEDITOR_CLOSE_BRACKETS, acBracketsCheck.getSelection());
store.setValue(SQLPreferenceConstants.SQL_FORMAT_KEYWORD_CASE_AUTO, afKeywordCase.getSelection());
store.setValue(SQLPreferenceConstants.SQL_FORMAT_EXTRACT_FROM_SOURCE, afExtractFromSource.getSelection());
store.setValue(ModelPreferences.SQL_FORMAT_FORMATTER, formatterSelector.getText().toUpperCase(Locale.ENGLISH));
final String caseName;
if (keywordCaseCombo.getSelectionIndex() == 0) {
caseName = "";
} else {
caseName = keywordCaseCombo.getText().toUpperCase(Locale.ENGLISH);
}
store.setValue(ModelPreferences.SQL_FORMAT_KEYWORD_CASE, caseName);
store.setValue(ModelPreferences.SQL_FORMAT_EXTERNAL_CMD, externalCmdText.getText());
store.setValue(ModelPreferences.SQL_FORMAT_EXTERNAL_FILE, externalUseFile.getSelection());
store.setValue(ModelPreferences.SQL_FORMAT_EXTERNAL_TIMEOUT, externalTimeout.getSelection());
PrefUtils.savePreferenceStore(store);
}
@Override
protected void clearPreferences(DBPPreferenceStore store)
{
store.setToDefault(SQLPreferenceConstants.SQLEDITOR_CLOSE_SINGLE_QUOTES);
store.setToDefault(SQLPreferenceConstants.SQLEDITOR_CLOSE_DOUBLE_QUOTES);
store.setToDefault(SQLPreferenceConstants.SQLEDITOR_CLOSE_BRACKETS);
store.setToDefault(SQLPreferenceConstants.SQL_FORMAT_KEYWORD_CASE_AUTO);
store.setToDefault(SQLPreferenceConstants.SQL_FORMAT_EXTRACT_FROM_SOURCE);
store.setToDefault(ModelPreferences.SQL_FORMAT_FORMATTER);
store.setToDefault(ModelPreferences.SQL_FORMAT_KEYWORD_CASE);
store.setToDefault(ModelPreferences.SQL_FORMAT_EXTERNAL_CMD);
}
@Override
protected void performApply() {
super.performApply();
formatSQL();
}
@Override
protected String getPropertyPageID()
{
return PAGE_ID;
}
private void showFormatterSettings() {
final boolean isDefFormatter = formatterSelector.getSelectionIndex() == 0;
defaultGroup.setVisible(isDefFormatter);
externalGroup.setVisible(!isDefFormatter);
((GridData)defaultGroup.getLayoutData()).exclude = !isDefFormatter;
((GridData)externalGroup.getLayoutData()).exclude = isDefFormatter;
defaultGroup.getParent().layout();
}
private static String capitalizeCaseName(String name) {
return CommonUtils.capitalizeWord(name.toLowerCase(Locale.ENGLISH));
}
private void formatSQL() {
try {
try (final InputStream sqlStream = getClass().getResourceAsStream(FORMAT_FILE_NAME)) {
final String sqlText = ContentUtils.readToString(sqlStream, GeneralUtils.DEFAULT_ENCODING);
sqlViewer.setInput(new StringEditorInput("SQL preview", sqlText, true, GeneralUtils.getDefaultFileEncoding()));
}
} catch (Exception e) {
log.error(e);
}
sqlViewer.getTextViewer().doOperation(ISourceViewer.FORMAT);
sqlViewer.reloadSyntaxRules();
}
}