QGIS API Documentation  3.2.0-Bonn (bc43194)
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 "qgscodeeditor.h"
18 #include "qgssettings.h"
19 
20 #include <QWidget>
21 #include <QFont>
22 #include <QDebug>
23 #include <QFocusEvent>
24 
25 QgsCodeEditor::QgsCodeEditor( QWidget *parent, const QString &title, bool folding, bool margin )
26  : QsciScintilla( parent )
27  , mWidgetTitle( title )
28  , mFolding( folding )
29  , mMargin( margin )
30 {
31  if ( !parent && mWidgetTitle.isEmpty() )
32  {
33  setWindowTitle( QStringLiteral( "Text Editor" ) );
34  }
35  else
36  {
37  setWindowTitle( mWidgetTitle );
38  }
39  setSciWidget();
40  setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
41 }
42 
43 // Workaround a bug in QScintilla 2.8.X
44 void QgsCodeEditor::focusOutEvent( QFocusEvent *event )
45 {
46 #if QSCINTILLA_VERSION >= 0x020800 && QSCINTILLA_VERSION < 0x020900
47  if ( event->reason() != Qt::ActiveWindowFocusReason )
48  {
49  /* There's a bug in all QScintilla 2.8.X, where
50  a focus out event that is not due to ActiveWindowFocusReason doesn't
51  lead to the bliking caret being disabled. The hack consists in making
52  QsciScintilla::focusOutEvent believe that the event is a ActiveWindowFocusReason
53  The bug was fixed in 2.9 per:
54  2015-04-14 Phil Thompson <[email protected]>
55 
56  * qt/qsciscintillabase.cpp:
57  Fixed a problem notifying when focus is lost to another application
58  widget.
59  [41734678234e]
60  */
61  QFocusEvent newFocusEvent( QEvent::FocusOut, Qt::ActiveWindowFocusReason );
62  QsciScintilla::focusOutEvent( &newFocusEvent );
63  }
64  else
65 #endif
66  {
67  QsciScintilla::focusOutEvent( event );
68  }
69 }
70 
71 // This workaround a likely bug in QScintilla. The ESC key should not be consumned
72 // by the main entry, so that the default behavior (Dialog closing) can trigger,
73 // but only is the auto-completion suggestion list isn't displayed
74 void QgsCodeEditor::keyPressEvent( QKeyEvent *event )
75 {
76  if ( event->key() == Qt::Key_Escape && !isListActive() )
77  {
78  // Shortcut QScintilla and redirect the event to the QWidget handler
79  QWidget::keyPressEvent( event ); // clazy:exclude=skipped-base-method
80  }
81  else
82  {
83  QsciScintilla::keyPressEvent( event );
84  }
85 }
86 
87 void QgsCodeEditor::setSciWidget()
88 {
89  setUtf8( true );
90  setCaretLineVisible( true );
91  setCaretLineBackgroundColor( QColor( 252, 243, 237 ) );
92 
93  setBraceMatching( QsciScintilla::SloppyBraceMatch );
94  setMatchedBraceBackgroundColor( QColor( 183, 249, 7 ) );
95  // whether margin will be shown
96  setMarginVisible( mMargin );
97  // whether margin will be shown
98  setFoldingVisible( mFolding );
99  // indentation
100  setAutoIndent( true );
101  setIndentationWidth( 4 );
102  setTabIndents( true );
103  setBackspaceUnindents( true );
104  setTabWidth( 4 );
105  // autocomplete
106  setAutoCompletionThreshold( 2 );
107  setAutoCompletionSource( QsciScintilla::AcsAPIs );
108 }
109 
110 void QgsCodeEditor::setTitle( const QString &title )
111 {
112  setWindowTitle( title );
113 }
114 
116 {
117  mMargin = margin;
118  if ( margin )
119  {
120  QFont marginFont( QStringLiteral( "Courier" ), 10 );
121  setMarginLineNumbers( 1, true );
122  setMarginsFont( marginFont );
123  setMarginWidth( 1, QStringLiteral( "00000" ) );
124  setMarginsForegroundColor( QColor( 62, 62, 227 ) );
125  setMarginsBackgroundColor( QColor( 249, 249, 249 ) );
126  }
127  else
128  {
129  setMarginWidth( 0, 0 );
130  setMarginWidth( 1, 0 );
131  setMarginWidth( 2, 0 );
132  }
133 }
134 
136 {
137  mFolding = folding;
138  if ( folding )
139  {
140  setFolding( QsciScintilla::PlainFoldStyle );
141  setFoldMarginColors( QColor( 244, 244, 244 ), QColor( 244, 244, 244 ) );
142  }
143  else
144  {
145  setFolding( QsciScintilla::NoFoldStyle );
146  }
147 }
148 
149 void QgsCodeEditor::insertText( const QString &text )
150 {
151  // Insert the text or replace selected text
152  if ( hasSelectedText() )
153  {
154  replaceSelectedText( text );
155  }
156  else
157  {
158  int line, index;
159  getCursorPosition( &line, &index );
160  insertAt( text, line, index );
161  setCursorPosition( line, index + text.length() );
162  }
163 }
164 
165 // Settings for font and fontsize
166 bool QgsCodeEditor::isFixedPitch( const QFont &font )
167 {
168  return font.fixedPitch();
169 }
170 
172 {
173  QgsSettings settings;
174  QString loadFont = settings.value( QStringLiteral( "pythonConsole/fontfamilytextEditor" ), "Monospace" ).toString();
175  int fontSize = settings.value( QStringLiteral( "pythonConsole/fontsizeEditor" ), 10 ).toInt();
176 
177  QFont font( loadFont );
178  font.setFixedPitch( true );
179  font.setPointSize( fontSize );
180  font.setStyleHint( QFont::TypeWriter );
181  font.setStretch( QFont::SemiCondensed );
182  font.setLetterSpacing( QFont::PercentageSpacing, 87.0 );
183  font.setBold( false );
184  return font;
185 }
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
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