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