QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 
19 #include <QSettings>
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( "Text Editor" );
34  setMinimumSize( 800, 300 );
35  }
36  else
37  {
38  setWindowTitle( mWidgetTitle );
39  }
40  setSciWidget();
41  setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
42 }
43 
45 {
46 }
47 
48 // Workaround a bug in QScintilla 2.8.X
50 {
51 #if QSCINTILLA_VERSION >= 0x020800 && QSCINTILLA_VERSION < 0x020900
52  if ( event->reason() != Qt::ActiveWindowFocusReason )
53  {
54  /* There's a bug in all QScintilla 2.8.X, where
55  a focus out event that is not due to ActiveWindowFocusReason doesn't
56  lead to the bliking caret being disabled. The hack consists in making
57  QsciScintilla::focusOutEvent believe that the event is a ActiveWindowFocusReason
58  The bug was fixed in 2.9 per:
59  2015-04-14 Phil Thompson <[email protected]>
60 
61  * qt/qsciscintillabase.cpp:
62  Fixed a problem notifying when focus is lost to another application
63  widget.
64  [41734678234e]
65  */
66  QFocusEvent newFocusEvent( QEvent::FocusOut, Qt::ActiveWindowFocusReason );
67  QsciScintilla::focusOutEvent( &newFocusEvent );
68  }
69  else
70 #endif
71  {
72  QsciScintilla::focusOutEvent( event );
73  }
74 }
75 
76 // This workaround a likely bug in QScintilla. The ESC key should not be consumned
77 // by the main entry, so that the default behaviour (Dialog closing) can trigger,
78 // but only is the auto-completion suggestion list isn't displayed
80 {
81  if ( event->key() == Qt::Key_Escape && !isListActive() )
82  {
83  // Shortcut QScintilla and redirect the event to the QWidget handler
84  QWidget::keyPressEvent( event );
85  }
86  else
87  {
88  QsciScintilla::keyPressEvent( event );
89  }
90 }
91 
92 void QgsCodeEditor::setSciWidget()
93 {
94  setUtf8( true );
95  setCaretLineVisible( true );
96  setCaretLineBackgroundColor( QColor( "#fcf3ed" ) );
97 
98  setBraceMatching( QsciScintilla::SloppyBraceMatch );
99  setMatchedBraceBackgroundColor( QColor( "#b7f907" ) );
100  // whether margin will be shown
101  setMarginVisible( mMargin );
102  // whether margin will be shown
103  setFoldingVisible( mFolding );
104  // indentation
105  setAutoIndent( true );
106  setIndentationWidth( 4 );
107  setTabIndents( true );
108  setBackspaceUnindents( true );
109  setTabWidth( 4 );
110  // autocomplete
111  setAutoCompletionThreshold( 2 );
112  setAutoCompletionSource( QsciScintilla::AcsAPIs );
113 }
114 
115 void QgsCodeEditor::setTitle( const QString& title )
116 {
117  setWindowTitle( title );
118 }
119 
121 {
122  mMargin = margin;
123  if ( margin )
124  {
125  QFont marginFont( "Courier", 10 );
126  setMarginLineNumbers( 1, true );
127  setMarginsFont( marginFont );
128  setMarginWidth( 1, "00000" );
129  setMarginsForegroundColor( QColor( "#3E3EE3" ) );
130  setMarginsBackgroundColor( QColor( "#f9f9f9" ) );
131  }
132  else
133  {
134  setMarginWidth( 0, 0 );
135  setMarginWidth( 1, 0 );
136  setMarginWidth( 2, 0 );
137  }
138 }
139 
141 {
142  mFolding = folding;
143  if ( folding )
144  {
145  setFolding( QsciScintilla::PlainFoldStyle );
146  setFoldMarginColors( QColor( "#f4f4f4" ), QColor( "#f4f4f4" ) );
147  }
148  else
149  {
150  setFolding( QsciScintilla::NoFoldStyle );
151  }
152 }
153 
154 void QgsCodeEditor::insertText( const QString& theText )
155 {
156  // Insert the text or replace selected text
157  if ( hasSelectedText() )
158  {
159  replaceSelectedText( theText );
160  }
161  else
162  {
163  int line, index;
164  getCursorPosition( &line, &index );
165  insertAt( theText, line, index );
166  setCursorPosition( line, index + theText.length() );
167  }
168 }
169 
170 // Settings for font and fontsize
172 {
173  return font.fixedPitch();
174 }
175 
177 {
178  QSettings settings;
179  QString loadFont = settings.value( "pythonConsole/fontfamilytextEditor", "Monospace" ).toString();
180  int fontSize = settings.value( "pythonConsole/fontsizeEditor", 10 ).toInt();
181 
182  QFont font( loadFont );
183  font.setFixedPitch( true );
184  font.setPointSize( fontSize );
185  font.setStyleHint( QFont::TypeWriter );
186  font.setStretch( QFont::SemiCondensed );
187  font.setLetterSpacing( QFont::PercentageSpacing, 87.0 );
188  font.setBold( false );
189  return font;
190 }
static unsigned index
void setPointSize(int pointSize)
void setFoldingVisible(bool folding)
Set folding visible state.
QFont getMonospaceFont()
void keyPressEvent(QKeyEvent *event) override
bool fixedPitch() const
void setBold(bool enable)
Qt::FocusReason reason() const
QgsCodeEditor(QWidget *parent=nullptr, const QString &title="", bool folding=false, bool margin=false)
Construct a new code editor.
int toInt(bool *ok) const
bool isEmpty() const
int key() const
void setStyleHint(StyleHint hint, StyleStrategy strategy)
void setMarginVisible(bool margin)
Set margin visible state.
QVariant value(const QString &key, const QVariant &defaultValue) const
virtual void keyPressEvent(QKeyEvent *event)
int length() const
void setTitle(const QString &title)
Set the widget title.
bool isFixedPitch(const QFont &font)
void setLetterSpacing(SpacingType type, qreal spacing)
QString toString() const
void focusOutEvent(QFocusEvent *event) override
void setFixedPitch(bool enable)
void insertText(const QString &theText)
Insert text at cursor position, or replace any selected text if user has made a selection.
void setStretch(int factor)