QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgscodeeditor.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgscodeeditor.cpp - A base code editor for QGIS and plugins. Provides
3 a base editor using QScintilla for editors
4 --------------------------------------
5 Date : 06-Oct-2013
6 Copyright : (C) 2013 by Salvatore Larosa
7 Email : lrssvtml (at) gmail (dot) com
8 ***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17#include "qgsapplication.h"
18#include "qgscodeeditor.h"
19#include "qgssettings.h"
20#include "qgssymbollayerutils.h"
21#include "qgsgui.h"
24#include "qgsstringutils.h"
25#include "qgsfontutils.h"
26
27#include <QLabel>
28#include <QWidget>
29#include <QFont>
30#include <QFontDatabase>
31#include <QDebug>
32#include <QFocusEvent>
33#include <Qsci/qscistyle.h>
34#include <QMenu>
35#include <QClipboard>
36#include <QScrollBar>
37#include <QMessageBox>
38
39QMap< QgsCodeEditorColorScheme::ColorRole, QString > QgsCodeEditor::sColorRoleToSettingsKey
40{
41 {QgsCodeEditorColorScheme::ColorRole::Default, QStringLiteral( "defaultFontColor" ) },
42 {QgsCodeEditorColorScheme::ColorRole::Keyword, QStringLiteral( "keywordFontColor" ) },
43 {QgsCodeEditorColorScheme::ColorRole::Class, QStringLiteral( "classFontColor" ) },
44 {QgsCodeEditorColorScheme::ColorRole::Method, QStringLiteral( "methodFontColor" ) },
45 {QgsCodeEditorColorScheme::ColorRole::Decoration, QStringLiteral( "decoratorFontColor" ) },
46 {QgsCodeEditorColorScheme::ColorRole::Number, QStringLiteral( "numberFontColor" ) },
47 {QgsCodeEditorColorScheme::ColorRole::Comment, QStringLiteral( "commentFontColor" ) },
48 {QgsCodeEditorColorScheme::ColorRole::CommentLine, QStringLiteral( "commentLineFontColor" ) },
49 {QgsCodeEditorColorScheme::ColorRole::CommentBlock, QStringLiteral( "commentBlockFontColor" ) },
50 {QgsCodeEditorColorScheme::ColorRole::Background, QStringLiteral( "paperBackgroundColor" ) },
51 {QgsCodeEditorColorScheme::ColorRole::Cursor, QStringLiteral( "cursorColor" ) },
52 {QgsCodeEditorColorScheme::ColorRole::CaretLine, QStringLiteral( "caretLineColor" ) },
53 {QgsCodeEditorColorScheme::ColorRole::Operator, QStringLiteral( "operatorFontColor" ) },
54 {QgsCodeEditorColorScheme::ColorRole::QuotedOperator, QStringLiteral( "quotedOperatorFontColor" ) },
55 {QgsCodeEditorColorScheme::ColorRole::Identifier, QStringLiteral( "identifierFontColor" ) },
56 {QgsCodeEditorColorScheme::ColorRole::QuotedIdentifier, QStringLiteral( "quotedIdentifierFontColor" ) },
57 {QgsCodeEditorColorScheme::ColorRole::Tag, QStringLiteral( "tagFontColor" ) },
58 {QgsCodeEditorColorScheme::ColorRole::UnknownTag, QStringLiteral( "unknownTagFontColor" ) },
59 {QgsCodeEditorColorScheme::ColorRole::SingleQuote, QStringLiteral( "singleQuoteFontColor" ) },
60 {QgsCodeEditorColorScheme::ColorRole::DoubleQuote, QStringLiteral( "doubleQuoteFontColor" ) },
61 {QgsCodeEditorColorScheme::ColorRole::TripleSingleQuote, QStringLiteral( "tripleSingleQuoteFontColor" ) },
62 {QgsCodeEditorColorScheme::ColorRole::TripleDoubleQuote, QStringLiteral( "tripleDoubleQuoteFontColor" ) },
63 {QgsCodeEditorColorScheme::ColorRole::MarginBackground, QStringLiteral( "marginBackgroundColor" ) },
64 {QgsCodeEditorColorScheme::ColorRole::MarginForeground, QStringLiteral( "marginForegroundColor" ) },
65 {QgsCodeEditorColorScheme::ColorRole::SelectionBackground, QStringLiteral( "selectionBackgroundColor" ) },
66 {QgsCodeEditorColorScheme::ColorRole::SelectionForeground, QStringLiteral( "selectionForegroundColor" ) },
67 {QgsCodeEditorColorScheme::ColorRole::MatchedBraceBackground, QStringLiteral( "matchedBraceBackground" ) },
68 {QgsCodeEditorColorScheme::ColorRole::MatchedBraceForeground, QStringLiteral( "matchedBraceColor" ) },
69 {QgsCodeEditorColorScheme::ColorRole::Edge, QStringLiteral( "edgeColor" ) },
70 {QgsCodeEditorColorScheme::ColorRole::Fold, QStringLiteral( "foldColor" ) },
71 {QgsCodeEditorColorScheme::ColorRole::Error, QStringLiteral( "stderrFontColor" ) },
72 {QgsCodeEditorColorScheme::ColorRole::ErrorBackground, QStringLiteral( "stderrBackgroundColor" ) },
73 {QgsCodeEditorColorScheme::ColorRole::FoldIconForeground, QStringLiteral( "foldIconForeground" ) },
74 {QgsCodeEditorColorScheme::ColorRole::FoldIconHalo, QStringLiteral( "foldIconHalo" ) },
75 {QgsCodeEditorColorScheme::ColorRole::IndentationGuide, QStringLiteral( "indentationGuide" ) },
76};
77
78
79QgsCodeEditor::QgsCodeEditor( QWidget *parent, const QString &title, bool folding, bool margin, QgsCodeEditor::Flags flags, QgsCodeEditor::Mode mode )
80 : QsciScintilla( parent )
81 , mWidgetTitle( title )
82 , mMargin( margin )
83 , mFlags( flags )
84 , mMode( mode )
85{
86 if ( !parent && mWidgetTitle.isEmpty() )
87 {
88 setWindowTitle( QStringLiteral( "Text Editor" ) );
89 }
90 else
91 {
92 setWindowTitle( mWidgetTitle );
93 }
94
95 if ( folding )
97
98 mSoftHistory.append( QString() );
99
100 setSciWidget();
101 setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
102
103 SendScintilla( SCI_SETADDITIONALSELECTIONTYPING, 1 );
104 SendScintilla( SCI_SETMULTIPASTE, 1 );
105 SendScintilla( SCI_SETVIRTUALSPACEOPTIONS, SCVS_RECTANGULARSELECTION );
106
107 SendScintilla( SCI_SETMARGINTYPEN, static_cast< int >( QgsCodeEditor::MarginRole::ErrorIndicators ), SC_MARGIN_SYMBOL );
108 SendScintilla( SCI_SETMARGINMASKN, static_cast< int >( QgsCodeEditor::MarginRole::ErrorIndicators ), 1 << MARKER_NUMBER );
109 setMarginWidth( static_cast< int >( QgsCodeEditor::MarginRole::ErrorIndicators ), 0 );
110 setAnnotationDisplay( QsciScintilla::AnnotationBoxed );
111
112 connect( QgsGui::instance(), &QgsGui::optionsChanged, this, [ = ]
113 {
114 setSciWidget();
116 } );
117
118 switch ( mMode )
119 {
121 break;
122
124 {
125 // Don't want to see the horizontal scrollbar at all
126 SendScintilla( QsciScintilla::SCI_SETHSCROLLBAR, 0 );
127
128 setWrapMode( QsciScintilla::WrapCharacter );
129 break;
130 }
131
133 {
134 // Don't want to see the horizontal scrollbar at all
135 SendScintilla( QsciScintilla::SCI_SETHSCROLLBAR, 0 );
136
137 setWrapMode( QsciScintilla::WrapCharacter );
138 SendScintilla( QsciScintilla::SCI_EMPTYUNDOBUFFER );
139 break;
140 }
141 }
142
143#if QSCINTILLA_VERSION < 0x020d03
144 installEventFilter( this );
145#endif
146}
147
148// Workaround a bug in QScintilla 2.8.X
149void QgsCodeEditor::focusOutEvent( QFocusEvent *event )
150{
151#if QSCINTILLA_VERSION >= 0x020800 && QSCINTILLA_VERSION < 0x020900
152 if ( event->reason() != Qt::ActiveWindowFocusReason )
153 {
154 /* There's a bug in all QScintilla 2.8.X, where
155 a focus out event that is not due to ActiveWindowFocusReason doesn't
156 lead to the bliking caret being disabled. The hack consists in making
157 QsciScintilla::focusOutEvent believe that the event is a ActiveWindowFocusReason
158 The bug was fixed in 2.9 per:
159 2015-04-14 Phil Thompson <[email protected]>
160
161 * qt/qsciscintillabase.cpp:
162 Fixed a problem notifying when focus is lost to another application
163 widget.
164 [41734678234e]
165 */
166 QFocusEvent newFocusEvent( QEvent::FocusOut, Qt::ActiveWindowFocusReason );
167 QsciScintilla::focusOutEvent( &newFocusEvent );
168 }
169 else
170#endif
171 {
172 QsciScintilla::focusOutEvent( event );
173 }
174}
175
176// This workaround a likely bug in QScintilla. The ESC key should not be consumned
177// by the main entry, so that the default behavior (Dialog closing) can trigger,
178// but only is the auto-completion suggestion list isn't displayed
179void QgsCodeEditor::keyPressEvent( QKeyEvent *event )
180{
181 if ( isListActive() )
182 {
183 QsciScintilla::keyPressEvent( event );
184 return;
185 }
186
187 if ( event->key() == Qt::Key_Escape )
188 {
189 // Shortcut QScintilla and redirect the event to the QWidget handler
190 QWidget::keyPressEvent( event ); // NOLINT(bugprone-parent-virtual-call) clazy:exclude=skipped-base-method
191 return;
192 }
193
195 {
196 switch ( event->key() )
197 {
198 case Qt::Key_Return:
199 case Qt::Key_Enter:
200 runCommand( text() );
201 updatePrompt();
202 return;
203
204 case Qt::Key_Down:
206 updatePrompt();
207 return;
208
209 case Qt::Key_Up:
211 updatePrompt();
212 return;
213
214 default:
215 break;
216 }
217 }
218
219 const bool ctrlModifier = event->modifiers() & Qt::ControlModifier;
220 const bool altModifier = event->modifiers() & Qt::AltModifier;
221
222 // Ctrl+Alt+F: reformat code
224 if ( !isReadOnly() && canReformat && ctrlModifier && altModifier && event->key() == Qt::Key_F )
225 {
226 event->accept();
227 reformatCode();
228 return;
229 }
230
231 // Toggle comment when user presses Ctrl+:
233 if ( !isReadOnly() && canToggle && ctrlModifier && event->key() == Qt::Key_Colon )
234 {
235 event->accept();
237 return;
238 }
239
240 QsciScintilla::keyPressEvent( event );
241
242}
243
244void QgsCodeEditor::contextMenuEvent( QContextMenuEvent *event )
245{
246 switch ( mMode )
247 {
249 {
250 QMenu *menu = createStandardContextMenu();
251 menu->setAttribute( Qt::WA_DeleteOnClose );
252
255 {
256 menu->addSeparator();
257 }
258
260 {
261 QAction *reformatAction = new QAction( tr( "Reformat Code" ), menu );
262 reformatAction->setShortcut( QStringLiteral( "Ctrl+Alt+F" ) );
263 reformatAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "console/iconFormatCode.svg" ) ) );
264 reformatAction->setEnabled( !isReadOnly() );
265 connect( reformatAction, &QAction::triggered, this, &QgsCodeEditor::reformatCode );
266 menu->addAction( reformatAction );
267 }
268
270 {
271 QAction *syntaxCheckAction = new QAction( tr( "Check Syntax" ), menu );
272 syntaxCheckAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "console/iconSyntaxErrorConsole.svg" ) ) );
273 connect( syntaxCheckAction, &QAction::triggered, this, &QgsCodeEditor::checkSyntax );
274 menu->addAction( syntaxCheckAction );
275 }
276
278 {
279 QAction *toggleCommentAction = new QAction( tr( "Toggle Comment" ), menu );
280 toggleCommentAction->setShortcut( QStringLiteral( "Ctrl+:" ) );
281 toggleCommentAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "console/iconCommentEditorConsole.svg" ) ) );
282 toggleCommentAction->setEnabled( !isReadOnly() );
283 connect( toggleCommentAction, &QAction::triggered, this, &QgsCodeEditor::toggleComment );
284 menu->addAction( toggleCommentAction );
285 }
286
287 populateContextMenu( menu );
288
289 menu->exec( mapToGlobal( event->pos() ) );
290 break;
291 }
292
294 {
295 QMenu *menu = new QMenu( this );
296 QMenu *historySubMenu = new QMenu( tr( "Command History" ), menu );
297
298 historySubMenu->addAction( tr( "Show" ), this, &QgsCodeEditor::showHistory, QStringLiteral( "Ctrl+Shift+SPACE" ) );
299 historySubMenu->addAction( tr( "Clear File" ), this, &QgsCodeEditor::clearPersistentHistory );
300 historySubMenu->addAction( tr( "Clear Session" ), this, &QgsCodeEditor::clearSessionHistory );
301
302 menu->addMenu( historySubMenu );
303 menu->addSeparator();
304
305 QAction *copyAction = menu->addAction( QgsApplication::getThemeIcon( "mActionEditCopy.svg" ), tr( "Copy" ), this, &QgsCodeEditor::copy, QKeySequence::Copy );
306 QAction *pasteAction = menu->addAction( QgsApplication::getThemeIcon( "mActionEditPaste.svg" ), tr( "Paste" ), this, &QgsCodeEditor::paste, QKeySequence::Paste );
307 copyAction->setEnabled( hasSelectedText() );
308 pasteAction->setEnabled( !QApplication::clipboard()->text().isEmpty() );
309
310 populateContextMenu( menu );
311
312 menu->exec( mapToGlobal( event->pos() ) );
313 break;
314 }
315
317 QsciScintilla::contextMenuEvent( event );
318 break;
319 }
320}
321
322bool QgsCodeEditor::eventFilter( QObject *watched, QEvent *event )
323{
324#if QSCINTILLA_VERSION < 0x020d03
325 if ( watched == this && event->type() == QEvent::InputMethod )
326 {
327 // swallow input method events, which cause loss of selected text.
328 // See https://sourceforge.net/p/scintilla/bugs/1913/ , which was ported to QScintilla
329 // in version 2.13.3
330 return true;
331 }
332#endif
333
334 return QsciScintilla::eventFilter( watched, event );
335}
336
338{
339
340}
341
343{
344 if ( mUseDefaultSettings )
345 return color( role );
346
347 if ( !mOverrideColors )
348 {
349 return defaultColor( role, mColorScheme );
350 }
351 else
352 {
353 const QColor color = mCustomColors.value( role );
354 return !color.isValid() ? defaultColor( role ) : color;
355 }
356}
357
359{
360 if ( mUseDefaultSettings )
361 return getMonospaceFont();
362
363 QFont font = QFontDatabase::systemFont( QFontDatabase::FixedFont );
364
365 const QgsSettings settings;
366 if ( !mFontFamily.isEmpty() )
367 QgsFontUtils::setFontFamily( font, mFontFamily );
368
369#ifdef Q_OS_MAC
370 if ( mFontSize > 0 )
371 font.setPointSize( mFontSize );
372 else
373 {
374 // The font size gotten from getMonospaceFont() is too small on Mac
375 font.setPointSize( QLabel().font().pointSize() );
376 }
377#else
378 if ( mFontSize > 0 )
379 font.setPointSize( mFontSize );
380 else
381 {
382 const int fontSize = settings.value( QStringLiteral( "qgis/stylesheet/fontPointSize" ), 10 ).toInt();
383 font.setPointSize( fontSize );
384 }
385#endif
386 font.setBold( false );
387
388 return font;
389}
390
392{
393 updateFolding();
394
397
398 SendScintilla( SCI_MARKERSETFORE, SC_MARKNUM_FOLDEROPEN, lexerColor( QgsCodeEditorColorScheme::ColorRole::FoldIconHalo ) );
399 SendScintilla( SCI_MARKERSETBACK, SC_MARKNUM_FOLDEROPEN, lexerColor( QgsCodeEditorColorScheme::ColorRole::FoldIconForeground ) );
400 SendScintilla( SCI_MARKERSETFORE, SC_MARKNUM_FOLDER, lexerColor( QgsCodeEditorColorScheme::ColorRole::FoldIconHalo ) );
401 SendScintilla( SCI_MARKERSETBACK, SC_MARKNUM_FOLDER, lexerColor( QgsCodeEditorColorScheme::ColorRole::FoldIconForeground ) );
402 SendScintilla( SCI_STYLESETFORE, STYLE_INDENTGUIDE, lexerColor( QgsCodeEditorColorScheme::ColorRole::IndentationGuide ) );
403 SendScintilla( SCI_STYLESETBACK, STYLE_INDENTGUIDE, lexerColor( QgsCodeEditorColorScheme::ColorRole::IndentationGuide ) );
404
406 {
407 setCaretLineVisible( false );
408 setLineNumbersVisible( false ); // NO linenumbers for the input line
409 // Margin 1 is used for the '>' prompt (console input)
410 setMarginLineNumbers( 1, true );
411 setMarginWidth( 1, "00000" );
412 setMarginType( 1, QsciScintilla::MarginType::TextMarginRightJustified );
413 setMarginsBackgroundColor( color( QgsCodeEditorColorScheme::ColorRole::Background ) );
414 setEdgeMode( QsciScintilla::EdgeNone );
415 }
416}
417
418void QgsCodeEditor::setSciWidget()
419{
420 const QFont font = lexerFont();
421 setFont( font );
422
423 setUtf8( true );
424 setCaretLineVisible( true );
425 setCaretLineBackgroundColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::CaretLine ) );
426 setCaretForegroundColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Cursor ) );
429
430 setBraceMatching( QsciScintilla::SloppyBraceMatch );
433
434 setLineNumbersVisible( false );
435
436 // temporarily disable folding, will be enabled later if required by updateFolding()
437 setFolding( QsciScintilla::NoFoldStyle );
438 setMarginWidth( static_cast< int >( QgsCodeEditor::MarginRole::FoldingControls ), 0 );
439
440 setMarginWidth( static_cast< int >( QgsCodeEditor::MarginRole::ErrorIndicators ), 0 );
441
444 setIndentationGuidesForegroundColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::MarginForeground ) );
445 setIndentationGuidesBackgroundColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::MarginBackground ) );
446 // whether margin will be shown
447 updateFolding();
448 const QColor foldColor = lexerColor( QgsCodeEditorColorScheme::ColorRole::Fold );
449 setFoldMarginColors( foldColor, foldColor );
450 // indentation
451 setAutoIndent( true );
452 setIndentationWidth( 4 );
453 setTabIndents( true );
454 setBackspaceUnindents( true );
455 setTabWidth( 4 );
456 // autocomplete
457 setAutoCompletionThreshold( 2 );
458 setAutoCompletionSource( QsciScintilla::AcsAPIs );
459
460 markerDefine( QgsApplication::getThemePixmap( "console/iconSyntaxErrorConsoleParams.svg", lexerColor( QgsCodeEditorColorScheme::ColorRole::Error ),
462}
463
464void QgsCodeEditor::setTitle( const QString &title )
465{
466 setWindowTitle( title );
467}
468
470{
472}
473
475{
477}
478
480{
481 switch ( language )
482 {
484 return tr( "CSS" );
486 return tr( "Expression" );
488 return tr( "HTML" );
490 return tr( "JavaScript" );
492 return tr( "JSON" );
494 return tr( "Python" );
496 return tr( "R" );
498 return tr( "SQL" );
500 return tr( "Batch" );
502 return tr( "Bash" );
504 return QString();
505 }
507}
508
510{
511 mMargin = margin;
512 if ( margin )
513 {
514 QFont marginFont = lexerFont();
515 marginFont.setPointSize( 10 );
516 setMarginLineNumbers( 0, true );
517 setMarginsFont( marginFont );
518 setMarginWidth( static_cast< int >( QgsCodeEditor::MarginRole::LineNumbers ), QStringLiteral( "00000" ) );
521 }
522 else
523 {
524 setMarginWidth( static_cast< int >( QgsCodeEditor::MarginRole::LineNumbers ), 0 );
525 setMarginWidth( static_cast< int >( QgsCodeEditor::MarginRole::ErrorIndicators ), 0 );
526 setMarginWidth( static_cast< int >( QgsCodeEditor::MarginRole::FoldingControls ), 0 );
527 }
528}
529
531{
532 if ( visible )
533 {
534 QFont marginFont = lexerFont();
535 marginFont.setPointSize( 10 );
536 setMarginLineNumbers( static_cast< int >( QgsCodeEditor::MarginRole::LineNumbers ), true );
537 setMarginsFont( marginFont );
538 setMarginWidth( static_cast< int >( QgsCodeEditor::MarginRole::LineNumbers ), QStringLiteral( "00000" ) );
541 }
542 else
543 {
544 setMarginLineNumbers( static_cast< int >( QgsCodeEditor::MarginRole::LineNumbers ), false );
545 setMarginWidth( static_cast< int >( QgsCodeEditor::MarginRole::LineNumbers ), 0 );
546 }
547}
548
550{
551 return marginLineNumbers( static_cast< int >( QgsCodeEditor::MarginRole::LineNumbers ) );
552}
553
555{
556 if ( folding )
557 {
559 }
560 else
561 {
562 mFlags &= ~( static_cast< int >( QgsCodeEditor::Flag::CodeFolding ) );
563 }
564 updateFolding();
565}
566
568{
569 return mFlags & QgsCodeEditor::Flag::CodeFolding;
570}
571
572void QgsCodeEditor::updateFolding()
573{
575 {
576 setMarginWidth( static_cast< int >( QgsCodeEditor::MarginRole::FoldingControls ), "0" );
579 setFolding( QsciScintilla::PlainFoldStyle );
580 }
581 else
582 {
583 setFolding( QsciScintilla::NoFoldStyle );
584 setMarginWidth( static_cast< int >( QgsCodeEditor::MarginRole::FoldingControls ), 0 );
585 }
586}
587
588bool QgsCodeEditor::readHistoryFile()
589{
590 if ( mHistoryFilePath.isEmpty() || !QFile::exists( mHistoryFilePath ) )
591 return false;
592
593 QFile file( mHistoryFilePath );
594 if ( file.open( QIODevice::ReadOnly ) )
595 {
596 QTextStream stream( &file );
597#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
598 // Always use UTF-8
599 stream.setCodec( "UTF-8" );
600#endif
601 QString line;
602 while ( !stream.atEnd() )
603 {
604 line = stream.readLine(); // line of text excluding '\n'
605 mHistory.append( line );
606 }
607 syncSoftHistory();
608 return true;
609 }
610
611 return false;
612}
613
614void QgsCodeEditor::syncSoftHistory()
615{
616 mSoftHistory = mHistory;
617 mSoftHistory.append( QString() );
618 mSoftHistoryIndex = mSoftHistory.length() - 1;
619}
620
622{
623 mSoftHistory[mSoftHistoryIndex] = text();
624}
625
626void QgsCodeEditor::updateHistory( const QStringList &commands, bool skipSoftHistory )
627{
628 if ( commands.size() > 1 )
629 {
630 mHistory.append( commands );
631 }
632 else if ( !commands.value( 0 ).isEmpty() )
633 {
634 const QString command = commands.value( 0 );
635 if ( mHistory.empty() || command != mHistory.constLast() )
636 mHistory.append( command );
637 }
638
639 if ( !skipSoftHistory )
640 syncSoftHistory();
641}
642
644{
645
646}
647
648QString QgsCodeEditor::reformatCodeString( const QString &string )
649{
650 return string;
651}
652
653void QgsCodeEditor::showMessage( const QString &title, const QString &message, Qgis::MessageLevel level )
654{
655 switch ( level )
656 {
657 case Qgis::Info:
658 case Qgis::Success:
659 case Qgis::NoLevel:
660 QMessageBox::information( this, title, message );
661 break;
662
663 case Qgis::Warning:
664 QMessageBox::warning( this, title, message );
665 break;
666
667 case Qgis::Critical:
668 QMessageBox::critical( this, title, message );
669 break;
670 }
671}
672
674{
675 if ( mInterpreter )
676 {
677 const QString prompt = mInterpreter->promptForState( mInterpreter->currentState() );
678 SendScintilla( QsciScintilla::SCI_MARGINSETTEXT, static_cast< uintptr_t >( 0 ), prompt.toUtf8().constData() );
679 }
680}
681
683{
684 return mInterpreter;
685}
686
688{
689 mInterpreter = newInterpreter;
690 updatePrompt();
691}
692
693// Find the source substring index that most closely matches the target string
694int findMinimalDistanceIndex( const QString &source, const QString &target )
695{
696 const int index = std::min( source.length(), target.length() );
697
698 const int d0 = QgsStringUtils::levenshteinDistance( source.left( index ), target );
699 if ( d0 == 0 )
700 return index;
701
702 int refDistanceMore = d0;
703 int refIndexMore = index;
704 if ( index < source.length() - 1 )
705 {
706 while ( true )
707 {
708 const int newDistance = QgsStringUtils::levenshteinDistance( source.left( refIndexMore + 1 ), target );
709 if ( newDistance <= refDistanceMore )
710 {
711 refDistanceMore = newDistance;
712 refIndexMore++;
713 if ( refIndexMore == source.length() - 1 )
714 break;
715 }
716 else
717 {
718 break;
719 }
720 }
721 }
722
723 int refDistanceLess = d0;
724 int refIndexLess = index;
725 if ( index > 0 )
726 {
727 while ( true )
728 {
729 const int newDistance = QgsStringUtils::levenshteinDistance( source.left( refIndexLess - 1 ), target );
730 if ( newDistance <= refDistanceLess )
731 {
732 refDistanceLess = newDistance;
733 refIndexLess--;
734 if ( refIndexLess == 0 )
735 break;
736 }
737 else
738 {
739 break;
740 }
741 }
742 }
743
744 if ( refDistanceMore < refDistanceLess )
745 return refIndexMore;
746 else
747 return refIndexLess;
748}
749
751{
753 return;
754
755 const QString textBeforeCursor = text( 0, linearPosition() );
756 const QString originalText = text();
757 const QString newText = reformatCodeString( originalText );
758
759 if ( originalText == newText )
760 return;
761
762 // try to preserve the cursor position and scroll position
763 const int oldScrollValue = verticalScrollBar()->value();
764 const int linearIndex = findMinimalDistanceIndex( newText, textBeforeCursor );
765
766 beginUndoAction();
767 selectAll();
768 removeSelectedText();
769 insert( newText );
770 setLinearPosition( linearIndex );
771 verticalScrollBar()->setValue( oldScrollValue );
772 endUndoAction();
773}
774
776{
777 return true;
778}
779
781{
782
783}
784
785QStringList QgsCodeEditor::history() const
786{
787 return mHistory;
788}
789
790void QgsCodeEditor::runCommand( const QString &command, bool skipHistory )
791{
792 if ( !skipHistory )
793 {
794 updateHistory( { command } );
797 }
798
799 if ( mInterpreter )
800 mInterpreter->exec( command );
801
802 clear();
804}
805
807{
808 mHistory.clear();
809 readHistoryFile();
810 syncSoftHistory();
811
813}
814
816{
817 mHistory.clear();
818
819 if ( !mHistoryFilePath.isEmpty() && QFile::exists( mHistoryFilePath ) )
820 {
821 QFile file( mHistoryFilePath );
822 file.open( QFile::WriteOnly | QFile::Truncate );
823 }
824
826}
827
829{
830 if ( mHistoryFilePath.isEmpty() )
831 return false;
832
833 QFile f( mHistoryFilePath );
834 if ( !f.open( QFile::WriteOnly | QIODevice::Truncate ) )
835 {
836 return false;
837 }
838
839 QTextStream ts( &f );
840#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
841 ts.setCodec( "UTF-8" );
842#endif
843 for ( const QString &command : std::as_const( mHistory ) )
844 {
845 ts << command + '\n';
846 }
847 return true;
848}
849
851{
852 if ( mSoftHistoryIndex < mSoftHistory.length() - 1 && !mSoftHistory.isEmpty() )
853 {
854 mSoftHistoryIndex += 1;
855 setText( mSoftHistory[mSoftHistoryIndex] );
857 }
858}
859
861{
862 if ( mSoftHistoryIndex > 0 && !mSoftHistory.empty() )
863 {
864 mSoftHistoryIndex -= 1;
865 setText( mSoftHistory[mSoftHistoryIndex] );
867 }
868}
869
871{
872 QgsCodeEditorHistoryDialog *dialog = new QgsCodeEditorHistoryDialog( this, this );
873 dialog->setAttribute( Qt::WA_DeleteOnClose );
874
875 dialog->show();
876 dialog->activateWindow();
877}
878
880{
881 // remove item from the command history (just for the current session)
882 mHistory.removeAt( index );
883 mSoftHistory.removeAt( index );
884 if ( index < mSoftHistoryIndex )
885 {
886 mSoftHistoryIndex -= 1;
887 if ( mSoftHistoryIndex < 0 )
888 mSoftHistoryIndex = mSoftHistory.length() - 1;
889 }
890}
891
892void QgsCodeEditor::insertText( const QString &text )
893{
894 // Insert the text or replace selected text
895 if ( hasSelectedText() )
896 {
897 replaceSelectedText( text );
898 }
899 else
900 {
901 int line, index;
902 getCursorPosition( &line, &index );
903 insertAt( text, line, index );
904 setCursorPosition( line, index + text.length() );
905 }
906}
907
909{
910 if ( theme.isEmpty() && QgsApplication::themeName() == QLatin1String( "default" ) )
911 {
912 // if using default theme, take certain colors from the palette
913 const QPalette pal = qApp->palette();
914
915 switch ( role )
916 {
918 return pal.color( QPalette::Highlight );
920 return pal.color( QPalette::HighlightedText );
921 default:
922 break;
923 }
924 }
925 else if ( theme.isEmpty() )
926 {
927 // non default theme (e.g. Blend of Gray). Take colors from theme ini file...
928 const QSettings ini( QgsApplication::uiThemes().value( QgsApplication::themeName() ) + "/qscintilla.ini", QSettings::IniFormat );
929
930 static const QMap< QgsCodeEditorColorScheme::ColorRole, QString > sColorRoleToIniKey
931 {
932 {QgsCodeEditorColorScheme::ColorRole::Default, QStringLiteral( "python/defaultFontColor" ) },
933 {QgsCodeEditorColorScheme::ColorRole::Keyword, QStringLiteral( "python/keywordFontColor" ) },
934 {QgsCodeEditorColorScheme::ColorRole::Class, QStringLiteral( "python/classFontColor" ) },
935 {QgsCodeEditorColorScheme::ColorRole::Method, QStringLiteral( "python/methodFontColor" ) },
936 {QgsCodeEditorColorScheme::ColorRole::Decoration, QStringLiteral( "python/decoratorFontColor" ) },
937 {QgsCodeEditorColorScheme::ColorRole::Number, QStringLiteral( "python/numberFontColor" ) },
938 {QgsCodeEditorColorScheme::ColorRole::Comment, QStringLiteral( "python/commentFontColor" ) },
939 {QgsCodeEditorColorScheme::ColorRole::CommentLine, QStringLiteral( "sql/commentLineFontColor" ) },
940 {QgsCodeEditorColorScheme::ColorRole::CommentBlock, QStringLiteral( "python/commentBlockFontColor" ) },
941 {QgsCodeEditorColorScheme::ColorRole::Background, QStringLiteral( "python/paperBackgroundColor" ) },
942 {QgsCodeEditorColorScheme::ColorRole::Cursor, QStringLiteral( "cursorColor" ) },
943 {QgsCodeEditorColorScheme::ColorRole::CaretLine, QStringLiteral( "caretLineColor" ) },
944 {QgsCodeEditorColorScheme::ColorRole::Operator, QStringLiteral( "sql/operatorFontColor" ) },
945 {QgsCodeEditorColorScheme::ColorRole::QuotedOperator, QStringLiteral( "sql/QuotedOperatorFontColor" ) },
946 {QgsCodeEditorColorScheme::ColorRole::Identifier, QStringLiteral( "sql/identifierFontColor" ) },
947 {QgsCodeEditorColorScheme::ColorRole::QuotedIdentifier, QStringLiteral( "sql/QuotedIdentifierFontColor" ) },
948 {QgsCodeEditorColorScheme::ColorRole::Tag, QStringLiteral( "html/tagFontColor" ) },
949 {QgsCodeEditorColorScheme::ColorRole::UnknownTag, QStringLiteral( "html/unknownTagFontColor" ) },
950 {QgsCodeEditorColorScheme::ColorRole::SingleQuote, QStringLiteral( "sql/singleQuoteFontColor" ) },
951 {QgsCodeEditorColorScheme::ColorRole::DoubleQuote, QStringLiteral( "sql/doubleQuoteFontColor" ) },
952 {QgsCodeEditorColorScheme::ColorRole::TripleSingleQuote, QStringLiteral( "python/tripleSingleQuoteFontColor" ) },
953 {QgsCodeEditorColorScheme::ColorRole::TripleDoubleQuote, QStringLiteral( "python/tripleDoubleQuoteFontColor" ) },
954 {QgsCodeEditorColorScheme::ColorRole::MarginBackground, QStringLiteral( "marginBackgroundColor" ) },
955 {QgsCodeEditorColorScheme::ColorRole::MarginForeground, QStringLiteral( "marginForegroundColor" ) },
956 {QgsCodeEditorColorScheme::ColorRole::SelectionBackground, QStringLiteral( "selectionBackgroundColor" ) },
957 {QgsCodeEditorColorScheme::ColorRole::SelectionForeground, QStringLiteral( "selectionForegroundColor" ) },
958 {QgsCodeEditorColorScheme::ColorRole::MatchedBraceBackground, QStringLiteral( "matchedBraceBackground" ) },
959 {QgsCodeEditorColorScheme::ColorRole::MatchedBraceForeground, QStringLiteral( "matchedBraceColor" ) },
960 {QgsCodeEditorColorScheme::ColorRole::Edge, QStringLiteral( "edgeColor" ) },
961 {QgsCodeEditorColorScheme::ColorRole::Fold, QStringLiteral( "foldColor" ) },
962 {QgsCodeEditorColorScheme::ColorRole::Error, QStringLiteral( "stderrFontColor" ) },
963 {QgsCodeEditorColorScheme::ColorRole::ErrorBackground, QStringLiteral( "stderrBackground" ) },
964 {QgsCodeEditorColorScheme::ColorRole::FoldIconForeground, QStringLiteral( "foldIconForeground" ) },
965 {QgsCodeEditorColorScheme::ColorRole::FoldIconHalo, QStringLiteral( "foldIconHalo" ) },
966 {QgsCodeEditorColorScheme::ColorRole::IndentationGuide, QStringLiteral( "indentationGuide" ) },
967 };
968
969 const QgsCodeEditorColorScheme defaultScheme = QgsGui::codeEditorColorSchemeRegistry()->scheme( QStringLiteral( "default" ) );
970 return QgsSymbolLayerUtils::decodeColor( ini.value( sColorRoleToIniKey.value( role ), defaultScheme.color( role ).name() ).toString() );
971 }
972
973 const QgsCodeEditorColorScheme scheme = QgsGui::codeEditorColorSchemeRegistry()->scheme( theme.isEmpty() ? QStringLiteral( "default" ) : theme );
974 return scheme.color( role );
975}
976
978{
979 const QgsSettings settings;
980 if ( !settings.value( QStringLiteral( "codeEditor/overrideColors" ), false, QgsSettings::Gui ).toBool() )
981 {
982 const QString theme = settings.value( QStringLiteral( "codeEditor/colorScheme" ), QString(), QgsSettings::Gui ).toString();
983 return defaultColor( role, theme );
984 }
985 else
986 {
987 const QString color = settings.value( QStringLiteral( "codeEditor/%1" ).arg( sColorRoleToSettingsKey.value( role ) ), QString(), QgsSettings::Gui ).toString();
988 return color.isEmpty() ? defaultColor( role ) : QgsSymbolLayerUtils::decodeColor( color );
989 }
990}
991
993{
994 QgsSettings settings;
995 if ( color.isValid() )
996 {
997 settings.setValue( QStringLiteral( "codeEditor/%1" ).arg( sColorRoleToSettingsKey.value( role ) ), color.name(), QgsSettings::Gui );
998 }
999 else
1000 {
1001 settings.remove( QStringLiteral( "codeEditor/%1" ).arg( sColorRoleToSettingsKey.value( role ) ), QgsSettings::Gui );
1002 }
1003}
1004
1005// Settings for font and fontsize
1006bool QgsCodeEditor::isFixedPitch( const QFont &font )
1007{
1008 return font.fixedPitch();
1009}
1010
1012{
1013 QFont font = QFontDatabase::systemFont( QFontDatabase::FixedFont );
1014
1015 const QgsSettings settings;
1016 if ( !settings.value( QStringLiteral( "codeEditor/fontfamily" ), QString(), QgsSettings::Gui ).toString().isEmpty() )
1017 QgsFontUtils::setFontFamily( font, settings.value( QStringLiteral( "codeEditor/fontfamily" ), QString(), QgsSettings::Gui ).toString() );
1018
1019 const int fontSize = settings.value( QStringLiteral( "codeEditor/fontsize" ), 0, QgsSettings::Gui ).toInt();
1020
1021#ifdef Q_OS_MAC
1022 if ( fontSize > 0 )
1023 font.setPointSize( fontSize );
1024 else
1025 {
1026 // The font size gotten from getMonospaceFont() is too small on Mac
1027 font.setPointSize( QLabel().font().pointSize() );
1028 }
1029#else
1030 if ( fontSize > 0 )
1031 font.setPointSize( fontSize );
1032 else
1033 {
1034 const int fontSize = settings.value( QStringLiteral( "qgis/stylesheet/fontPointSize" ), 10 ).toInt();
1035 font.setPointSize( fontSize );
1036 }
1037#endif
1038 font.setBold( false );
1039
1040 return font;
1041}
1042
1043void QgsCodeEditor::setCustomAppearance( const QString &scheme, const QMap<QgsCodeEditorColorScheme::ColorRole, QColor> &customColors, const QString &fontFamily, int fontSize )
1044{
1045 mUseDefaultSettings = false;
1046 mOverrideColors = !customColors.isEmpty();
1047 mColorScheme = scheme;
1048 mCustomColors = customColors;
1049 mFontFamily = fontFamily;
1050 mFontSize = fontSize;
1051
1052 setSciWidget();
1054}
1055
1056void QgsCodeEditor::addWarning( const int lineNumber, const QString &warning )
1057{
1058 setMarginWidth( static_cast< int >( QgsCodeEditor::MarginRole::ErrorIndicators ), "000" );
1059 markerAdd( lineNumber, MARKER_NUMBER );
1060 QFont font = lexerFont();
1061 font.setItalic( true );
1062 const QsciStyle styleAnn = QsciStyle( -1, QStringLiteral( "Annotation" ),
1065 font,
1066 true );
1067 annotate( lineNumber, warning, styleAnn );
1068 mWarningLines.push_back( lineNumber );
1069}
1070
1072{
1073 for ( const int line : mWarningLines )
1074 {
1075 markerDelete( line );
1076 clearAnnotations( line );
1077 }
1078 setMarginWidth( static_cast< int >( QgsCodeEditor::MarginRole::ErrorIndicators ), 0 );
1079 mWarningLines.clear();
1080}
1081
1083{
1084 int line = 0;
1085 int index = 0;
1086 getCursorPosition( &line, &index );
1087 return line == lines() - 1;
1088}
1089
1090void QgsCodeEditor::setHistoryFilePath( const QString &path )
1091{
1092 mHistoryFilePath = path;
1093 readHistoryFile();
1094}
1095
1097{
1098 setCursorPosition( 0, 0 );
1099 ensureCursorVisible();
1100 ensureLineVisible( 0 );
1101
1102 if ( mMode == QgsCodeEditor::Mode::CommandInput )
1103 updatePrompt();
1104}
1105
1107{
1108 const int endLine = lines() - 1;
1109 const int endLineLength = lineLength( endLine );
1110 setCursorPosition( endLine, endLineLength );
1111 ensureCursorVisible();
1112 ensureLineVisible( endLine );
1113
1114 if ( mMode == QgsCodeEditor::Mode::CommandInput )
1115 updatePrompt();
1116}
1117
1119{
1120 int line, index;
1121 getCursorPosition( &line, &index );
1122 return positionFromLineIndex( line, index );
1123}
1124
1126{
1127 int line, index;
1128 lineIndexFromPosition( linearIndex, &line, &index );
1129 setCursorPosition( line, index );
1130}
1131
1133{
1134 int startLine, startIndex, _;
1135 getSelection( &startLine, &startIndex, &_, &_ );
1136 if ( startLine == -1 )
1137 {
1138 return linearPosition();
1139 }
1140 return positionFromLineIndex( startLine, startIndex );
1141}
1142
1144{
1145 int endLine, endIndex, _;
1146 getSelection( &_, &_, &endLine, &endIndex );
1147 if ( endLine == -1 )
1148 {
1149 return linearPosition();
1150 }
1151 return positionFromLineIndex( endLine, endIndex );
1152}
1153
1154void QgsCodeEditor::setLinearSelection( int start, int end )
1155{
1156 int startLine, startIndex, endLine, endIndex;
1157 lineIndexFromPosition( start, &startLine, &startIndex );
1158 lineIndexFromPosition( end, &endLine, &endIndex );
1159 setSelection( startLine, startIndex, endLine, endIndex );
1160}
1161
1163
1164int QgsCodeInterpreter::exec( const QString &command )
1165{
1166 mState = execCommandImpl( command );
1167 return mState;
1168}
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition: qgis.h:99
@ NoLevel
No level.
Definition: qgis.h:104
@ Warning
Warning message.
Definition: qgis.h:101
@ Critical
Critical/error message.
Definition: qgis.h:102
@ Info
Information message.
Definition: qgis.h:100
@ Success
Used for reporting a successful operation.
Definition: qgis.h:103
@ CheckSyntax
Language supports syntax checking.
@ Reformat
Language supports automatic code reformatting.
@ ToggleComment
Language supports comment toggling.
ScriptLanguage
Scripting languages.
Definition: qgis.h:3718
@ QgisExpression
QGIS expressions.
@ Batch
Windows batch files.
@ JavaScript
JavaScript.
@ Bash
Bash scripts.
@ Unknown
Unknown/other language.
QFlags< ScriptLanguageCapability > ScriptLanguageCapabilities
Script language capabilities.
Definition: qgis.h:3753
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.
@ 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.
@ IndentationGuide
Indentation guide line.
@ SingleQuote
Single quote color.
@ MarginBackground
Margin background color.
@ SelectionBackground
Selection background color.
@ MatchedBraceForeground
Matched brace foreground 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.
bool eventFilter(QObject *watched, QEvent *event) override
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...
Mode
Code editor modes.
@ 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 reformatCode()
Applies code reformatting to the editor.
virtual void toggleComment()
Toggle comment for the selected text.
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.
void setLinearSelection(int start, int end)
Convenience function to set the selection using linear indexes.
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...
QFlags< Flag > Flags
Flags controlling behavior of code editor.
void persistentHistoryCleared()
Emitted when the persistent history of commands run in the editor is cleared.
void runCommand(const QString &command, bool skipHistory=false)
Runs a command in the editor.
void setFoldingVisible(bool folding)
Set whether the folding controls are visible in the editor.
virtual Qgis::ScriptLanguageCapabilities languageCapabilities() const
Returns the associated scripting language capabilities.
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 showMessage(const QString &title, const QString &message, Qgis::MessageLevel level)
Shows a user facing message (eg a warning message).
int selectionEnd() const
Convenience function to return the end of the selection as a linear index Contrary to the getSelectio...
virtual void initializeLexer()
Called when the dialect specific code lexer needs to be initialized (or reinitialized).
int linearPosition() const
Convenience function to return the cursor position as a linear index.
void setTitle(const QString &title)
Set the widget title.
void setLinearPosition(int position)
Convenience function to set the cursor position as a linear index.
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)
Construct a new 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.
@ ImmediatelyUpdateHistory
Indicates that the history file should be immediately updated whenever a command is executed,...
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.
virtual Qgis::ScriptLanguage language() const
Returns the associated scripting language.
QFont lexerFont() const
Returns the font to use in the lexer.
virtual QString reformatCodeString(const QString &string)
Applies code reformatting to a string and returns the result.
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.
int selectionStart() const
Convenience function to return the start of the selection as a linear index Contrary to the getSelect...
void addWarning(int lineNumber, const QString &warning)
Adds a warning message and indicator to the specified a lineNumber.
virtual bool checkSyntax()
Applies syntax checking to the editor.
static QColor color(QgsCodeEditorColorScheme::ColorRole role)
Returns the color to use in the editor for the specified role.
An interface for code interpreters.
Definition: qgscodeeditor.h:41
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.
Definition: qgscodeeditor.h:59
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()
static void setFontFamily(QFont &font, const QString &family)
Sets the family for a font object.
void optionsChanged()
This signal is emitted whenever the application options have been changed.
static QgsGui * instance()
Returns a pointer to the singleton instance.
Definition: qgsgui.cpp:73
static QgsCodeEditorColorSchemeRegistry * codeEditorColorSchemeRegistry()
Returns the global code editor color scheme registry, used for registering the color schemes for QgsC...
Definition: qgsgui.cpp:154
This class is a composition of two QSettings instances:
Definition: qgssettings.h:64
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 int levenshteinDistance(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the Levenshtein edit distance between two strings.
static QColor decodeColor(const QString &str)
#define BUILTIN_UNREACHABLE
Definition: qgis.h:5853
int findMinimalDistanceIndex(const QString &source, const QString &target)