Extend UDP Reply message with keyboard modifiers

This allows UDP servers to  emulate keyboard modified double-clicks on
decoded messages,  E.g. ALT+double-click for  replying to a CQ  or QRZ
call without changing ones Tx frequency offset.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@8103 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2017-09-22 15:36:24 +00:00
parent e1da6f6e16
commit 567af321c0
11 changed files with 43 additions and 21 deletions

View File

@ -152,12 +152,14 @@ void MessageClient::impl::parse_message (QByteArray const& msg)
QByteArray mode;
QByteArray message;
bool low_confidence {false};
in >> time >> snr >> delta_time >> delta_frequency >> mode >> message >> low_confidence;
quint8 modifiers {0};
in >> time >> snr >> delta_time >> delta_frequency >> mode >> message
>> low_confidence >> modifiers;
if (check_status (in) != Fail)
{
Q_EMIT self_->reply (time, snr, delta_time, delta_frequency
, QString::fromUtf8 (mode), QString::fromUtf8 (message)
, low_confidence);
, low_confidence, modifiers);
}
}
break;

View File

@ -72,7 +72,7 @@ public:
// this signal is emitted if the server sends us a reply, the only
// reply supported is reply to a prior CQ or QRZ message
Q_SIGNAL void reply (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode
, QString const& message_text, bool low_confidence);
, QString const& message_text, bool low_confidence, quint8 modifiers);
// this signal is emitted if the server has requested a replay of
// all decodes

View File

@ -403,7 +403,9 @@ void MessageServer::start (port_type port, QHostAddress const& multicast_group_a
}
}
void MessageServer::reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text, bool low_confidence)
void MessageServer::reply (QString const& id, QTime time, qint32 snr, float delta_time
, quint32 delta_frequency, QString const& mode
, QString const& message_text, bool low_confidence, quint8 modifiers)
{
auto iter = m_->clients_.find (id);
if (iter != std::end (m_->clients_))
@ -411,7 +413,7 @@ void MessageServer::reply (QString const& id, QTime time, qint32 snr, float delt
QByteArray message;
NetworkMessage::Builder out {&message, NetworkMessage::Reply, id, (*iter).negotiated_schema_number_};
out << time << snr << delta_time << delta_frequency << mode.toUtf8 ()
<< message_text.toUtf8 () << low_confidence;
<< message_text.toUtf8 () << low_confidence << modifiers;
m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_);
}
}

View File

@ -46,7 +46,7 @@ public:
// note that the client is not obliged to take any action and only
// takes any action if the decode is present and is a CQ or QRZ message
Q_SLOT void reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency
, QString const& mode, QString const& message, bool low_confidence);
, QString const& mode, QString const& message, bool low_confidence, quint8 modifiers);
// ask the client with identification 'id' to replay all decodes
Q_SLOT void replay (QString const& id);

View File

@ -157,7 +157,7 @@
* Mode utf8
* Message utf8
* Low confidence bool
* Off air bool
* Off air bool
*
* The decode message is sent when a new decode is completed, in
* this case the 'New' field is true. It is also used in response
@ -193,6 +193,7 @@
* Mode utf8
* Message utf8
* Low confidence bool
* Modifiers quint8
*
* In order for a server to provide a useful cooperative service
* to WSJT-X it is possible for it to initiate a QSO by sending
@ -209,6 +210,19 @@
* initiation the rest of the QSO is carried out manually using
* the normal WSJT-X user interface.
*
* The Modifiers field allows the equivalent of keyboard
* modifiers to be sent "as if" those modifier keys where pressed
* while double-clicking the specified decoded message. The
* modifier values (hexadecimal) are as follows:
*
* no modifier 0x00
* SHIFT 0x02
* CTRL 0x04 CMD on Mac
* ALT 0x08
* META 0x10 Windows key on MS Windows
* KEYPAD 0x20 Keypad or arrows
* Group switch 0x40 X11 only
*
*
* QSO Logged Out 5 quint32
* Id (unique key) utf8

View File

@ -208,7 +208,7 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod
// 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));
Q_EMIT do_reply (decodes_proxy_model_.mapToSource (index), QApplication::keyboardModifiers () >> 24);
});
}

View File

@ -39,7 +39,7 @@ public:
, QString const& callsign, QString const& grid, qint32 power
, bool off_air);
Q_SIGNAL void do_reply (QModelIndex const&);
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);

View File

@ -136,7 +136,7 @@ void DecodesModel::clear_decodes (QString const& client_id)
}
}
void DecodesModel::do_reply (QModelIndex const& source)
void DecodesModel::do_reply (QModelIndex const& source, quint8 modifiers)
{
auto row = source.row ();
Q_EMIT reply (data (index (row, 0)).toString ()
@ -146,7 +146,8 @@ void DecodesModel::do_reply (QModelIndex const& source)
, item (row, 4)->data ().toInt ()
, data (index (row, 5)).toString ()
, data (index (row, 6)).toString ()
, confidence_string (true) == data (index (row, 7)).toString ());
, confidence_string (true) == data (index (row, 7)).toString ()
, modifiers);
}
#include "moc_DecodesModel.cpp"

View File

@ -35,10 +35,10 @@ public:
, quint32 delta_frequency, QString const& mode, QString const& message
, bool low_confidence, bool off_air, bool is_fast);
Q_SLOT void clear_decodes (QString const& client_id);
Q_SLOT void do_reply (QModelIndex const& source);
Q_SLOT void do_reply (QModelIndex const& source, quint8 modifiers);
Q_SIGNAL void reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency
, QString const& mode, QString const& message, bool low_confidence);
, QString const& mode, QString const& message, bool low_confidence, quint8 modifiers);
};
#endif

View File

@ -6130,7 +6130,9 @@ void MainWindow::on_cbTx6_toggled(bool)
}
// Takes a decoded CQ line and sets it up for reply
void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text)
void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 delta_frequency
, QString const& mode, QString const& message_text
, bool /*low_confidence*/, quint8 modifiers)
{
if (!m_config.accept_udp_requests ())
{
@ -6140,14 +6142,14 @@ void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 de
if (message_text.contains (QRegularExpression {R"(^(CQ |CQDX |QRZ ))"}))
{
// a message we are willing to accept
QString format_string {"%1 %2 %3 %4 %5 %6"};
QString format_string {"%1 %2 %3 %4 %5 %6"};
auto const& time_string = time.toString ("~" == mode || "&" == mode ? "hhmmss" : "hhmm");
auto cqtext = format_string
.arg (time_string)
.arg (snr, 3)
.arg (delta_time, 4, 'f', 1)
.arg (delta_frequency, 4)
.arg (mode)
.arg (mode, 2)
.arg (message_text);
auto messages = ui->decodedTextBrowser->toPlainText ();
auto position = messages.lastIndexOf (cqtext);
@ -6159,7 +6161,7 @@ void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 de
.arg (snr, 3)
.arg ('-' + QString::number (delta_time, 'f', 1), 4)
.arg (delta_frequency, 4)
.arg (mode)
.arg (mode, 2)
.arg (message_text));
}
if (position >= 0)
@ -6180,8 +6182,9 @@ void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 de
m_bDoubleClicked = true;
auto start = messages.left (position).lastIndexOf (QChar::LineFeed) + 1;
DecodedText message {messages.mid (start, position - start), ("MSK144" == m_mode || "FT8" == m_mode) &&
ui->cbVHFcontest->isChecked(), m_config.my_grid ()};
processMessage (message);
ui->cbVHFcontest->isChecked(), m_config.my_grid ()};
Qt::KeyboardModifiers kbmod {modifiers << 24};
processMessage (message, kbmod & Qt::ControlModifier,kbmod & Qt::AltModifier);
tx_watchdog (false);
QApplication::alert (this);
}
@ -6239,7 +6242,7 @@ void MainWindow::postDecode (bool is_new, QString const& message)
m_messageClient->decode (is_new
, QTime::fromString (parts[0], has_seconds ? "hhmmss" : "hhmm")
, parts[1].toInt ()
, parts[2].toFloat (), parts[3].toUInt (), parts[4][0]
, parts[2].toFloat (), parts[3].toUInt (), parts[4]
, decode.mid (has_seconds ? 24 : 22, 21)
, QChar {'?'} == decode.mid (has_seconds ? 24 + 21 : 22 + 21, 1)
, m_diskData);

View File

@ -597,7 +597,7 @@ private:
void displayDialFrequency ();
void transmitDisplay (bool);
void processMessage(DecodedText const&, bool ctrl = false, bool alt = false);
void replyToCQ (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text);
void replyToCQ (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text, bool low_confidence, quint8 modifiers);
void replayDecodes ();
void postDecode (bool is_new, QString const& message);
void postWSPRDecode (bool is_new, QStringList message_parts);