Add editingTimeout for QgsCodeEditor

This commit is contained in:
Yoann Quenach de Quivillic 2024-12-26 02:58:18 +01:00 committed by Loïc Bartoletti
parent 86bd2c5353
commit b9d4575715
16 changed files with 156 additions and 15 deletions

View File

@ -57,7 +57,7 @@ QgsCodeEditor.Flags = lambda flags=0: QgsCodeEditor.Flag(flags)
QgsCodeEditor.Flags.baseClass = QgsCodeEditor
Flags = QgsCodeEditor # dirty hack since SIP seems to introduce the flags in module
try:
QgsCodeEditor.__attribute_docs__ = {'SEARCH_RESULT_INDICATOR': 'Indicator index for search results', 'sessionHistoryCleared': 'Emitted when the history of commands run in the current session is cleared.\n\n.. versionadded:: 3.30\n', 'persistentHistoryCleared': 'Emitted when the persistent history of commands run in the editor is cleared.\n\n.. versionadded:: 3.30\n', 'helpRequested': 'Emitted when documentation was requested for the specified ``word``.\n\n.. versionadded:: 3.42\n'}
QgsCodeEditor.__attribute_docs__ = {'SEARCH_RESULT_INDICATOR': 'Indicator index for search results', 'sessionHistoryCleared': 'Emitted when the history of commands run in the current session is cleared.\n\n.. versionadded:: 3.30\n', 'persistentHistoryCleared': 'Emitted when the persistent history of commands run in the editor is cleared.\n\n.. versionadded:: 3.30\n', 'helpRequested': 'Emitted when documentation was requested for the specified ``word``.\n\n.. versionadded:: 3.42\n', 'editingTimeout': 'Emitted when either:\n\n1. 500ms have elapsed since the last text change in the widget\n2. or, immediately after the widget has lost focus after its text was changed.\n\n.. seealso:: :py:func:`editingTimeoutInterval`\n\n.. versionadded:: 3.42\n'}
QgsCodeEditor.languageToString = staticmethod(QgsCodeEditor.languageToString)
QgsCodeEditor.defaultColor = staticmethod(QgsCodeEditor.defaultColor)
QgsCodeEditor.color = staticmethod(QgsCodeEditor.color)

View File

@ -3,7 +3,7 @@ QgsDoubleSpinBox.MinimumValue = QgsDoubleSpinBox.ClearValueMode.MinimumValue
QgsDoubleSpinBox.MaximumValue = QgsDoubleSpinBox.ClearValueMode.MaximumValue
QgsDoubleSpinBox.CustomValue = QgsDoubleSpinBox.ClearValueMode.CustomValue
try:
QgsDoubleSpinBox.__attribute_docs__ = {'returnPressed': 'Emitted when the Return or Enter key is used in the line edit.\n\n.. versionadded:: 3.40\n', 'textEdited': 'Emitted when the the value has been manually edited via line edit.\n\n.. versionadded:: 3.40\n', 'editingTimeout': 'Emitted when either:\n\n1. 2 seconds has elapsed since the last value change in the widget (eg last key press or scroll wheel event)\n2. or, immediately after the widget has lost focus after its value was changed.\n\nThis signal can be used to respond semi-instantly to changes in the spin box, without responding too quickly\nwhile the user in the middle of setting the value.\n\n.. seealso:: :py:func:`editingTimeoutInterval`\n\n.. versionadded:: 3.42\n'}
QgsDoubleSpinBox.__attribute_docs__ = {'returnPressed': 'Emitted when the Return or Enter key is used in the line edit.\n\n.. versionadded:: 3.40\n', 'textEdited': 'Emitted when the the value has been manually edited via line edit.\n\n.. versionadded:: 3.40\n', 'editingTimeout': 'Emitted when either:\n\n1. 1 second has elapsed since the last value change in the widget (eg last key press or scroll wheel event)\n2. or, immediately after the widget has lost focus after its value was changed.\n\nThis signal can be used to respond semi-instantly to changes in the spin box, without responding too quickly\nwhile the user in the middle of setting the value.\n\n.. seealso:: :py:func:`editingTimeoutInterval`\n\n.. versionadded:: 3.42\n'}
QgsDoubleSpinBox.__signal_arguments__ = {'textEdited': ['text: str'], 'editingTimeout': ['value: float']}
QgsDoubleSpinBox.__group__ = ['editorwidgets']
except (NameError, AttributeError):

View File

@ -3,7 +3,7 @@ QgsSpinBox.MinimumValue = QgsSpinBox.ClearValueMode.MinimumValue
QgsSpinBox.MaximumValue = QgsSpinBox.ClearValueMode.MaximumValue
QgsSpinBox.CustomValue = QgsSpinBox.ClearValueMode.CustomValue
try:
QgsSpinBox.__attribute_docs__ = {'returnPressed': 'Emitted when the Return or Enter key is used in the line edit\n\n.. versionadded:: 3.40\n', 'textEdited': 'Emitted when the the value has been manually edited via line edit.\n\n.. versionadded:: 3.40\n', 'editingTimeout': 'Emitted when either:\n\n1. 2 seconds has elapsed since the last value change in the widget (eg last key press or scroll wheel event)\n2. or, immediately after the widget has lost focus after its value was changed.\n\nThis signal can be used to respond semi-instantly to changes in the spin box, without responding too quickly\nwhile the user in the middle of setting the value.\n\n.. seealso:: :py:func:`editingTimeoutInterval`\n\n.. versionadded:: 3.42\n'}
QgsSpinBox.__attribute_docs__ = {'returnPressed': 'Emitted when the Return or Enter key is used in the line edit\n\n.. versionadded:: 3.40\n', 'textEdited': 'Emitted when the the value has been manually edited via line edit.\n\n.. versionadded:: 3.40\n', 'editingTimeout': 'Emitted when either:\n\n1. 1 second has elapsed since the last value change in the widget (eg last key press or scroll wheel event)\n2. or, immediately after the widget has lost focus after its value was changed.\n\nThis signal can be used to respond semi-instantly to changes in the spin box, without responding too quickly\nwhile the user in the middle of setting the value.\n\n.. seealso:: :py:func:`editingTimeoutInterval`\n\n.. versionadded:: 3.42\n'}
QgsSpinBox.__signal_arguments__ = {'textEdited': ['text: str'], 'editingTimeout': ['value: int']}
QgsSpinBox.__group__ = ['editorwidgets']
except (NameError, AttributeError):

View File

@ -373,6 +373,18 @@ If wrapping is disabled, returns -1 instead
.. versionadded:: 3.40
%End
int editingTimeoutInterval() const;
%Docstring
Returns the timeout (in milliseconds) threshold for the :py:func:`~QgsCodeEditor.editingTimeout` signal to be emitted
after an edit.
.. seealso:: :py:func:`setEditingTimeoutInterval`
.. versionadded:: 3.42
%End
public slots:
void runCommand( const QString &command, bool skipHistory = false );
@ -509,6 +521,18 @@ Adjust the width of the scroll bar to fit the content.
virtual void setText( const QString &text );
void setEditingTimeoutInterval( int timeout );
%Docstring
Sets the ``timeout`` (in milliseconds) threshold for the :py:func:`~QgsCodeEditor.editingTimeout` signal to be emitted
after an edit.
.. seealso:: :py:func:`editingTimeoutInterval`
.. seealso:: :py:func:`editingTimeout`
.. versionadded:: 3.42
%End
signals:
void sessionHistoryCleared();
@ -530,6 +554,19 @@ Emitted when the persistent history of commands run in the editor is cleared.
%Docstring
Emitted when documentation was requested for the specified ``word``.
.. versionadded:: 3.42
%End
void editingTimeout();
%Docstring
Emitted when either:
1. 500ms have elapsed since the last text change in the widget
2. or, immediately after the widget has lost focus after its text was changed.
.. seealso:: :py:func:`editingTimeoutInterval`
.. versionadded:: 3.42
%End
@ -547,7 +584,6 @@ Returns ``True`` if a ``font`` is a fixed pitch font.
virtual bool eventFilter( QObject *watched, QEvent *event );
virtual void initializeLexer();
%Docstring
Called when the dialect specific code lexer needs to be initialized (or reinitialized).

View File

@ -191,7 +191,7 @@ Emitted when the the value has been manually edited via line edit.
%Docstring
Emitted when either:
1. 2 seconds has elapsed since the last value change in the widget (eg last key press or scroll wheel event)
1. 1 second has elapsed since the last value change in the widget (eg last key press or scroll wheel event)
2. or, immediately after the widget has lost focus after its value was changed.
This signal can be used to respond semi-instantly to changes in the spin box, without responding too quickly

View File

@ -179,7 +179,7 @@ Emitted when the the value has been manually edited via line edit.
%Docstring
Emitted when either:
1. 2 seconds has elapsed since the last value change in the widget (eg last key press or scroll wheel event)
1. 1 second has elapsed since the last value change in the widget (eg last key press or scroll wheel event)
2. or, immediately after the widget has lost focus after its value was changed.
This signal can be used to respond semi-instantly to changes in the spin box, without responding too quickly

View File

@ -56,7 +56,7 @@ QgsCodeEditor.Flag.baseClass = QgsCodeEditor
QgsCodeEditor.Flags.baseClass = QgsCodeEditor
Flags = QgsCodeEditor # dirty hack since SIP seems to introduce the flags in module
try:
QgsCodeEditor.__attribute_docs__ = {'SEARCH_RESULT_INDICATOR': 'Indicator index for search results', 'sessionHistoryCleared': 'Emitted when the history of commands run in the current session is cleared.\n\n.. versionadded:: 3.30\n', 'persistentHistoryCleared': 'Emitted when the persistent history of commands run in the editor is cleared.\n\n.. versionadded:: 3.30\n', 'helpRequested': 'Emitted when documentation was requested for the specified ``word``.\n\n.. versionadded:: 3.42\n'}
QgsCodeEditor.__attribute_docs__ = {'SEARCH_RESULT_INDICATOR': 'Indicator index for search results', 'sessionHistoryCleared': 'Emitted when the history of commands run in the current session is cleared.\n\n.. versionadded:: 3.30\n', 'persistentHistoryCleared': 'Emitted when the persistent history of commands run in the editor is cleared.\n\n.. versionadded:: 3.30\n', 'helpRequested': 'Emitted when documentation was requested for the specified ``word``.\n\n.. versionadded:: 3.42\n', 'editingTimeout': 'Emitted when either:\n\n1. 500ms have elapsed since the last text change in the widget\n2. or, immediately after the widget has lost focus after its text was changed.\n\n.. seealso:: :py:func:`editingTimeoutInterval`\n\n.. versionadded:: 3.42\n'}
QgsCodeEditor.languageToString = staticmethod(QgsCodeEditor.languageToString)
QgsCodeEditor.defaultColor = staticmethod(QgsCodeEditor.defaultColor)
QgsCodeEditor.color = staticmethod(QgsCodeEditor.color)

View File

@ -1,6 +1,6 @@
# The following has been generated automatically from src/gui/editorwidgets/qgsdoublespinbox.h
try:
QgsDoubleSpinBox.__attribute_docs__ = {'returnPressed': 'Emitted when the Return or Enter key is used in the line edit.\n\n.. versionadded:: 3.40\n', 'textEdited': 'Emitted when the the value has been manually edited via line edit.\n\n.. versionadded:: 3.40\n', 'editingTimeout': 'Emitted when either:\n\n1. 2 seconds has elapsed since the last value change in the widget (eg last key press or scroll wheel event)\n2. or, immediately after the widget has lost focus after its value was changed.\n\nThis signal can be used to respond semi-instantly to changes in the spin box, without responding too quickly\nwhile the user in the middle of setting the value.\n\n.. seealso:: :py:func:`editingTimeoutInterval`\n\n.. versionadded:: 3.42\n'}
QgsDoubleSpinBox.__attribute_docs__ = {'returnPressed': 'Emitted when the Return or Enter key is used in the line edit.\n\n.. versionadded:: 3.40\n', 'textEdited': 'Emitted when the the value has been manually edited via line edit.\n\n.. versionadded:: 3.40\n', 'editingTimeout': 'Emitted when either:\n\n1. 1 second has elapsed since the last value change in the widget (eg last key press or scroll wheel event)\n2. or, immediately after the widget has lost focus after its value was changed.\n\nThis signal can be used to respond semi-instantly to changes in the spin box, without responding too quickly\nwhile the user in the middle of setting the value.\n\n.. seealso:: :py:func:`editingTimeoutInterval`\n\n.. versionadded:: 3.42\n'}
QgsDoubleSpinBox.__signal_arguments__ = {'textEdited': ['text: str'], 'editingTimeout': ['value: float']}
QgsDoubleSpinBox.__group__ = ['editorwidgets']
except (NameError, AttributeError):

View File

@ -1,6 +1,6 @@
# The following has been generated automatically from src/gui/editorwidgets/qgsspinbox.h
try:
QgsSpinBox.__attribute_docs__ = {'returnPressed': 'Emitted when the Return or Enter key is used in the line edit\n\n.. versionadded:: 3.40\n', 'textEdited': 'Emitted when the the value has been manually edited via line edit.\n\n.. versionadded:: 3.40\n', 'editingTimeout': 'Emitted when either:\n\n1. 2 seconds has elapsed since the last value change in the widget (eg last key press or scroll wheel event)\n2. or, immediately after the widget has lost focus after its value was changed.\n\nThis signal can be used to respond semi-instantly to changes in the spin box, without responding too quickly\nwhile the user in the middle of setting the value.\n\n.. seealso:: :py:func:`editingTimeoutInterval`\n\n.. versionadded:: 3.42\n'}
QgsSpinBox.__attribute_docs__ = {'returnPressed': 'Emitted when the Return or Enter key is used in the line edit\n\n.. versionadded:: 3.40\n', 'textEdited': 'Emitted when the the value has been manually edited via line edit.\n\n.. versionadded:: 3.40\n', 'editingTimeout': 'Emitted when either:\n\n1. 1 second has elapsed since the last value change in the widget (eg last key press or scroll wheel event)\n2. or, immediately after the widget has lost focus after its value was changed.\n\nThis signal can be used to respond semi-instantly to changes in the spin box, without responding too quickly\nwhile the user in the middle of setting the value.\n\n.. seealso:: :py:func:`editingTimeoutInterval`\n\n.. versionadded:: 3.42\n'}
QgsSpinBox.__signal_arguments__ = {'textEdited': ['text: str'], 'editingTimeout': ['value: int']}
QgsSpinBox.__group__ = ['editorwidgets']
except (NameError, AttributeError):

View File

@ -373,6 +373,18 @@ If wrapping is disabled, returns -1 instead
.. versionadded:: 3.40
%End
int editingTimeoutInterval() const;
%Docstring
Returns the timeout (in milliseconds) threshold for the :py:func:`~QgsCodeEditor.editingTimeout` signal to be emitted
after an edit.
.. seealso:: :py:func:`setEditingTimeoutInterval`
.. versionadded:: 3.42
%End
public slots:
void runCommand( const QString &command, bool skipHistory = false );
@ -509,6 +521,18 @@ Adjust the width of the scroll bar to fit the content.
virtual void setText( const QString &text );
void setEditingTimeoutInterval( int timeout );
%Docstring
Sets the ``timeout`` (in milliseconds) threshold for the :py:func:`~QgsCodeEditor.editingTimeout` signal to be emitted
after an edit.
.. seealso:: :py:func:`editingTimeoutInterval`
.. seealso:: :py:func:`editingTimeout`
.. versionadded:: 3.42
%End
signals:
void sessionHistoryCleared();
@ -530,6 +554,19 @@ Emitted when the persistent history of commands run in the editor is cleared.
%Docstring
Emitted when documentation was requested for the specified ``word``.
.. versionadded:: 3.42
%End
void editingTimeout();
%Docstring
Emitted when either:
1. 500ms have elapsed since the last text change in the widget
2. or, immediately after the widget has lost focus after its text was changed.
.. seealso:: :py:func:`editingTimeoutInterval`
.. versionadded:: 3.42
%End
@ -547,7 +584,6 @@ Returns ``True`` if a ``font`` is a fixed pitch font.
virtual bool eventFilter( QObject *watched, QEvent *event );
virtual void initializeLexer();
%Docstring
Called when the dialect specific code lexer needs to be initialized (or reinitialized).

View File

@ -191,7 +191,7 @@ Emitted when the the value has been manually edited via line edit.
%Docstring
Emitted when either:
1. 2 seconds has elapsed since the last value change in the widget (eg last key press or scroll wheel event)
1. 1 second has elapsed since the last value change in the widget (eg last key press or scroll wheel event)
2. or, immediately after the widget has lost focus after its value was changed.
This signal can be used to respond semi-instantly to changes in the spin box, without responding too quickly

View File

@ -179,7 +179,7 @@ Emitted when the the value has been manually edited via line edit.
%Docstring
Emitted when either:
1. 2 seconds has elapsed since the last value change in the widget (eg last key press or scroll wheel event)
1. 1 second has elapsed since the last value change in the widget (eg last key press or scroll wheel event)
2. or, immediately after the widget has lost focus after its value was changed.
This signal can be used to respond semi-instantly to changes in the spin box, without responding too quickly

View File

@ -149,6 +149,12 @@ QgsCodeEditor::QgsCodeEditor( QWidget *parent, const QString &title, bool foldin
#if QSCINTILLA_VERSION < 0x020d03
installEventFilter( this );
#endif
mLastEditTimer = new QTimer( this );
mLastEditTimer->setSingleShot( true );
mLastEditTimer->setInterval( 500 );
connect( mLastEditTimer, &QTimer::timeout, this, &QgsCodeEditor::onLastEditTimeout );
connect( this, &QgsCodeEditor::textChanged, mLastEditTimer, qOverload<>( &QTimer::start ) );
}
// Workaround a bug in QScintilla 2.8.X
@ -177,6 +183,7 @@ void QgsCodeEditor::focusOutEvent( QFocusEvent *event )
{
QsciScintilla::focusOutEvent( event );
}
onLastEditTimeout();
}
// This workaround a likely bug in QScintilla. The ESC key should not be consumned
@ -352,6 +359,7 @@ void QgsCodeEditor::contextMenuEvent( QContextMenuEvent *event )
}
}
bool QgsCodeEditor::eventFilter( QObject *watched, QEvent *event )
{
#if QSCINTILLA_VERSION < 0x020d03
@ -453,6 +461,12 @@ void QgsCodeEditor::runPostLexerConfigurationTasks()
}
}
void QgsCodeEditor::onLastEditTimeout()
{
mLastEditTimer->stop();
emit editingTimeout();
}
void QgsCodeEditor::setSciWidget()
{
const QFont font = lexerFont();
@ -841,10 +855,24 @@ void QgsCodeEditor::adjustScrollWidth()
void QgsCodeEditor::setText( const QString &text )
{
disconnect( this, &QgsCodeEditor::textChanged, mLastEditTimer, qOverload<>( &QTimer::start ) );
QsciScintilla::setText( text );
connect( this, &QgsCodeEditor::textChanged, mLastEditTimer, qOverload<>( &QTimer::start ) );
onLastEditTimeout();
adjustScrollWidth();
}
int QgsCodeEditor::editingTimeoutInterval() const
{
return mLastEditTimer->interval();
}
void QgsCodeEditor::setEditingTimeoutInterval( int timeout )
{
mLastEditTimer->setInterval( timeout );
}
QStringList QgsCodeEditor::history() const
{
return mHistory;

View File

@ -415,6 +415,18 @@ class GUI_EXPORT QgsCodeEditor : public QsciScintilla
*/
int wrapPosition( int line = -1 );
/**
* Returns the timeout (in milliseconds) threshold for the editingTimeout() signal to be emitted
* after an edit.
*
* \see setEditingTimeoutInterval()
*
* \since QGIS 3.42
*/
int editingTimeoutInterval() const;
public slots:
/**
@ -541,6 +553,17 @@ class GUI_EXPORT QgsCodeEditor : public QsciScintilla
// Override QsciScintilla::setText to adjust the scroll width
void setText( const QString &text ) override;
/**
* Sets the \a timeout (in milliseconds) threshold for the editingTimeout() signal to be emitted
* after an edit.
*
* \see editingTimeoutInterval()
* \see editingTimeout()
*
* \since QGIS 3.42
*/
void setEditingTimeoutInterval( int timeout );
signals:
/**
@ -565,6 +588,20 @@ class GUI_EXPORT QgsCodeEditor : public QsciScintilla
*/
void helpRequested( const QString &word );
/**
* Emitted when either:
*
* 1. 500ms have elapsed since the last text change in the widget
* 2. or, immediately after the widget has lost focus after its text was changed.
*
*
* \see editingTimeoutInterval()
*
* \since QGIS 3.42
*/
void editingTimeout();
protected:
/**
* Returns TRUE if a \a font is a fixed pitch font.
@ -575,7 +612,6 @@ class GUI_EXPORT QgsCodeEditor : public QsciScintilla
void keyPressEvent( QKeyEvent *event ) override;
void contextMenuEvent( QContextMenuEvent *event ) override;
bool eventFilter( QObject *watched, QEvent *event ) override;
/**
* Called when the dialect specific code lexer needs to be initialized (or reinitialized).
*
@ -651,6 +687,9 @@ class GUI_EXPORT QgsCodeEditor : public QsciScintilla
*/
virtual void showMessage( const QString &title, const QString &message, Qgis::MessageLevel level );
private slots:
void onLastEditTimeout();
private:
void setSciWidget();
void updateFolding();
@ -685,6 +724,8 @@ class GUI_EXPORT QgsCodeEditor : public QsciScintilla
static QMap<QgsCodeEditorColorScheme::ColorRole, QString> sColorRoleToSettingsKey;
static constexpr int MARKER_NUMBER = 6;
QTimer *mLastEditTimer = nullptr;
};
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsCodeEditor::Flags )

View File

@ -188,7 +188,7 @@ class GUI_EXPORT QgsDoubleSpinBox : public QDoubleSpinBox
/**
* Emitted when either:
*
* 1. 2 seconds has elapsed since the last value change in the widget (eg last key press or scroll wheel event)
* 1. 1 second has elapsed since the last value change in the widget (eg last key press or scroll wheel event)
* 2. or, immediately after the widget has lost focus after its value was changed.
*
* This signal can be used to respond semi-instantly to changes in the spin box, without responding too quickly

View File

@ -179,7 +179,7 @@ class GUI_EXPORT QgsSpinBox : public QSpinBox
/**
* Emitted when either:
*
* 1. 2 seconds has elapsed since the last value change in the widget (eg last key press or scroll wheel event)
* 1. 1 second has elapsed since the last value change in the widget (eg last key press or scroll wheel event)
* 2. or, immediately after the widget has lost focus after its value was changed.
*
* This signal can be used to respond semi-instantly to changes in the spin box, without responding too quickly