mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2026-06-08 00:44:39 -04:00
New incoming UDP message to allow external applications to highlight decoded callsigns
UDP servers can request that WSJT-X clients highlight a specified callsign in the Band Activity decodes window. Either the last occurrence of the callsign may be highlighted or all past and future occurrences can be highlighted. The latter case WSJT-X will remember the callsign and requested highlighting options so that future occurrences can be correctly highlighted. Either or both of the text background color and the text foreground color may be specified. A further UDP message may be sent to change the persistent color highlighting for a given callsign, including reseting persistent highlighting by passing an invalid color value. Thanks to Alex, VE3NEA, for this contribution. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@8589 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
@@ -115,9 +115,10 @@ namespace
|
||||
|
||||
ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemModel * beacons_model
|
||||
, QString const& id, QString const& version, QString const& revision
|
||||
, QWidget * parent)
|
||||
, QListWidget const * calls_of_interest, QWidget * parent)
|
||||
: QDockWidget {make_title (id, version, revision), parent}
|
||||
, id_ {id}
|
||||
, calls_of_interest_ {calls_of_interest}
|
||||
, decodes_proxy_model_ {id_}
|
||||
, decodes_table_view_ {new QTableView}
|
||||
, beacons_table_view_ {new QTableView}
|
||||
@@ -216,11 +217,27 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod
|
||||
// setMinimumSize (QSize {550, 0});
|
||||
setFeatures (DockWidgetMovable | DockWidgetFloatable);
|
||||
setAllowedAreas (Qt::BottomDockWidgetArea);
|
||||
setFloating (true);
|
||||
|
||||
// connect up table view signals
|
||||
connect (decodes_table_view_, &QTableView::doubleClicked, this, [this] (QModelIndex const& index) {
|
||||
Q_EMIT do_reply (decodes_proxy_model_.mapToSource (index), QApplication::keyboardModifiers () >> 24);
|
||||
});
|
||||
|
||||
// tell new client about calls of interest
|
||||
for (int row = 0; row < calls_of_interest_->count (); ++row)
|
||||
{
|
||||
Q_EMIT highlight_callsign (id_, calls_of_interest_->item (row)->text (), QColor {Qt::blue}, QColor {Qt::yellow});
|
||||
}
|
||||
}
|
||||
|
||||
ClientWidget::~ClientWidget ()
|
||||
{
|
||||
for (int row = 0; row < calls_of_interest_->count (); ++row)
|
||||
{
|
||||
// tell client to forget calls of interest
|
||||
Q_EMIT highlight_callsign (id_, calls_of_interest_->item (row)->text ());
|
||||
}
|
||||
}
|
||||
|
||||
void ClientWidget::update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
class QAbstractItemModel;
|
||||
class QModelIndex;
|
||||
class QColor;
|
||||
|
||||
using Frequency = MessageServer::Frequency;
|
||||
|
||||
@@ -22,7 +23,8 @@ class ClientWidget
|
||||
public:
|
||||
explicit ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemModel * beacons_model
|
||||
, QString const& id, QString const& version, QString const& revision
|
||||
, QWidget * parent = nullptr);
|
||||
, QListWidget const * calls_of_interest, QWidget * parent = nullptr);
|
||||
~ClientWidget ();
|
||||
|
||||
bool fast_mode () const {return fast_mode_;}
|
||||
|
||||
@@ -43,10 +45,14 @@ public:
|
||||
Q_SIGNAL void do_reply (QModelIndex const&, quint8 modifier);
|
||||
Q_SIGNAL void do_halt_tx (QString const& id, bool auto_only);
|
||||
Q_SIGNAL void do_free_text (QString const& id, QString const& text, bool);
|
||||
Q_SIGNAL void location (QString const &id, QString const &text);
|
||||
Q_SIGNAL void location (QString const& id, QString const& text);
|
||||
Q_SIGNAL void highlight_callsign (QString const& id, QString const& call
|
||||
, QColor const& bg = QColor {}, QColor const& fg = QColor {}
|
||||
, bool last_only = false);
|
||||
|
||||
private:
|
||||
QString id_;
|
||||
QListWidget const * calls_of_interest_;
|
||||
class IdFilterModel final
|
||||
: public QSortFilterProxyModel
|
||||
{
|
||||
|
||||
@@ -36,6 +36,11 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow ()
|
||||
, server_ {new MessageServer {this}}
|
||||
, multicast_group_line_edit_ {new QLineEdit}
|
||||
, log_table_view_ {new QTableView}
|
||||
, add_call_of_interest_action_ {new QAction {tr ("&Add callsign"), this}}
|
||||
, delete_call_of_interest_action_ {new QAction {tr ("&Delete callsign"), this}}
|
||||
, last_call_of_interest_action_ {new QAction {tr ("&Highlight last only"), this}}
|
||||
, call_of_interest_bg_colour_action_ {new QAction {tr ("&Background colour"), this}}
|
||||
, call_of_interest_fg_colour_action_ {new QAction {tr ("&Foreground colour"), this}}
|
||||
{
|
||||
// logbook
|
||||
int column {0};
|
||||
@@ -83,6 +88,91 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow ()
|
||||
setDockOptions (AnimatedDocks | AllowNestedDocks | AllowTabbedDocks);
|
||||
setTabPosition (Qt::BottomDockWidgetArea, QTabWidget::North);
|
||||
|
||||
QDockWidget * calls_dock {new QDockWidget {tr ("Calls of Interest"), this}};
|
||||
calls_dock->setAllowedAreas (Qt::RightDockWidgetArea);
|
||||
calls_of_interest_ = new QListWidget {calls_dock};
|
||||
calls_of_interest_->setContextMenuPolicy (Qt::ActionsContextMenu);
|
||||
calls_of_interest_->insertAction (nullptr, add_call_of_interest_action_);
|
||||
connect (add_call_of_interest_action_, &QAction::triggered, [this] () {
|
||||
auto item = new QListWidgetItem {};
|
||||
item->setFlags (item->flags () | Qt::ItemIsEditable);
|
||||
item->setData (Qt::UserRole, QString {});
|
||||
calls_of_interest_->addItem (item);
|
||||
calls_of_interest_->editItem (item);
|
||||
});
|
||||
calls_of_interest_->insertAction (nullptr, delete_call_of_interest_action_);
|
||||
connect (delete_call_of_interest_action_, &QAction::triggered, [this] () {
|
||||
for (auto item : calls_of_interest_->selectedItems ())
|
||||
{
|
||||
auto old_call = item->data (Qt::UserRole);
|
||||
if (old_call.isValid ()) change_highlighting (old_call.toString ());
|
||||
delete item;
|
||||
}
|
||||
});
|
||||
calls_of_interest_->insertAction (nullptr, last_call_of_interest_action_);
|
||||
connect (last_call_of_interest_action_, &QAction::triggered, [this] () {
|
||||
for (auto item : calls_of_interest_->selectedItems ())
|
||||
{
|
||||
auto old_call = item->data (Qt::UserRole);
|
||||
change_highlighting (old_call.toString ());
|
||||
change_highlighting (old_call.toString ()
|
||||
, item->background ().color (), item->foreground ().color (), true);
|
||||
delete item;
|
||||
}
|
||||
});
|
||||
calls_of_interest_->insertAction (nullptr, call_of_interest_bg_colour_action_);
|
||||
connect (call_of_interest_bg_colour_action_, &QAction::triggered, [this] () {
|
||||
for (auto item : calls_of_interest_->selectedItems ())
|
||||
{
|
||||
auto old_call = item->data (Qt::UserRole);
|
||||
auto new_colour = QColorDialog::getColor (item->background ().color ()
|
||||
, this, tr ("Select background color"));
|
||||
if (new_colour.isValid ())
|
||||
{
|
||||
change_highlighting (old_call.toString (), new_colour, item->foreground ().color ());
|
||||
item->setBackground (new_colour);
|
||||
}
|
||||
}
|
||||
});
|
||||
calls_of_interest_->insertAction (nullptr, call_of_interest_fg_colour_action_);
|
||||
connect (call_of_interest_fg_colour_action_, &QAction::triggered, [this] () {
|
||||
for (auto item : calls_of_interest_->selectedItems ())
|
||||
{
|
||||
auto old_call = item->data (Qt::UserRole);
|
||||
auto new_colour = QColorDialog::getColor (item->foreground ().color ()
|
||||
, this, tr ("Select foreground color"));
|
||||
if (new_colour.isValid ())
|
||||
{
|
||||
change_highlighting (old_call.toString (), item->background ().color (), new_colour);
|
||||
item->setForeground (new_colour);
|
||||
}
|
||||
}
|
||||
});
|
||||
connect (calls_of_interest_, &QListWidget::itemChanged, [this] (QListWidgetItem * item) {
|
||||
auto old_call = item->data (Qt::UserRole);
|
||||
auto new_call = item->text ().toUpper ();
|
||||
if (new_call != old_call)
|
||||
{
|
||||
// tell all clients
|
||||
if (old_call.isValid ())
|
||||
{
|
||||
change_highlighting (old_call.toString ());
|
||||
}
|
||||
item->setData (Qt::UserRole, new_call);
|
||||
item->setText (new_call);
|
||||
auto bg = item->listWidget ()->palette ().text ().color ();
|
||||
auto fg = item->listWidget ()->palette ().base ().color ();
|
||||
item->setBackground (bg);
|
||||
item->setForeground (fg);
|
||||
change_highlighting (new_call, bg, fg);
|
||||
}
|
||||
});
|
||||
|
||||
calls_dock->setWidget (calls_of_interest_);
|
||||
addDockWidget (Qt::RightDockWidgetArea, calls_dock);
|
||||
view_menu_->addAction (calls_dock->toggleViewAction ());
|
||||
view_menu_->addSeparator ();
|
||||
|
||||
// connect up server
|
||||
connect (server_, &MessageServer::error, [this] (QString const& message) {
|
||||
QMessageBox::warning (this, QApplication::applicationName (), tr ("Network Error"), message);
|
||||
@@ -144,7 +234,7 @@ void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time
|
||||
|
||||
void MessageAggregatorMainWindow::add_client (QString const& id, QString const& version, QString const& revision)
|
||||
{
|
||||
auto dock = new ClientWidget {decodes_model_, beacons_model_, id, version, revision, this};
|
||||
auto dock = new ClientWidget {decodes_model_, beacons_model_, id, version, revision, calls_of_interest_, this};
|
||||
dock->setAttribute (Qt::WA_DeleteOnClose);
|
||||
auto view_action = dock->toggleViewAction ();
|
||||
view_action->setEnabled (true);
|
||||
@@ -159,8 +249,9 @@ void MessageAggregatorMainWindow::add_client (QString const& id, QString const&
|
||||
connect (dock, &ClientWidget::do_free_text, server_, &MessageServer::free_text);
|
||||
connect (dock, &ClientWidget::location, server_, &MessageServer::location);
|
||||
connect (view_action, &QAction::toggled, dock, &ClientWidget::setVisible);
|
||||
connect (dock, &ClientWidget::highlight_callsign, server_, &MessageServer::highlight_callsign);
|
||||
dock_widgets_[id] = dock;
|
||||
server_->replay (id);
|
||||
server_->replay (id); // request decodes and status
|
||||
}
|
||||
|
||||
void MessageAggregatorMainWindow::remove_client (QString const& id)
|
||||
@@ -173,4 +264,21 @@ void MessageAggregatorMainWindow::remove_client (QString const& id)
|
||||
}
|
||||
}
|
||||
|
||||
MessageAggregatorMainWindow::~MessageAggregatorMainWindow ()
|
||||
{
|
||||
for (auto client : dock_widgets_)
|
||||
{
|
||||
delete client;
|
||||
}
|
||||
}
|
||||
|
||||
void MessageAggregatorMainWindow::change_highlighting (QString const& call, QColor const& bg, QColor const& fg
|
||||
, bool last_only)
|
||||
{
|
||||
for (auto id : dock_widgets_.keys ())
|
||||
{
|
||||
server_->highlight_callsign (id, call, bg, fg, last_only);
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_MessageAggregatorMainWindow.cpp"
|
||||
|
||||
@@ -15,6 +15,7 @@ class BeaconsModel;
|
||||
class QLineEdit;
|
||||
class QTableView;
|
||||
class ClientWidget;
|
||||
class QListWidget;
|
||||
|
||||
using Frequency = MessageServer::Frequency;
|
||||
|
||||
@@ -25,6 +26,7 @@ class MessageAggregatorMainWindow
|
||||
|
||||
public:
|
||||
MessageAggregatorMainWindow ();
|
||||
~MessageAggregatorMainWindow ();
|
||||
|
||||
Q_SLOT void log_qso (QString const& /*id*/, QDateTime time_off, QString const& dx_call, QString const& dx_grid
|
||||
, Frequency dial_frequency, QString const& mode, QString const& report_sent
|
||||
@@ -35,6 +37,12 @@ public:
|
||||
private:
|
||||
void add_client (QString const& id, QString const& version, QString const& revision);
|
||||
void remove_client (QString const& id);
|
||||
void change_highlighting (QString const& call, QColor const& bg = QColor {}, QColor const& fg = QColor {},
|
||||
bool last_only = false);
|
||||
|
||||
// maps client id to widgets
|
||||
using ClientsDictionary = QHash<QString, ClientWidget *>;
|
||||
ClientsDictionary dock_widgets_;
|
||||
|
||||
QStandardItemModel * log_;
|
||||
QMenu * view_menu_;
|
||||
@@ -43,10 +51,12 @@ private:
|
||||
MessageServer * server_;
|
||||
QLineEdit * multicast_group_line_edit_;
|
||||
QTableView * log_table_view_;
|
||||
|
||||
// maps client id to widgets
|
||||
using ClientsDictionary = QHash<QString, ClientWidget *>;
|
||||
ClientsDictionary dock_widgets_;
|
||||
QListWidget * calls_of_interest_;
|
||||
QAction * add_call_of_interest_action_;
|
||||
QAction * delete_call_of_interest_action_;
|
||||
QAction * last_call_of_interest_action_;
|
||||
QAction * call_of_interest_bg_colour_action_;
|
||||
QAction * call_of_interest_fg_colour_action_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user