Skip to content
Permalink
Browse files

Show a code editor preview widget in the code editor settings panel

Allows instant preview of changes
  • Loading branch information
nyalldawson committed Oct 5, 2020
1 parent 8654efd commit f5cd52f81b4f8c7fa95b244a5de71690662231dd
@@ -12,6 +12,7 @@




class QgsCodeEditor : QsciScintilla
{
%Docstring
@@ -156,6 +157,7 @@ Returns the monospaced font to use for code editors.
.. versionadded:: 3.16
%End


protected:

bool isFixedPitch( const QFont &font );
@@ -171,6 +173,20 @@ Called when the dialect specific code lexer needs to be initialized (or reinitia

The default implementation does nothing.

.. versionadded:: 3.16
%End

QColor lexerColor( ColorRole role ) const;
%Docstring
Returns the color to use in the lexer for the specified ``role``.

.. versionadded:: 3.16
%End

QFont lexerFont() const;
%Docstring
Returns the font to use in the lexer.

.. versionadded:: 3.16
%End

@@ -99,6 +99,8 @@ QgsCodeEditorOptionsWidget::QgsCodeEditorOptionsWidget( QWidget *parent )
}
mBlockCustomColorChange = false;
}

updatePreview();
} );

for ( auto it = mColorButtonMap.constBegin(); it != mColorButtonMap.constEnd(); ++it )
@@ -109,6 +111,7 @@ QgsCodeEditorOptionsWidget::QgsCodeEditorOptionsWidget( QWidget *parent )
return;

mColorSchemeComboBox->setCurrentIndex( mColorSchemeComboBox->findData( QStringLiteral( "custom" ) ) );
updatePreview();
} );
}

@@ -117,6 +120,132 @@ QgsCodeEditorOptionsWidget::QgsCodeEditorOptionsWidget( QWidget *parent )
mFontComboBox->setCurrentFont( font );
mSizeSpin->setValue( font.pointSize() );
mOverrideFontGroupBox->setChecked( !settings.value( QStringLiteral( "codeEditor/fontfamily" ), QString(), QgsSettings::Gui ).toString().isEmpty() );

connect( mFontComboBox, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, [ = ]
{
updatePreview();
} );
connect( mSizeSpin, qgis::overload<int>::of( &QSpinBox::valueChanged ), this, [ = ]
{
updatePreview();
} );
connect( mOverrideFontGroupBox, &QGroupBox::toggled, this, [ = ]
{
updatePreview();
} );

mListLanguage->addItem( tr( "Python" ) );
mListLanguage->addItem( tr( "QGIS Expression" ) );
mListLanguage->addItem( tr( "SQL" ) );
mListLanguage->addItem( tr( "HTML" ) );
mListLanguage->addItem( tr( "CSS" ) );
mListLanguage->addItem( tr( "JavaScript" ) );

connect( mListLanguage, &QListWidget::currentRowChanged, this, [ = ]
{
mPreviewStackedWidget->setCurrentIndex( mListLanguage->currentRow() );
} );

mPythonPreview->setText( R"""(def simple_function(x,y,z):
"""
Function docstring
"""
return [1, 1.2, "val", 'a string', {'a': 1, 'b': 2}]
@my_decorator
def somefunc(param1: str='', param2=0):
r'''A docstring'''
if param1 > param2: # interesting
print('Gre\'ater'.lower())
return (param2 - param1 + 1 + 0b10l) or None
class SomeClass:
"""
My class docstring
"""
pass
)""" );

mExpressionPreview->setText( R"""(aggregate(layer:='rail_stations',
aggregate:='collect', -- a comment
expression:=centroid($geometry), /* a comment */
filter:="region_name" = attribute(@parent,'name') + 55
)
)""");

mSQLPreview->setText( R"""(CREATE TABLE "my_table" (
"pk" serial NOT NULL PRIMARY KEY,
"a_field" integer,
"another_field" varchar(255)
);
-- Retrieve values
SELECT count(*) FROM "my_table" WHERE "a_field" > 'a value';
)""");

mHtmlPreview->setText(R"""(<html>
<head>
<title>QGIS</title>
</head>
<body>
<h1>QGIS Rocks!</h1>
<img src="qgis.png" style="width: 100px" />
<!--Sample comment-->
<p>Sample paragraph</p>
</body>
</html>
)""");

mCssPreview->setText( R"""(@import url(print.css);
@font-face {
font-family: DroidSans; /* A comment */
src: url('DroidSans.ttf');
}
p.style_name:lang(en) {
color: #F0F0F0;
background: #600;
}
ul > li, a:hover {
line-height: 11px;
text-decoration: underline;
}
@media print {
a[href^=http]::after {
content: attr(href)
}
}
)""" );

mJsPreview->setText( R"""(// my sample JavaScript function
window.onAction(function update() {
/* Do some work */
var prevPos = closure.pos;
element.width = 100;
element.height = 2500;
element.name = 'a string';
element.title= "another string";
if (prevPos.x > 100) {
element.x += max(100*2, 100);
}
});)""" );

mListLanguage->setCurrentRow( 0 );
mPreviewStackedWidget->setCurrentIndex( 0 );

mSplitter->restoreState( settings.value( QStringLiteral( "Windows/CodeEditorOptions/splitterState" ) ).toByteArray() );
}

QgsCodeEditorOptionsWidget::~QgsCodeEditorOptionsWidget()
{
QgsSettings settings;
settings.setValue( QStringLiteral( "Windows/CodeEditorOptions/splitterState" ), mSplitter->saveState() );
}

QString QgsCodeEditorOptionsWidget::helpKey() const
@@ -152,6 +281,37 @@ void QgsCodeEditorOptionsWidget::apply()
}
}

void QgsCodeEditorOptionsWidget::updatePreview()
{
QString theme = mColorSchemeComboBox->currentData().toString();


QMap< QgsCodeEditor::ColorRole, QColor> colors;
if ( theme == QLatin1String( "custom" ) )
{
for ( auto it = mColorButtonMap.constBegin(); it != mColorButtonMap.constEnd(); ++it )
{
colors[ it.key() ] = it.value()->color();
}
theme.clear();
}

QString fontFamily;
int fontSize = 0;
if ( mOverrideFontGroupBox->isChecked() )
{
fontFamily = mFontComboBox->currentFont().family();
fontSize = mSizeSpin->value();
}

mPythonPreview->setCustomAppearance( theme, colors, fontFamily, fontSize );
mExpressionPreview->setCustomAppearance( theme, colors, fontFamily, fontSize );
mSQLPreview->setCustomAppearance( theme, colors, fontFamily, fontSize );
mHtmlPreview->setCustomAppearance( theme, colors, fontFamily, fontSize );
mCssPreview->setCustomAppearance( theme, colors, fontFamily, fontSize );
mJsPreview->setCustomAppearance( theme, colors, fontFamily, fontSize );
}

//
// QgsCodeEditorOptionsFactory
//
@@ -36,6 +36,7 @@ class QgsCodeEditorOptionsWidget : public QgsOptionsPageWidget, private Ui::QgsC
* Constructor for QgsCodeEditorOptionsWidget with the specified \a parent widget.
*/
QgsCodeEditorOptionsWidget( QWidget *parent );
~QgsCodeEditorOptionsWidget() override;

QString helpKey() const override;

@@ -46,6 +47,9 @@ class QgsCodeEditorOptionsWidget : public QgsOptionsPageWidget, private Ui::QgsC
QMap< QgsCodeEditor::ColorRole, QgsColorButton * > mColorButtonMap;
bool mBlockCustomColorChange = false;

void updatePreview();


};


@@ -140,30 +140,79 @@ void QgsCodeEditor::initializeLexer()

}

QColor QgsCodeEditor::lexerColor( QgsCodeEditor::ColorRole role ) const
{
if ( mUseDefaultSettings )
return color( role );

if ( !mOverrideColors )
{
return defaultColor( role, mColorScheme );
}
else
{
const QColor color = mCustomColors.value( role );
return !color.isValid() ? defaultColor( role ) : color;
}
}

QFont QgsCodeEditor::lexerFont() const
{
if ( mUseDefaultSettings )
return getMonospaceFont();

QFont font = QFontDatabase::systemFont( QFontDatabase::FixedFont );

QgsSettings settings;
if ( !mFontFamily.isEmpty() )
font.setFamily( mFontFamily );

#ifdef Q_OS_MAC
if ( mFontSize > 0 )
font.setPointSize( mFontSize );
else
{
// The font size gotten from getMonospaceFont() is too small on Mac
font.setPointSize( QLabel().font().pointSize() );
}
#else
if ( mFontSize > 0 )
font.setPointSize( mFontSize );
else
{
int fontSize = settings.value( QStringLiteral( "qgis/stylesheet/fontPointSize" ), 10 ).toInt();
font.setPointSize( fontSize );
}
#endif
font.setBold( false );

return font;
}

void QgsCodeEditor::setSciWidget()
{
QFont font = getMonospaceFont();
QFont font = lexerFont();
setFont( font );

setUtf8( true );
setCaretLineVisible( true );
setCaretLineBackgroundColor( color( ColorRole::CaretLine ) );
setCaretForegroundColor( color( ColorRole::Cursor ) );
setSelectionForegroundColor( color( ColorRole::SelectionForeground ) );
setSelectionBackgroundColor( color( ColorRole::SelectionBackground ) );
setCaretLineBackgroundColor( lexerColor( ColorRole::CaretLine ) );
setCaretForegroundColor( lexerColor( ColorRole::Cursor ) );
setSelectionForegroundColor( lexerColor( ColorRole::SelectionForeground ) );
setSelectionBackgroundColor( lexerColor( ColorRole::SelectionBackground ) );

setBraceMatching( QsciScintilla::SloppyBraceMatch );
setMatchedBraceForegroundColor( color( ColorRole::MatchedBraceForeground ) );
setMatchedBraceBackgroundColor( color( ColorRole::MatchedBraceBackground ) );
setMatchedBraceForegroundColor( lexerColor( ColorRole::MatchedBraceForeground ) );
setMatchedBraceBackgroundColor( lexerColor( ColorRole::MatchedBraceBackground ) );
// whether margin will be shown
setMarginVisible( mMargin );
setMarginsForegroundColor( color( ColorRole::MarginForeground ) );
setMarginsBackgroundColor( color( ColorRole::MarginBackground ) );
setIndentationGuidesForegroundColor( color( ColorRole::MarginForeground ) );
setIndentationGuidesBackgroundColor( color( ColorRole::MarginBackground ) );
setMarginsForegroundColor( lexerColor( ColorRole::MarginForeground ) );
setMarginsBackgroundColor( lexerColor( ColorRole::MarginBackground ) );
setIndentationGuidesForegroundColor( lexerColor( ColorRole::MarginForeground ) );
setIndentationGuidesBackgroundColor( lexerColor( ColorRole::MarginBackground ) );
// whether margin will be shown
setFoldingVisible( mFolding );
QColor foldColor = color( ColorRole::Fold );
QColor foldColor = lexerColor( ColorRole::Fold );
setFoldMarginColors( foldColor, foldColor );
// indentation
setAutoIndent( true );
@@ -186,7 +235,7 @@ void QgsCodeEditor::setMarginVisible( bool margin )
mMargin = margin;
if ( margin )
{
QFont marginFont = getMonospaceFont();
QFont marginFont = lexerFont();
marginFont.setPointSize( 10 );
setMarginLineNumbers( 1, true );
setMarginsFont( marginFont );
@@ -407,7 +456,6 @@ QColor QgsCodeEditor::defaultColor( QgsCodeEditor::ColorRole role, const QString
QColor QgsCodeEditor::color( QgsCodeEditor::ColorRole role )
{
const QgsSettings settings;

if ( !settings.value( QStringLiteral( "codeEditor/overrideColors" ), false, QgsSettings::Gui ).toBool() )
{
const QString theme = settings.value( QStringLiteral( "codeEditor/colorScheme" ), QString(), QgsSettings::Gui ).toString();
@@ -470,3 +518,16 @@ QFont QgsCodeEditor::getMonospaceFont()

return font;
}

void QgsCodeEditor::setCustomAppearance( const QString &scheme, const QMap<QgsCodeEditor::ColorRole, QColor> &customColors, const QString &fontFamily, int fontSize )
{
mUseDefaultSettings = false;
mOverrideColors = !customColors.isEmpty();
mColorScheme = scheme;
mCustomColors = customColors;
mFontFamily = fontFamily;
mFontSize = fontSize;

setSciWidget();
initializeLexer();
}

0 comments on commit f5cd52f

Please sign in to comment.
You can’t perform that action at this time.