Performance improvements to decode highlighting

The Highlight  Callsign (13)  UDP message now  operates in  a slightly
different way.  The  "Highlight last" field, when  true valued, causes
all  instances of  the specified  callsign  to be  highlighted in  the
decoding  period. This  allows external  applications to  highlight DX
callsigns even when  multiple stations are calling  them.  Before this
was  unlikely to  work since  the external  application would  have to
respond to  Decode (2) UDP  messages exceedingly quickly  to guarantee
successful highlighting  before another decode  with the same  DX call
was  printed.   There  should  be  no  changes  required  to  external
applications acting  as servers  to the  WSJT-X UDP  Message Protocol,
although  using  the  version  of the  Highlight  Callsign  (13)  with
"Highlight   last"  should   not  be   required  for   adhoc  callsign
highlighting. It should be reserved for commonly recurring targets and
limited to  no more than 100  active highlighting requests at  any one
time, otherwise there may be performance impacts on WSJT-X.
This commit is contained in:
Bill Somerville
2020-05-24 16:33:14 +01:00
parent b31dfba67b
commit c6688534cd
3 changed files with 87 additions and 45 deletions
+76 -38
View File
@@ -497,60 +497,92 @@ namespace
{
void update_selection (QTextCursor& cursor, QColor const& bg, QColor const& fg)
{
if (!cursor.isNull ())
QTextCharFormat format {cursor.charFormat ()};
if (bg.isValid ())
{
QTextCharFormat format {cursor.charFormat ()};
if (bg.isValid ())
{
format.setBackground (bg);
}
else
{
format.clearBackground ();
}
if (fg.isValid ())
{
format.setForeground (fg);
}
else
{
format.clearForeground ();
}
cursor.mergeCharFormat (format);
format.setBackground (bg);
}
else
{
format.clearBackground ();
}
if (fg.isValid ())
{
format.setForeground (fg);
}
else
{
format.clearForeground ();
}
cursor.mergeCharFormat (format);
}
void reset_selection (QTextCursor& cursor)
{
if (!cursor.isNull ())
// restore previous text format, we rely on the text
// char format at he start of the selection being the
// old one which should be the case
auto c2 = cursor;
c2.setPosition (c2.selectionStart ());
cursor.setCharFormat (c2.charFormat ());
}
}
namespace
{
QString get_timestamp (QTextCursor& cursor)
{
QString timestamp;
if (cursor.movePosition (QTextCursor::PreviousCharacter)
&& cursor.movePosition (QTextCursor::StartOfLine)
&& cursor.movePosition (QTextCursor::EndOfWord, QTextCursor::KeepAnchor)
&& cursor.hasSelection ())
{
// restore previous text format, we rely on the text
// char format at he start of the selection being the
// old one which should be the case
auto c2 = cursor;
c2.setPosition (c2.selectionStart ());
cursor.setCharFormat (c2.charFormat ());
timestamp = cursor.selectedText ();
cursor.movePosition (QTextCursor::StartOfLine);
}
return timestamp;
}
}
void DisplayText::highlight_callsign (QString const& callsign, QColor const& bg,
QColor const& fg, bool last_only)
QColor const& fg, bool last_period_only)
{
// qDebug () << "DisplayText::highlight_callsign: callsign:" << callsign << "last period:" << last_period_only;
if (!callsign.size ())
{
return;
}
QRegularExpression target {QString {"<?"} + callsign + QString {">?"}, QRegularExpression::DontCaptureOption};
QTextCharFormat old_format {currentCharFormat ()};
QTextCursor cursor {document ()};
if (last_only)
if (last_period_only)
{
// highlight each instance of the given callsign (word) in the
// current period
cursor.movePosition (QTextCursor::End);
cursor = document ()->find (callsign, cursor
, QTextDocument::FindBackward | QTextDocument::FindWholeWords);
if (bg.isValid () || fg.isValid ())
QTextCursor period_start {cursor};
QTextCursor prior {cursor};
auto period_timestamp = get_timestamp (period_start);
while (period_timestamp.size () && period_timestamp == get_timestamp (prior))
{
update_selection (cursor, bg, fg);
period_start = prior;
}
else
while (!cursor.isNull () && cursor > period_start)
{
reset_selection (cursor);
cursor = document ()->find (target, cursor
, QTextDocument::FindBackward | QTextDocument::FindWholeWords);
if (!cursor.isNull () && cursor.hasSelection ())
{
if (bg.isValid () || fg.isValid ())
{
update_selection (cursor, bg, fg);
}
else
{
reset_selection (cursor);
}
}
}
}
else
@@ -569,8 +601,11 @@ void DisplayText::highlight_callsign (QString const& callsign, QColor const& bg,
}
while (!cursor.isNull ())
{
cursor = document ()->find (callsign, cursor, QTextDocument::FindWholeWords);
update_selection (cursor, bg, fg);
cursor = document ()->find (target, cursor, QTextDocument::FindWholeWords);
if (!cursor.isNull () && cursor.hasSelection ())
{
update_selection (cursor, bg, fg);
}
}
}
else if (pos != highlighted_calls_.end ())
@@ -579,8 +614,11 @@ void DisplayText::highlight_callsign (QString const& callsign, QColor const& bg,
QTextCursor cursor {document ()};
while (!cursor.isNull ())
{
cursor = document ()->find (callsign, cursor, QTextDocument::FindWholeWords);
reset_selection (cursor);
cursor = document ()->find (target, cursor, QTextDocument::FindWholeWords);
if (!cursor.isNull () && cursor.hasSelection ())
{
reset_selection (cursor);
}
}
}
}