mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2026-08-01 16:37:31 -04:00
First attempt at a time based Tx watchdog
The watchdog configuration is now a spin box of minutes with a special first value of disabled. WSJT-X counts down minutes on the minute, if the countdown reaches zero any attempt to transmit is aborted. The countdown is reset by any mouse press or key press event inside the main window or if the Tx message changes (auto sequencing). The status bar now shows the Tx watchdog countdown if it is active. This information is shown to the right of the progress bar text. The warning message boxes triggered within the GUI update routine now no longer block the GUI updates. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6840 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
+141
-64
@@ -143,6 +143,13 @@ namespace
|
||||
&& ((type < 6 && msg_parts.contains ("73"))
|
||||
|| (type == 6 && !msg_parts.filter ("73").isEmpty ()));
|
||||
}
|
||||
|
||||
int ms_to_next_minute ()
|
||||
{
|
||||
auto const& now = QDateTime::currentDateTime ();
|
||||
auto const& time = now.time ();
|
||||
return now.msecsTo (QDateTime {now.date (), QTime {time.hour (), time.minute (), 0}}.addSecs (60));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------- MainWindow constructor
|
||||
@@ -192,7 +199,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
m_inGain {0},
|
||||
m_secID {0},
|
||||
m_repeatMsg {0},
|
||||
m_watchdogLimit {6},
|
||||
m_nSubMode {0},
|
||||
m_nclearave {1},
|
||||
m_pctx {0},
|
||||
@@ -423,7 +429,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
// text message, send + empty text means send the current free
|
||||
// text message without change, !send + empty text means clear
|
||||
// the current free text message
|
||||
qDebug () << "Free text UDP message - text:" << text << "send:" << send << "text empty:" << text.isEmpty ();
|
||||
if (0 == ui->tabWidget->currentIndex ()) {
|
||||
if (!text.isEmpty ()) {
|
||||
ui->tx5->setCurrentText (text);
|
||||
@@ -507,7 +512,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
});
|
||||
|
||||
setWindowTitle (program_title ());
|
||||
createStatusBar();
|
||||
|
||||
connect(&proc_jt9, &QProcess::readyReadStandardOutput, this, &MainWindow::readFromStdout);
|
||||
connect(&proc_jt9, static_cast<void (QProcess::*) (QProcess::ProcessError)> (&QProcess::error),
|
||||
@@ -654,6 +658,8 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
|
||||
readSettings(); //Restore user's setup params
|
||||
|
||||
createStatusBar();
|
||||
|
||||
m_audioThread.start (m_audioThreadPriority);
|
||||
|
||||
#ifdef WIN32
|
||||
@@ -834,10 +840,42 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
m_wideGraph->setModeTx(m_modeTx);
|
||||
ui->sbSubmode->setValue(m_nSubMode);
|
||||
|
||||
connect (&minuteTimer, &QTimer::timeout, this, &MainWindow::on_the_minute);
|
||||
minuteTimer.setSingleShot (true);
|
||||
minuteTimer.start (ms_to_next_minute ());
|
||||
|
||||
// this must be the last statement of constructor
|
||||
if (!m_valid) throw std::runtime_error {"Fatal initialization exception"};
|
||||
}
|
||||
|
||||
void MainWindow::on_the_minute ()
|
||||
{
|
||||
if (minuteTimer.isSingleShot ())
|
||||
{
|
||||
minuteTimer.setSingleShot (false);
|
||||
minuteTimer.start (60 * 1000); // run free
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const& ms = ms_to_next_minute ();
|
||||
if (qAbs (60 * 1000 - ms) > 1000) // correct drift
|
||||
{
|
||||
minuteTimer.setSingleShot (true);
|
||||
minuteTimer.start (ms);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_repeatMsg < m_config.watchdog ()) ++m_repeatMsg;
|
||||
if (!m_mode.startsWith ("WSPR") && m_config.watchdog () != 0)
|
||||
{
|
||||
updateProgressBarFormat (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
updateProgressBarFormat (false);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------- MainWindow destructor
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
@@ -1392,7 +1430,7 @@ void MainWindow::updateProgressBarFormat (bool wd_in_use)
|
||||
{
|
||||
if (wd_in_use)
|
||||
{
|
||||
progressBar->setFormat (QString {"%v/%m WD:%1"}.arg (m_watchdogLimit - m_repeatMsg));
|
||||
progressBar->setFormat (QString {"%v/%m WD:%1m"}.arg (m_config.watchdog () - m_repeatMsg));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1400,28 +1438,8 @@ void MainWindow::updateProgressBarFormat (bool wd_in_use)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::mousePressEvent (QMouseEvent * e)
|
||||
{
|
||||
if (!m_mode.startsWith ("WSPR") && m_mode!="Echo" && m_config.watchdog ()) {
|
||||
m_repeatMsg = 0; // reset Tx watchdog
|
||||
updateProgressBarFormat (true);
|
||||
}
|
||||
else {
|
||||
updateProgressBarFormat (false);
|
||||
}
|
||||
QMainWindow::mousePressEvent (e);
|
||||
}
|
||||
|
||||
void MainWindow::keyPressEvent (QKeyEvent * e)
|
||||
{
|
||||
if (!m_mode.startsWith ("WSPR") && m_mode!="Echo" && m_config.watchdog ()) {
|
||||
m_repeatMsg = 0; // reset Tx watchdog
|
||||
updateProgressBarFormat (true);
|
||||
}
|
||||
else {
|
||||
updateProgressBarFormat (false);
|
||||
}
|
||||
|
||||
int n;
|
||||
switch(e->key())
|
||||
{
|
||||
@@ -1570,17 +1588,35 @@ void MainWindow::statusChanged()
|
||||
<< ui->rptSpinBox->value() << ";" << m_modeTx << endl;
|
||||
f.close();
|
||||
} else {
|
||||
msgBox("Cannot open \"" + f.fileName () + "\" for writing:" + f.errorString ());
|
||||
msgBox (tr ("Cannot open \"%1\" for writing: %2").arg (f.fileName ()).arg (f.errorString ()));
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::eventFilter(QObject *object, QEvent *event) //eventFilter()
|
||||
bool MainWindow::eventFilter (QObject * object, QEvent * event)
|
||||
{
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
MainWindow::keyPressEvent(keyEvent);
|
||||
return QObject::eventFilter(object, event);
|
||||
}
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::KeyPress:
|
||||
// fall through
|
||||
case QEvent::MouseButtonPress:
|
||||
if (m_repeatMsg && !m_mode.startsWith ("WSPR") && m_config.watchdog () != 0) {
|
||||
m_repeatMsg = 0; // reset Tx watchdog
|
||||
updateProgressBarFormat (true);
|
||||
}
|
||||
break;
|
||||
|
||||
case QEvent::ChildAdded:
|
||||
// ensure our child widgets get added to our event filter
|
||||
add_child_to_event_filter (static_cast<QChildEvent *> (event)->child ());
|
||||
break;
|
||||
|
||||
case QEvent::ChildRemoved:
|
||||
// ensure our child widgets get d=removed from our event filter
|
||||
remove_child_from_event_filter (static_cast<QChildEvent *> (event)->child ());
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
return QObject::eventFilter(object, event);
|
||||
}
|
||||
|
||||
@@ -1592,7 +1628,6 @@ void MainWindow::createStatusBar() //createStatusBar
|
||||
tx_status_label->setFrameStyle(QFrame::Panel | QFrame::Sunken);
|
||||
statusBar()->addWidget(tx_status_label);
|
||||
|
||||
|
||||
mode_label->setAlignment(Qt::AlignHCenter);
|
||||
mode_label->setMinimumSize(QSize(80,18));
|
||||
mode_label->setFrameStyle(QFrame::Panel | QFrame::Sunken);
|
||||
@@ -1610,7 +1645,7 @@ void MainWindow::createStatusBar() //createStatusBar
|
||||
|
||||
statusBar()->addWidget(progressBar);
|
||||
progressBar->setMinimumSize (QSize {150, 18});
|
||||
updateProgressBarFormat (!m_mode.startsWith ("WSPR") && m_mode!="Echo" && m_config.watchdog ());
|
||||
updateProgressBarFormat (!m_mode.startsWith ("WSPR") && m_config.watchdog () != 0);
|
||||
}
|
||||
|
||||
void MainWindow::subProcessFailed (QProcess * process, int exit_code, QProcess::ExitStatus status)
|
||||
@@ -1684,11 +1719,11 @@ void MainWindow::on_stopButton_clicked() //stopButton
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::msgBox(QString t) //msgBox
|
||||
void MainWindow::msgBox (QString const& text)
|
||||
{
|
||||
msgBox0.setText(t);
|
||||
msgBox0.setText (text);
|
||||
QApplication::alert (this);
|
||||
msgBox0.exec();
|
||||
msgBox0.exec ();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionOnline_User_Guide_triggered() //Display manual
|
||||
@@ -2149,7 +2184,7 @@ void::MainWindow::fast_decode_done()
|
||||
out << message.mid(0,n-2) << endl;
|
||||
f.close();
|
||||
} else {
|
||||
msgBox("Cannot open \"" + f.fileName () + "\" for append:" + f.errorString ());
|
||||
msgBox (tr ("Cannot open \"%1\" for append: %2").arg (f.fileName ()).arg (f.errorString ()));
|
||||
}
|
||||
|
||||
if(m_mode=="JT9" or m_mode=="JTMSK" or m_mode=="MSK144") {
|
||||
@@ -2236,7 +2271,7 @@ void MainWindow::readFromStdout() //readFromStdout
|
||||
out << t.mid(0,n-2) << endl;
|
||||
f.close();
|
||||
} else {
|
||||
msgBox("Cannot open \"" + f.fileName () + "\" for append:" + f.errorString ());
|
||||
msgBox (tr ("Cannot open \"%1\" for append: %2").arg (f.fileName ()).arg (f.errorString ()));
|
||||
}
|
||||
|
||||
if (m_config.insert_blank () && m_blankLine)
|
||||
@@ -2485,13 +2520,23 @@ void MainWindow::guiUpdate()
|
||||
if (m_auto) auto_tx_mode (false);
|
||||
if(onAirFreq!=m_onAirFreq0) {
|
||||
m_onAirFreq0=onAirFreq;
|
||||
QString t="Please choose another Tx frequency.\n";
|
||||
t+="WSJT-X will not knowingly transmit another\n";
|
||||
t+="mode in the WSPR sub-band on 30 m.";
|
||||
msgBox(t);
|
||||
auto const& message = tr ("Please choose another Tx frequency.\n"
|
||||
"WSJT-X will not knowingly transmit another\n"
|
||||
"mode in the WSPR sub-band on 30 m.");
|
||||
QTimer::singleShot (0, [=] {msgBox (message);}); // don't block guiUpdate
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_mode.startsWith ("WSPR") && m_config.watchdog() != 0
|
||||
&& m_repeatMsg >= m_config. watchdog ()) {
|
||||
m_bTxTime=false;
|
||||
if (m_tune) stop_tuning ();
|
||||
if (m_auto) auto_tx_mode (false);
|
||||
QTimer::singleShot (0, [=] {msgBox ("Runaway Tx watchdog");}); // don't block guiUpdate
|
||||
m_repeatMsg = 0;
|
||||
updateProgressBarFormat (true);
|
||||
}
|
||||
|
||||
float fTR=float((nsec%m_TRperiod))/m_TRperiod;
|
||||
// if(g_iptt==0 and ((m_bTxTime and fTR<0.4) or m_tune )) {
|
||||
if(g_iptt==0 and ((m_bTxTime and fTR<99) or m_tune )) { //### Allow late starts
|
||||
@@ -2622,7 +2667,9 @@ void MainWindow::guiUpdate()
|
||||
}
|
||||
else
|
||||
{
|
||||
msgBox("Cannot open \"" + f.fileName () + "\" for append:" + f.errorString ());
|
||||
auto const& message = tr ("Cannot open \"%1\" for append: %2")
|
||||
.arg (f.fileName ()).arg (f.errorString ());
|
||||
QTimer::singleShot (0, [=] {msgBox (message);}); // don't block guiUpdate
|
||||
}
|
||||
if (m_config.TX_messages ())
|
||||
{
|
||||
@@ -2702,18 +2749,13 @@ void MainWindow::guiUpdate()
|
||||
if (g_iptt == 1 && m_iptt0 == 0)
|
||||
{
|
||||
auto const& current_message = QString::fromLatin1 (msgsent);
|
||||
if(!m_mode.startsWith ("WSPR") && m_mode!="Echo" && m_config.watchdog ()) {
|
||||
if (current_message == m_msgSent0) {
|
||||
m_repeatMsg++;
|
||||
} else {
|
||||
if(!m_mode.startsWith ("WSPR") && m_config.watchdog () != 0) {
|
||||
if (current_message != m_msgSent0) {
|
||||
m_repeatMsg=0; // in case we are auto sequencing
|
||||
m_msgSent0 = current_message;
|
||||
}
|
||||
updateProgressBarFormat (true);
|
||||
}
|
||||
else {
|
||||
updateProgressBarFormat (false);
|
||||
}
|
||||
|
||||
if(!m_tune) {
|
||||
QFile f {m_dataDir.absoluteFilePath ("ALL.TXT")};
|
||||
@@ -2725,8 +2767,9 @@ void MainWindow::guiUpdate()
|
||||
<< ": " << m_currentMessage << endl;
|
||||
f.close();
|
||||
} else {
|
||||
msgBox("Cannot open \"" + f.fileName () + "\" for append:" +
|
||||
f.errorString ());
|
||||
auto const& message = tr ("Cannot open \"%1\" for append: %2")
|
||||
.arg (f.fileName ()).arg(f.errorString ());
|
||||
QTimer::singleShot (0, [=] {msgBox (message);}); // don't block guiUpdate
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2844,7 +2887,8 @@ void MainWindow::startTx2()
|
||||
<< m_currentMessage << " " + m_mode << endl;
|
||||
f.close();
|
||||
} else {
|
||||
msgBox("Cannot open \"" + f.fileName () + "\" for append:" + f.errorString ());
|
||||
msgBox (tr ("Cannot open \"%1\" for append: %2")
|
||||
.arg (f.fileName ()).arg (f.errorString ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2870,17 +2914,6 @@ void MainWindow::stopTx2()
|
||||
on_stopTxButton_clicked();
|
||||
m_nTx73=0;
|
||||
}
|
||||
if (!m_mode.startsWith ("WSPR") && m_mode!="Echo" && m_config.watchdog()) {
|
||||
if (m_repeatMsg >= m_watchdogLimit) {
|
||||
on_stopTxButton_clicked();
|
||||
msgBox("Runaway Tx watchdog");
|
||||
m_repeatMsg = 0;
|
||||
}
|
||||
updateProgressBarFormat (true);
|
||||
}
|
||||
else {
|
||||
updateProgressBarFormat (false);
|
||||
}
|
||||
if(m_mode.startsWith ("WSPR") and m_ntr==-1 and !m_tuneup) {
|
||||
m_wideGraph->setWSPRtransmitted();
|
||||
WSPR_scheduling ();
|
||||
@@ -4136,6 +4169,7 @@ void MainWindow::WSPR_config(bool b)
|
||||
auto_tx_label->setText (m_config.quick_call () ? "Auto-Tx-Enable Armed" : "Auto-Tx-Enable Disarmed");
|
||||
m_bSimplex = false;
|
||||
}
|
||||
auto_tx_label->setVisible (!b);
|
||||
enable_DXCC_entity (m_config.DXCC ()); // sets text window proportions and (re)inits the logbook
|
||||
}
|
||||
|
||||
@@ -5574,3 +5608,46 @@ void MainWindow::statusUpdate () const
|
||||
m_hisGrid);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::childEvent (QChildEvent * e)
|
||||
{
|
||||
if (e->child ()->isWidgetType ())
|
||||
{
|
||||
switch (e->type ())
|
||||
{
|
||||
case QEvent::ChildAdded: add_child_to_event_filter (e->child ()); break;
|
||||
case QEvent::ChildRemoved: remove_child_from_event_filter (e->child ()); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
QMainWindow::childEvent (e);
|
||||
}
|
||||
|
||||
// add widget and any child widgets to our event filter so that we can
|
||||
// take action on key press ad mouse press events anywhere in the main window
|
||||
void MainWindow::add_child_to_event_filter (QObject * target)
|
||||
{
|
||||
if (target && target->isWidgetType ())
|
||||
{
|
||||
target->installEventFilter (this);
|
||||
}
|
||||
auto const& children = target->children ();
|
||||
for (auto iter = children.begin (); iter != children.end (); ++iter)
|
||||
{
|
||||
add_child_to_event_filter (*iter);
|
||||
}
|
||||
}
|
||||
|
||||
// recursively remove widget and any child widgets from our event filter
|
||||
void MainWindow::remove_child_from_event_filter (QObject * target)
|
||||
{
|
||||
auto const& children = target->children ();
|
||||
for (auto iter = children.begin (); iter != children.end (); ++iter)
|
||||
{
|
||||
remove_child_from_event_filter (*iter);
|
||||
}
|
||||
if (target && target->isWidgetType ())
|
||||
{
|
||||
target->removeEventFilter (this);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user