28#include <QFontDatabase>
31#include <Qsci/qscistyle.h>
35QMap< QgsCodeEditorColorScheme::ColorRole, QString > QgsCodeEditor::sColorRoleToSettingsKey
76 : QsciScintilla( parent )
77 , mWidgetTitle( title )
82 if ( !parent && mWidgetTitle.isEmpty() )
84 setWindowTitle( QStringLiteral(
"Text Editor" ) );
88 setWindowTitle( mWidgetTitle );
94 mSoftHistory.append( QString() );
97 setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
99 SendScintilla( SCI_SETADDITIONALSELECTIONTYPING, 1 );
100 SendScintilla( SCI_SETMULTIPASTE, 1 );
101 SendScintilla( SCI_SETVIRTUALSPACEOPTIONS, SCVS_RECTANGULARSELECTION );
106 setAnnotationDisplay( QsciScintilla::AnnotationBoxed );
122 SendScintilla( QsciScintilla::SCI_SETHSCROLLBAR, 0 );
124 setWrapMode( QsciScintilla::WrapCharacter );
131 SendScintilla( QsciScintilla::SCI_SETHSCROLLBAR, 0 );
133 setWrapMode( QsciScintilla::WrapCharacter );
134 SendScintilla( QsciScintilla::SCI_EMPTYUNDOBUFFER );
143#if QSCINTILLA_VERSION >= 0x020800 && QSCINTILLA_VERSION < 0x020900
144 if ( event->reason() != Qt::ActiveWindowFocusReason )
158 QFocusEvent newFocusEvent( QEvent::FocusOut, Qt::ActiveWindowFocusReason );
159 QsciScintilla::focusOutEvent( &newFocusEvent );
164 QsciScintilla::focusOutEvent( event );
173 if ( isListActive() )
175 QsciScintilla::keyPressEvent( event );
179 if ( event->key() == Qt::Key_Escape )
182 QWidget::keyPressEvent( event );
188 switch ( event->key() )
211 QsciScintilla::keyPressEvent( event );
219 QsciScintilla::contextMenuEvent( event );
223 QMenu *menu =
new QMenu(
this );
224 QMenu *historySubMenu =
new QMenu( tr(
"Command History" ), menu );
230 menu->addMenu( historySubMenu );
231 menu->addSeparator();
233 QAction *copyAction = menu->addAction(
QgsApplication::getThemeIcon(
"mActionEditCopy.svg" ), tr(
"Copy" ),
this, &QgsCodeEditor::copy, QKeySequence::Copy );
234 QAction *pasteAction = menu->addAction(
QgsApplication::getThemeIcon(
"mActionEditPaste.svg" ), tr(
"Paste" ),
this, &QgsCodeEditor::paste, QKeySequence::Paste );
235 copyAction->setEnabled( hasSelectedText() );
236 pasteAction->setEnabled( !QApplication::clipboard()->text().isEmpty() );
240 menu->exec( mapToGlobal( event->pos() ) );
250 if ( mUseDefaultSettings )
251 return color( role );
253 if ( !mOverrideColors )
259 const QColor
color = mCustomColors.value( role );
266 if ( mUseDefaultSettings )
269 QFont font = QFontDatabase::systemFont( QFontDatabase::FixedFont );
272 if ( !mFontFamily.isEmpty() )
273 font.setFamily( mFontFamily );
277 font.setPointSize( mFontSize );
281 font.setPointSize( QLabel().font().pointSize() );
285 font.setPointSize( mFontSize );
288 const int fontSize = settings.
value( QStringLiteral(
"qgis/stylesheet/fontPointSize" ), 10 ).toInt();
289 font.setPointSize( fontSize );
292 font.setBold(
false );
313 setCaretLineVisible(
false );
316 setMarginLineNumbers( 1,
true );
317 setMarginWidth( 1,
"00000" );
318 setMarginType( 1, QsciScintilla::MarginType::TextMarginRightJustified );
320 setEdgeMode( QsciScintilla::EdgeNone );
324void QgsCodeEditor::setSciWidget()
330 setCaretLineVisible(
true );
336 setBraceMatching( QsciScintilla::SloppyBraceMatch );
343 setFolding( QsciScintilla::NoFoldStyle );
355 setFoldMarginColors( foldColor, foldColor );
357 setAutoIndent(
true );
358 setIndentationWidth( 4 );
359 setTabIndents(
true );
360 setBackspaceUnindents(
true );
363 setAutoCompletionThreshold( 2 );
364 setAutoCompletionSource( QsciScintilla::AcsAPIs );
372 setWindowTitle( title );
387 return tr(
"Expression" );
391 return tr(
"JavaScript" );
395 return tr(
"Python" );
412 marginFont.setPointSize( 10 );
413 setMarginLineNumbers( 0,
true );
414 setMarginsFont( marginFont );
432 marginFont.setPointSize( 10 );
434 setMarginsFont( marginFont );
469void QgsCodeEditor::updateFolding()
476 setFolding( QsciScintilla::PlainFoldStyle );
480 setFolding( QsciScintilla::NoFoldStyle );
485bool QgsCodeEditor::readHistoryFile()
487 if ( mHistoryFilePath.isEmpty() || !QFile::exists( mHistoryFilePath ) )
490 QFile file( mHistoryFilePath );
491 if ( file.open( QIODevice::ReadOnly ) )
493 QTextStream stream( &file );
494#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
496 stream.setCodec(
"UTF-8" );
499 while ( !stream.atEnd() )
501 line = stream.readLine();
502 mHistory.append( line );
511void QgsCodeEditor::syncSoftHistory()
513 mSoftHistory = mHistory;
514 mSoftHistory.append( QString() );
515 mSoftHistoryIndex = mSoftHistory.length() - 1;
520 mSoftHistory[mSoftHistoryIndex] = text();
523void QgsCodeEditor::updateHistory(
const QStringList &commands,
bool skipSoftHistory )
525 if ( commands.size() > 1 )
527 mHistory.append( commands );
529 else if ( !commands.value( 0 ).isEmpty() )
531 const QString command = commands.value( 0 );
532 if ( mHistory.empty() || command != mHistory.constLast() )
533 mHistory.append( command );
536 if ( !skipSoftHistory )
550 SendScintilla( QsciScintilla::SCI_MARGINSETTEXT,
static_cast< uintptr_t
>( 0 ), prompt.toUtf8().constData() );
561 mInterpreter = newInterpreter;
572 updateHistory( { command } );
575 mInterpreter->
exec( command );
594 if ( !mHistoryFilePath.isEmpty() && QFile::exists( mHistoryFilePath ) )
596 QFile file( mHistoryFilePath );
597 file.open( QFile::WriteOnly | QFile::Truncate );
605 if ( mHistoryFilePath.isEmpty() )
608 QFile f( mHistoryFilePath );
609 if ( !f.open( QFile::WriteOnly | QIODevice::Truncate ) )
614 QTextStream ts( &f );
615#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
616 ts.setCodec(
"UTF-8" );
618 for (
const QString &command : std::as_const( mHistory ) )
620 ts << command +
'\n';
627 if ( mSoftHistoryIndex < mSoftHistory.length() - 1 && !mSoftHistory.isEmpty() )
629 mSoftHistoryIndex += 1;
630 setText( mSoftHistory[mSoftHistoryIndex] );
637 if ( mSoftHistoryIndex > 0 && !mSoftHistory.empty() )
639 mSoftHistoryIndex -= 1;
640 setText( mSoftHistory[mSoftHistoryIndex] );
648 dialog->setAttribute( Qt::WA_DeleteOnClose );
651 dialog->activateWindow();
657 mHistory.removeAt( index );
658 mSoftHistory.removeAt( index );
659 if ( index < mSoftHistoryIndex )
661 mSoftHistoryIndex -= 1;
662 if ( mSoftHistoryIndex < 0 )
663 mSoftHistoryIndex = mSoftHistory.length() - 1;
670 if ( hasSelectedText() )
672 replaceSelectedText( text );
677 getCursorPosition( &line, &index );
678 insertAt( text, line, index );
679 setCursorPosition( line, index + text.length() );
688 const QPalette
pal = qApp->palette();
693 return pal.color( QPalette::Highlight );
695 return pal.color( QPalette::HighlightedText );
700 else if ( theme.isEmpty() )
705 static const QMap< QgsCodeEditorColorScheme::ColorRole, QString > sColorRoleToIniKey
749 return scheme.
color( role );
755 if ( !settings.
value( QStringLiteral(
"codeEditor/overrideColors" ),
false,
QgsSettings::Gui ).toBool() )
757 const QString theme = settings.
value( QStringLiteral(
"codeEditor/colorScheme" ), QString(),
QgsSettings::Gui ).toString();
762 const QString
color = settings.
value( QStringLiteral(
"codeEditor/%1" ).arg( sColorRoleToSettingsKey.value( role ) ), QString(),
QgsSettings::Gui ).toString();
770 if (
color.isValid() )
776 settings.
remove( QStringLiteral(
"codeEditor/%1" ).arg( sColorRoleToSettingsKey.value( role ) ),
QgsSettings::Gui );
783 return font.fixedPitch();
788 QFont font = QFontDatabase::systemFont( QFontDatabase::FixedFont );
791 if ( !settings.
value( QStringLiteral(
"codeEditor/fontfamily" ), QString(),
QgsSettings::Gui ).toString().isEmpty() )
792 font.setFamily( settings.
value( QStringLiteral(
"codeEditor/fontfamily" ), QString(),
QgsSettings::Gui ).toString() );
794 const int fontSize = settings.
value( QStringLiteral(
"codeEditor/fontsize" ), 0,
QgsSettings::Gui ).toInt();
798 font.setPointSize( fontSize );
802 font.setPointSize( QLabel().font().pointSize() );
806 font.setPointSize( fontSize );
809 const int fontSize = settings.
value( QStringLiteral(
"qgis/stylesheet/fontPointSize" ), 10 ).toInt();
810 font.setPointSize( fontSize );
813 font.setBold(
false );
820 mUseDefaultSettings =
false;
821 mOverrideColors = !customColors.isEmpty();
822 mColorScheme = scheme;
823 mCustomColors = customColors;
824 mFontFamily = fontFamily;
825 mFontSize = fontSize;
834 markerAdd( lineNumber, MARKER_NUMBER );
836 font.setItalic(
true );
837 const QsciStyle styleAnn = QsciStyle( -1, QStringLiteral(
"Annotation" ),
842 annotate( lineNumber, warning, styleAnn );
843 mWarningLines.push_back( lineNumber );
848 for (
const int line : mWarningLines )
850 markerDelete( line );
851 clearAnnotations( line );
854 mWarningLines.clear();
861 getCursorPosition( &line, &index );
862 return line == lines() - 1;
867 mHistoryFilePath = path;
873 setCursorPosition( 0, 0 );
874 ensureCursorVisible();
875 ensureLineVisible( 0 );
883 const int endLine = lines() - 1;
884 const int endLineLength = lineLength( endLine );
885 setCursorPosition( endLine, endLineLength );
886 ensureCursorVisible();
887 ensureLineVisible( endLine );
ScriptLanguage
Scripting languages.
@ QgisExpression
QGIS expressions.
@ Unknown
Unknown/other language.
static QPixmap getThemePixmap(const QString &name, const QColor &foreColor=QColor(), const QColor &backColor=QColor(), int size=16)
Helper to get a theme icon as a pixmap.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QHash< QString, QString > uiThemes()
All themes found in ~/.qgis3/themes folder.
static QString themeName()
Set the active theme to the specified theme.
QgsCodeEditorColorScheme scheme(const QString &id) const
Returns the color scheme with matching id.
Defines a color scheme for use in QgsCodeEditor widgets.
@ TripleSingleQuote
Triple single quote color.
@ CommentBlock
Comment block color.
@ QuotedOperator
Quoted operator color.
@ Decoration
Decoration color.
@ Identifier
Identifier color.
@ DoubleQuote
Double quote color.
@ QuotedIdentifier
Quoted identifier color.
@ SelectionForeground
Selection foreground color.
@ CommentLine
Line comment color.
@ FoldIconForeground
Fold icon foreground color.
@ MarginForeground
Margin foreground color.
@ ErrorBackground
Error background color.
@ MatchedBraceBackground
Matched brace background color.
@ Default
Default text color.
@ CaretLine
Caret line color.
@ IndentationGuide
Indentation guide line.
@ Background
Background color.
@ SingleQuote
Single quote color.
@ MarginBackground
Margin background color.
@ SelectionBackground
Selection background color.
@ MatchedBraceForeground
Matched brace foreground color.
@ Operator
Operator color.
@ TripleDoubleQuote
Triple double quote color.
@ FoldIconHalo
Fold icon halo color.
QColor color(ColorRole role) const
Returns the color to use in the editor for the specified role.
A dialog for displaying and managing command history for a QgsCodeEditor widget.
void sessionHistoryCleared()
Emitted when the history of commands run in the current session is cleared.
void showHistory()
Shows the command history dialog.
void setCustomAppearance(const QString &scheme=QString(), const QMap< QgsCodeEditorColorScheme::ColorRole, QColor > &customColors=QMap< QgsCodeEditorColorScheme::ColorRole, QColor >(), const QString &fontFamily=QString(), int fontSize=0)
Sets a custom appearance for the widget, disconnecting it from using the standard appearance taken fr...
@ OutputDisplay
Read only mode for display of command outputs.
@ ScriptEditor
Standard mode, allows for display and edit of entire scripts.
@ CommandInput
Command input mode.
void contextMenuEvent(QContextMenuEvent *event) override
void clearPersistentHistory()
Clears the entire persistent history of commands run in the editor.
void removeHistoryCommand(int index)
Removes the command at the specified index from the history of the code editor.
static void setColor(QgsCodeEditorColorScheme::ColorRole role, const QColor &color)
Sets the color to use in the editor for the specified role.
void setHistoryFilePath(const QString &path)
Sets the file path to use for recording and retrieving previously executed commands.
QStringList history() const
Returns the list of commands previously executed in the editor.
void keyPressEvent(QKeyEvent *event) override
virtual void moveCursorToStart()
Moves the cursor to the start of the document and scrolls to ensure it is visible.
virtual void populateContextMenu(QMenu *menu)
Called when the context menu for the widget is about to be shown, after it has been fully populated w...
void persistentHistoryCleared()
Emitted when the persistent history of commands run in the editor is cleared.
void setFoldingVisible(bool folding)
Set whether the folding controls are visible in the editor.
void setInterpreter(QgsCodeInterpreter *newInterpreter)
Sets an attached code interpreter for executing commands when the editor is in the QgsCodeEditor::Mod...
@ FoldingControls
Folding controls.
@ ErrorIndicators
Error indicators.
@ LineNumbers
Line numbers.
void runPostLexerConfigurationTasks()
Performs tasks which must be run after a lexer has been set for the widget.
virtual void initializeLexer()
Called when the dialect specific code lexer needs to be initialized (or reinitialized).
void setTitle(const QString &title)
Set the widget title.
QgsCodeEditor(QWidget *parent=nullptr, const QString &title=QString(), bool folding=false, bool margin=false, QgsCodeEditor::Flags flags=QgsCodeEditor::Flags(), QgsCodeEditor::Mode mode=QgsCodeEditor::Mode::ScriptEditor)
Flags controlling behavior of code editor.
void clearWarnings()
Clears all warning messages from the editor.
static QFont getMonospaceFont()
Returns the monospaced font to use for code editors.
void showNextCommand()
Shows the next command from the session in the editor.
void focusOutEvent(QFocusEvent *event) override
@ CodeFolding
Indicates that code folding should be enabled for the editor.
bool isCursorOnLastLine() const
Returns true if the cursor is on the last line of the document.
static bool isFixedPitch(const QFont &font)
Returns true if a font is a fixed pitch font.
void updateSoftHistory()
Updates the soft history by storing the current editor text in the history.
void clearSessionHistory()
Clears the history of commands run in the current session.
void insertText(const QString &text)
Insert text at cursor position, or replace any selected text if user has made a selection.
bool writeHistoryFile()
Stores the commands executed in the editor to the persistent history file.
virtual void moveCursorToEnd()
Moves the cursor to the end of the document and scrolls to ensure it is visible.
static QString languageToString(Qgis::ScriptLanguage language)
Returns a user-friendly, translated name of the specified script language.
void setLineNumbersVisible(bool visible)
Sets whether line numbers should be visible in the editor.
void runCommand(const QString &command)
Runs a command in the editor.
virtual Qgis::ScriptLanguage language() const
Returns the associated scripting language.
QFont lexerFont() const
Returns the font to use in the lexer.
QgsCodeInterpreter * interpreter() const
Returns the attached code interpreter, or nullptr if not set.
bool lineNumbersVisible() const
Returns whether line numbers are visible in the editor.
QColor lexerColor(QgsCodeEditorColorScheme::ColorRole role) const
Returns the color to use in the lexer for the specified role.
bool foldingVisible()
Returns true if the folding controls are visible in the editor.
void showPreviousCommand()
Shows the previous command from the session in the editor.
Q_DECL_DEPRECATED void setMarginVisible(bool margin)
Set margin visible state.
void updatePrompt()
Triggers an update of the interactive prompt part of the editor.
static QColor defaultColor(QgsCodeEditorColorScheme::ColorRole role, const QString &theme=QString())
Returns the default color for the specified role.
void addWarning(int lineNumber, const QString &warning)
Adds a warning message and indicator to the specified a lineNumber.
static QColor color(QgsCodeEditorColorScheme::ColorRole role)
Returns the color to use in the editor for the specified role.
An interface for code interpreters.
virtual int execCommandImpl(const QString &command)=0
Pure virtual method for executing commands in the interpreter.
virtual int currentState() const
Returns the current interpreter state.
virtual QString promptForState(int state) const =0
Returns the interactive prompt string to use for the interpreter, given a state.
int exec(const QString &command)
Executes a command in the interpreter.
virtual ~QgsCodeInterpreter()
void optionsChanged()
This signal is emitted whenever the application options have been changed.
static QgsGui * instance()
Returns a pointer to the singleton instance.
static QgsCodeEditorColorSchemeRegistry * codeEditorColorSchemeRegistry()
Returns the global code editor color scheme registry, used for registering the color schemes for QgsC...
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void remove(const QString &key, QgsSettings::Section section=QgsSettings::NoSection)
Removes the setting key and any sub-settings of key in a section.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static QColor decodeColor(const QString &str)
#define BUILTIN_UNREACHABLE