QGIS API Documentation  3.13.0-Master (740be229cb)
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 
22 #include <QWidget>
23 #include <QFont>
24 #include <QDebug>
25 #include <QFocusEvent>
26 
27 QgsCodeEditor::QgsCodeEditor( QWidget *parent, const QString &title, bool folding, bool margin )
28  : QsciScintilla( parent )
29  , mWidgetTitle( title )
30  , mFolding( folding )
31  , mMargin( margin )
32 {
33  if ( !parent && mWidgetTitle.isEmpty() )
34  {
35  setWindowTitle( QStringLiteral( "Text Editor" ) );
36  }
37  else
38  {
39  setWindowTitle( mWidgetTitle );
40  }
41  setSciWidget();
42  setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
43 
44  SendScintilla( SCI_SETADDITIONALSELECTIONTYPING, 1 );
45  SendScintilla( SCI_SETMULTIPASTE, 1 );
46  SendScintilla( SCI_SETVIRTUALSPACEOPTIONS, SCVS_RECTANGULARSELECTION );
47 }
48 
49 // Workaround a bug in QScintilla 2.8.X
50 void QgsCodeEditor::focusOutEvent( QFocusEvent *event )
51 {
52 #if QSCINTILLA_VERSION >= 0x020800 && QSCINTILLA_VERSION < 0x020900
53  if ( event->reason() != Qt::ActiveWindowFocusReason )
54  {
55  /* There's a bug in all QScintilla 2.8.X, where
56  a focus out event that is not due to ActiveWindowFocusReason doesn't
57  lead to the bliking caret being disabled. The hack consists in making
58  QsciScintilla::focusOutEvent believe that the event is a ActiveWindowFocusReason
59  The bug was fixed in 2.9 per:
60  2015-04-14 Phil Thompson <[email protected]>
61 
62  * qt/qsciscintillabase.cpp:
63  Fixed a problem notifying when focus is lost to another application
64  widget.
65  [41734678234e]
66  */
67  QFocusEvent newFocusEvent( QEvent::FocusOut, Qt::ActiveWindowFocusReason );
68  QsciScintilla::focusOutEvent( &newFocusEvent );
69  }
70  else
71 #endif
72  {
73  QsciScintilla::focusOutEvent( event );
74  }
75 }
76 
77 // This workaround a likely bug in QScintilla. The ESC key should not be consumned
78 // by the main entry, so that the default behavior (Dialog closing) can trigger,
79 // but only is the auto-completion suggestion list isn't displayed
80 void QgsCodeEditor::keyPressEvent( QKeyEvent *event )
81 {
82  if ( event->key() == Qt::Key_Escape && !isListActive() )
83  {
84  // Shortcut QScintilla and redirect the event to the QWidget handler
85  QWidget::keyPressEvent( event ); // clazy:exclude=skipped-base-method
86  }
87  else
88  {
89  QsciScintilla::keyPressEvent( event );
90  }
91 }
92 
93 void QgsCodeEditor::setSciWidget()
94 {
95  QHash< QString, QColor > colors;
96  if ( QgsApplication::instance()->themeName() != QStringLiteral( "default" ) )
97  {
98  QSettings ini( QgsApplication::instance()->uiThemes().value( QgsApplication::instance()->themeName() ) + "/qscintilla.ini", QSettings::IniFormat );
99  for ( const auto &key : ini.allKeys() )
100  {
101  colors.insert( key, QgsSymbolLayerUtils::decodeColor( ini.value( key ).toString() ) );
102  }
103  }
104  QPalette pal = qApp->palette();
105 
106  setUtf8( true );
107  setCaretLineVisible( true );
108  setCaretLineBackgroundColor( colors.value( QStringLiteral( "caretLineColor" ), QColor( 252, 243, 237 ) ) );
109  setCaretForegroundColor( colors.value( QStringLiteral( "cursorColor" ), QColor( 51, 51, 51 ) ) );
110  setSelectionForegroundColor( colors.value( QStringLiteral( "selectionForegroundColor" ), pal.color( QPalette::HighlightedText ) ) );
111  setSelectionBackgroundColor( colors.value( QStringLiteral( "selectionBackgroundColor" ), pal.color( QPalette::Highlight ) ) );
112 
113  setBraceMatching( QsciScintilla::SloppyBraceMatch );
114  setMatchedBraceBackgroundColor( colors.value( QStringLiteral( "matchedBraceColor" ), QColor( 183, 249, 7 ) ) );
115  // whether margin will be shown
116  setMarginVisible( mMargin );
117  setMarginsForegroundColor( colors.value( QStringLiteral( "marginForegroundColor" ), QColor( 62, 62, 227 ) ) );
118  setMarginsBackgroundColor( colors.value( QStringLiteral( "marginBackgroundColor" ), QColor( 249, 249, 249 ) ) );
119  setIndentationGuidesForegroundColor( colors.value( QStringLiteral( "marginForegroundColor" ), QColor( 62, 62, 227 ) ) );
120  setIndentationGuidesBackgroundColor( colors.value( QStringLiteral( "marginBackgroundColor" ), QColor( 249, 249, 249 ) ) );
121  // whether margin will be shown
122  setFoldingVisible( mFolding );
123  QColor foldColor = colors.value( QStringLiteral( "foldColor" ), QColor( 244, 244, 244 ) );
124  setFoldMarginColors( foldColor, foldColor );
125  // indentation
126  setAutoIndent( true );
127  setIndentationWidth( 4 );
128  setTabIndents( true );
129  setBackspaceUnindents( true );
130  setTabWidth( 4 );
131  // autocomplete
132  setAutoCompletionThreshold( 2 );
133  setAutoCompletionSource( QsciScintilla::AcsAPIs );
134 }
135 
136 void QgsCodeEditor::setTitle( const QString &title )
137 {
138  setWindowTitle( title );
139 }
140 
142 {
143  mMargin = margin;
144  if ( margin )
145  {
146  QFont marginFont( QStringLiteral( "Courier" ), 10 );
147  setMarginLineNumbers( 1, true );
148  setMarginsFont( marginFont );
149  setMarginWidth( 1, QStringLiteral( "00000" ) );
150  }
151  else
152  {
153  setMarginWidth( 0, 0 );
154  setMarginWidth( 1, 0 );
155  setMarginWidth( 2, 0 );
156  }
157 }
158 
160 {
161  mFolding = folding;
162  if ( folding )
163  {
164  setFolding( QsciScintilla::PlainFoldStyle );
165  }
166  else
167  {
168  setFolding( QsciScintilla::NoFoldStyle );
169  }
170 }
171 
172 void QgsCodeEditor::insertText( const QString &text )
173 {
174  // Insert the text or replace selected text
175  if ( hasSelectedText() )
176  {
177  replaceSelectedText( text );
178  }
179  else
180  {
181  int line, index;
182  getCursorPosition( &line, &index );
183  insertAt( text, line, index );
184  setCursorPosition( line, index + text.length() );
185  }
186 }
187 
188 // Settings for font and fontsize
189 bool QgsCodeEditor::isFixedPitch( const QFont &font )
190 {
191  return font.fixedPitch();
192 }
193 
195 {
196  QgsSettings settings;
197  QString loadFont = settings.value( QStringLiteral( "pythonConsole/fontfamilytextEditor" ), "Monospace" ).toString();
198  int fontSize = settings.value( QStringLiteral( "pythonConsole/fontsizeEditor" ), 10 ).toInt();
199 
200  QFont font( loadFont );
201  font.setFixedPitch( true );
202  font.setPointSize( fontSize );
203  font.setStyleHint( QFont::TypeWriter );
204  font.setBold( false );
205  return font;
206 }
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:61
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setFoldingVisible(bool folding)
Set folding visible state.
QFont getMonospaceFont()
void keyPressEvent(QKeyEvent *event) override
void insertText(const QString &text)
Insert text at cursor position, or replace any selected text if user has made a selection.
QgsCodeEditor(QWidget *parent=nullptr, const QString &title=QString(), bool folding=false, bool margin=false)
Construct a new code editor.
void setMarginVisible(bool margin)
Set margin visible state.
void setTitle(const QString &title)
Set the widget title.
bool isFixedPitch(const QFont &font)
void focusOutEvent(QFocusEvent *event) override
static QColor decodeColor(const QString &str)