mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-07 00:15:48 -04:00
369 lines
12 KiB
C++
369 lines
12 KiB
C++
/***************************************************************************
|
|
qgscodeeditoroptions.cpp
|
|
-------------------------
|
|
begin : September 2020
|
|
copyright : (C) 2020 by Nyall Dawson
|
|
email : nyall dot dawson at gmail dot com
|
|
***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "qgscodeeditoroptions.h"
|
|
#include "qgsapplication.h"
|
|
#include "qgssettings.h"
|
|
#include "qgis.h"
|
|
#include "qgsgui.h"
|
|
#include "qgscodeeditorcolorschemeregistry.h"
|
|
|
|
//
|
|
// QgsCodeEditorOptionsWidget
|
|
//
|
|
|
|
QgsCodeEditorOptionsWidget::QgsCodeEditorOptionsWidget( QWidget *parent )
|
|
: QgsOptionsPageWidget( parent )
|
|
{
|
|
setupUi( this );
|
|
|
|
layout()->setContentsMargins( 0, 0, 0, 0 );
|
|
|
|
mSizeSpin->setClearValue( 10 );
|
|
|
|
mColorButtonMap =
|
|
{
|
|
{QgsCodeEditorColorScheme::ColorRole::Default, mColorDefault },
|
|
{QgsCodeEditorColorScheme::ColorRole::Keyword, mColorKeyword },
|
|
{QgsCodeEditorColorScheme::ColorRole::Class, mColorClass },
|
|
{QgsCodeEditorColorScheme::ColorRole::Method, mColorFunction },
|
|
{QgsCodeEditorColorScheme::ColorRole::Decoration, mColorDecorator },
|
|
{QgsCodeEditorColorScheme::ColorRole::Number, mColorNumber },
|
|
{QgsCodeEditorColorScheme::ColorRole::Comment, mColorComment },
|
|
{QgsCodeEditorColorScheme::ColorRole::CommentLine, mColorCommentLine },
|
|
{QgsCodeEditorColorScheme::ColorRole::CommentBlock, mColorCommentBlock },
|
|
{QgsCodeEditorColorScheme::ColorRole::Background, mColorBackground },
|
|
{QgsCodeEditorColorScheme::ColorRole::Cursor, mColorCursor },
|
|
{QgsCodeEditorColorScheme::ColorRole::CaretLine, mColorCaretLine },
|
|
{QgsCodeEditorColorScheme::ColorRole::Operator, mColorOperator },
|
|
{QgsCodeEditorColorScheme::ColorRole::QuotedOperator, mColorQuotedOperator },
|
|
{QgsCodeEditorColorScheme::ColorRole::Identifier, mColorIdentifier },
|
|
{QgsCodeEditorColorScheme::ColorRole::QuotedIdentifier, mColorQuotedIdentifier },
|
|
{QgsCodeEditorColorScheme::ColorRole::Tag, mColorTag },
|
|
{QgsCodeEditorColorScheme::ColorRole::UnknownTag, mColorUnknownTag },
|
|
{QgsCodeEditorColorScheme::ColorRole::SingleQuote, mColorSingleQuote },
|
|
{QgsCodeEditorColorScheme::ColorRole::DoubleQuote, mColorDoubleQuote },
|
|
{QgsCodeEditorColorScheme::ColorRole::TripleSingleQuote, mColorTripleSingleQuote },
|
|
{QgsCodeEditorColorScheme::ColorRole::TripleDoubleQuote, mColorTripleDoubleQuote },
|
|
{QgsCodeEditorColorScheme::ColorRole::MarginBackground, mColorMarginBackground },
|
|
{QgsCodeEditorColorScheme::ColorRole::MarginForeground, mColorMarginForeground },
|
|
{QgsCodeEditorColorScheme::ColorRole::SelectionBackground, mColorSelectionBackground },
|
|
{QgsCodeEditorColorScheme::ColorRole::SelectionForeground, mColorSelectionForeground },
|
|
{QgsCodeEditorColorScheme::ColorRole::MatchedBraceBackground, mColorBraceBackground },
|
|
{QgsCodeEditorColorScheme::ColorRole::MatchedBraceForeground, mColorBraceForeground },
|
|
{QgsCodeEditorColorScheme::ColorRole::Edge, mColorEdge },
|
|
{QgsCodeEditorColorScheme::ColorRole::Fold, mColorFold },
|
|
{QgsCodeEditorColorScheme::ColorRole::Error, mColorError },
|
|
{QgsCodeEditorColorScheme::ColorRole::ErrorBackground, mColorErrorBackground },
|
|
{QgsCodeEditorColorScheme::ColorRole::FoldIconForeground, mColorFoldIcon },
|
|
{QgsCodeEditorColorScheme::ColorRole::FoldIconHalo, mColorFoldIconHalo },
|
|
{QgsCodeEditorColorScheme::ColorRole::IndentationGuide, mColorIndentation },
|
|
};
|
|
|
|
for ( auto it = mColorButtonMap.constBegin(); it != mColorButtonMap.constEnd(); ++it )
|
|
{
|
|
it.value()->setColor( QgsCodeEditor::color( it.key() ) );
|
|
it.value()->setDefaultColor( it.value()->color() );
|
|
}
|
|
|
|
mColorSchemeComboBox->addItem( tr( "Default" ), QString() );
|
|
|
|
QMap< QString, QString> themeNameToId;
|
|
QStringList names;
|
|
const QStringList ids = QgsGui::codeEditorColorSchemeRegistry()->schemes();
|
|
for ( const QString &id : ids )
|
|
{
|
|
if ( id == QLatin1String( "default" ) )
|
|
continue;
|
|
|
|
const QString name = QgsGui::codeEditorColorSchemeRegistry()->scheme( id ).name();
|
|
names << name;
|
|
themeNameToId.insert( name, id );
|
|
}
|
|
|
|
std::sort( names.begin(), names.end() );
|
|
for ( const QString &name : std::as_const( names ) )
|
|
{
|
|
mColorSchemeComboBox->addItem( name, themeNameToId.value( name ) );
|
|
}
|
|
|
|
mColorSchemeComboBox->addItem( tr( "Custom" ), QStringLiteral( "custom" ) );
|
|
|
|
QgsSettings settings;
|
|
if ( !settings.value( QStringLiteral( "codeEditor/overrideColors" ), false, QgsSettings::Gui ).toBool() )
|
|
{
|
|
const QString theme = settings.value( QStringLiteral( "codeEditor/colorScheme" ), QString(), QgsSettings::Gui ).toString();
|
|
mColorSchemeComboBox->setCurrentIndex( mColorSchemeComboBox->findData( theme ) );
|
|
}
|
|
else
|
|
{
|
|
mColorSchemeComboBox->setCurrentIndex( mColorSchemeComboBox->findData( QStringLiteral( "custom" ) ) );
|
|
}
|
|
|
|
connect( mColorSchemeComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [ = ]
|
|
{
|
|
const QString theme = mColorSchemeComboBox->currentData().toString();
|
|
if ( theme != QLatin1String( "custom" ) )
|
|
{
|
|
mBlockCustomColorChange = true;
|
|
for ( auto it = mColorButtonMap.constBegin(); it != mColorButtonMap.constEnd(); ++it )
|
|
{
|
|
it.value()->setColor( QgsCodeEditor::defaultColor( it.key(), theme ) );
|
|
it.value()->setDefaultColor( it.value()->color() );
|
|
}
|
|
mBlockCustomColorChange = false;
|
|
}
|
|
|
|
updatePreview();
|
|
} );
|
|
|
|
for ( auto it = mColorButtonMap.constBegin(); it != mColorButtonMap.constEnd(); ++it )
|
|
{
|
|
connect( it.value(), &QgsColorButton::colorChanged, this, [ = ]
|
|
{
|
|
if ( mBlockCustomColorChange )
|
|
return;
|
|
|
|
mColorSchemeComboBox->setCurrentIndex( mColorSchemeComboBox->findData( QStringLiteral( "custom" ) ) );
|
|
updatePreview();
|
|
} );
|
|
}
|
|
|
|
// font
|
|
const QFont font = QgsCodeEditor::getMonospaceFont();
|
|
mFontComboBox->setCurrentFont( font );
|
|
mSizeSpin->setValue( font.pointSize() );
|
|
mOverrideFontGroupBox->setChecked( !settings.value( QStringLiteral( "codeEditor/fontfamily" ), QString(), QgsSettings::Gui ).toString().isEmpty() );
|
|
|
|
connect( mFontComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [ = ]
|
|
{
|
|
updatePreview();
|
|
} );
|
|
connect( mSizeSpin, qOverload<int>( &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': True, 'b': False}]
|
|
|
|
@my_decorator
|
|
def somefunc(param1: str='', param2=0):
|
|
'''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
|
|
{
|
|
return QStringLiteral( "introduction/qgis_configuration.html#code-editor-settings" );
|
|
}
|
|
|
|
void QgsCodeEditorOptionsWidget::apply()
|
|
{
|
|
const QString theme = mColorSchemeComboBox->currentData().toString();
|
|
|
|
QgsSettings settings;
|
|
const bool customTheme = theme == QLatin1String( "custom" );
|
|
settings.setValue( QStringLiteral( "codeEditor/overrideColors" ), customTheme, QgsSettings::Gui );
|
|
if ( !customTheme )
|
|
{
|
|
settings.setValue( QStringLiteral( "codeEditor/colorScheme" ), theme, QgsSettings::Gui );
|
|
}
|
|
for ( auto it = mColorButtonMap.constBegin(); it != mColorButtonMap.constEnd(); ++it )
|
|
{
|
|
QgsCodeEditor::setColor( it.key(), it.value()->color() );
|
|
}
|
|
|
|
if ( mOverrideFontGroupBox->isChecked() )
|
|
{
|
|
settings.setValue( QStringLiteral( "codeEditor/fontfamily" ), mFontComboBox->currentFont().family(), QgsSettings::Gui );
|
|
settings.setValue( QStringLiteral( "codeEditor/fontsize" ), mSizeSpin->value(), QgsSettings::Gui );
|
|
}
|
|
else
|
|
{
|
|
settings.remove( QStringLiteral( "codeEditor/fontfamily" ), QgsSettings::Gui );
|
|
settings.remove( QStringLiteral( "codeEditor/fontsize" ), QgsSettings::Gui );
|
|
}
|
|
}
|
|
|
|
void QgsCodeEditorOptionsWidget::updatePreview()
|
|
{
|
|
QString theme = mColorSchemeComboBox->currentData().toString();
|
|
|
|
|
|
QMap< QgsCodeEditorColorScheme::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
|
|
//
|
|
QgsCodeEditorOptionsFactory::QgsCodeEditorOptionsFactory()
|
|
: QgsOptionsWidgetFactory( tr( "Code Editor" ), QIcon() )
|
|
{
|
|
|
|
}
|
|
|
|
QIcon QgsCodeEditorOptionsFactory::icon() const
|
|
{
|
|
return QgsApplication::getThemeIcon( QStringLiteral( "/mIconCodeEditor.svg" ) );
|
|
}
|
|
|
|
QgsOptionsPageWidget *QgsCodeEditorOptionsFactory::createWidget( QWidget *parent ) const
|
|
{
|
|
return new QgsCodeEditorOptionsWidget( parent );
|
|
}
|
|
|
|
QStringList QgsCodeEditorOptionsFactory::path() const
|
|
{
|
|
return {QStringLiteral( "ide" ) };
|
|
}
|
|
|
|
QString QgsCodeEditorOptionsFactory::pagePositionHint() const
|
|
{
|
|
return QStringLiteral( "consoleOptions" );
|
|
}
|