diff --git a/Network/NetworkMessage.hpp b/Network/NetworkMessage.hpp index d01a3475e..8055e2a49 100644 --- a/Network/NetworkMessage.hpp +++ b/Network/NetworkMessage.hpp @@ -447,16 +447,20 @@ * The server may send this message at any time. The message * specifies the background and foreground color that will be * used to highlight the specified callsign in the decoded - * messages printed in the Band Activity panel. The WSJT-X + * messages printed in the Band Activity panel. The WSJT-X * clients maintain a list of such instructions and apply them to * all decoded messages in the band activity window. To clear - * highlighting send an invalid QColor value for either or both - * of the background and foreground fields. + * and cancel highlighting send an invalid QColor value for + * either or both of the background and foreground fields. When + * using this mode the total number of callsign highlighting + * requests should be limited otherwise the performance of WSJT-X + * decoding may be impacted. A rough rule of thumb might be too + * limit the number of active highlighting requests to no more + * than 100. * * The "Highlight last" field allows the sender to request that - * the last instance only instead of all instances of the - * specified call be highlighted or have it's highlighting - * cleared. + * all instances of "Callsign" in the last period only, instead + * of all instances in all periods, be highlighted. * * * SwitchConfiguration In 14 quint32 diff --git a/widgets/displaytext.cpp b/widgets/displaytext.cpp index db00e2587..b3ccf8eb2 100644 --- a/widgets/displaytext.cpp +++ b/widgets/displaytext.cpp @@ -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 {"?"}, 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); + } } } } diff --git a/widgets/displaytext.h b/widgets/displaytext.h index 5aa8c7103..fb8bb6134 100644 --- a/widgets/displaytext.h +++ b/widgets/displaytext.h @@ -43,7 +43,7 @@ public: Q_SLOT void appendText (QString const& text, QColor bg = QColor {}, QColor fg = QColor {} , QString const& call1 = QString {}, QString const& call2 = QString {}); Q_SLOT void erase (); - Q_SLOT void highlight_callsign (QString const& callsign, QColor const& bg, QColor const& fg, bool last_only); + Q_SLOT void highlight_callsign (QString const& callsign, QColor const& bg, QColor const& fg, bool last_period_only); private: void mouseDoubleClickEvent (QMouseEvent *) override;