Reputation: 19607
I have a CodeEditor
class which inherits from QPlainTextEdit
. This class has to emit requests when textCursor()
's position or selection changes. The thing is, I don't want 2 calls to assembleIntellisenseRequest
and pickListSortRequest
signals when both cursorPositionChanged
and selectionChanged
is emitted. I solved this with adding bool update_
member to CodeEditor
, which is set to true
in constructor. 500ms delay is just for clarity.
void CodeEditor::makeConnections()
{
auto updateRequest = [this]()
{
if(update_ && !textCursor().hasSelection())
{
update_ = false;
QTimer::singleShot(500, [this]() { update_ = true; });
emit assembleIntellisenseRequest(textCursor().blockNumber());
emit pickListSortRequest(textCursor().positionInBlock());
}
};
connect(this, &CodeEditor::cursorPositionChanged, updateRequest);
connect(this, &CodeEditor::selectionChanged, updateRequest);
}
Is there any better way to accomplish this? Also, why was in this case, when lambda captures by reference this1:
printout not equal to this:
? It was silent, I just knew, that update_
is still false
.
auto updateRequest = [this]()
{
cout << "this: " << this << endl;
if(update_ && !textCursor().hasSelection())
{
update_ = false;
QTimer::singleShot(500, [&]()
{
cout << "this1: " << this << endl;
update_ = true;
});
emit assembleIntellisenseRequest(textCursor().blockNumber());
emit pickListSortRequest(textCursor().positionInBlock());
}
};
Thank you in advance.
Upvotes: 1
Views: 416
Reputation: 8994
You can apply next pattern to your code:
class MyClass : public QObject
{
private slots:
void updateRequest();
private:
QTimer *_timer;
CodeEditor *_editor;
};
MyClass::MyClass()
{
// Init members
// ...
_timer->setSingleShot( true );
_timer->setInterval( 0 );
connect( _editor, &CodeEditor:: cursorPositionChanged, _timer, &QTimer::start);
connect( _editor, &CodeEditor:: selectionChanged, _timer, &QTimer::start);
connect( _timer, &QTimer::timeout, this, &MyClass::updateRequest );
}
In this solution, timer is a "proxy for signals". Each time signal is emited timer will start immedeately (when flow will return to an event loop). Each emitting of signal will call QTimer::start
slot. But all calls of start
will place only one call of timeout
signal to event queue. So, when control flow will return to event loop, your updateRequest
slot will be called only once, even if a lot of signals were emited.
QTimer
is a "Qt way" to replace your update_
variable, without any timeouts.
Upvotes: 2