JS8Call-Improved master
Loading...
Searching...
No Matches
mainwindow.h
1// -*- Mode: C++ -*-
2#ifndef MAINWINDOW_H
3#define MAINWINDOW_H
4
5#include "JS8_Audio/AudioDevice.h"
6#include "JS8_Audio/NotificationAudio.h"
7#include "JS8_Audio/SoundInput.h"
8#include "JS8_Audio/SoundOutput.h"
9#include "JS8_Include/EventFilter.h"
10#include "JS8_Include/commons.h"
11#include "JS8_Include/qpriorityqueue.h"
12#include "JS8_JSC/JSC_checker.h"
13#include "JS8_Logbook/LogBook.h"
16#include "JS8_Main/Bands.h"
17#include "JS8_Main/DirectedMessageHighlighter.h"
18#include "JS8_Main/DriftingDateTime.h"
19#include "JS8_Main/FrequencyList.h"
20#include "JS8_Main/Geodesic.h"
21#include "JS8_Main/HBBlockingDB.h"
22#include "JS8_Main/HelpTextWindow.h"
23#include "JS8_Main/Inbox.h"
24#include "JS8_Main/JS8MessageBox.h"
25#include "JS8_Main/MessageClient.h"
26#include "JS8_Main/MessageServer.h"
27#include "JS8_Main/Modes.h"
28#include "JS8_Main/MultiSettings.h"
30#include "JS8_Main/ProcessThread.h"
31#include "JS8_Main/Radio.h"
32#include "JS8_Main/SelfDestructMessageBox.h"
33#include "JS8_Main/SignalMeter.h"
34#include "JS8_Main/StationList.h"
35#include "JS8_Main/TxLoop.h"
36#include "JS8_Main/Varicode.h"
37#include "JS8_Main/qt_helpers.h"
38#include "JS8_Main/revision_utils.h"
39#include "JS8_Mode/DecodedText.h"
40#include "JS8_Mode/Decoder.h"
41#include "JS8_Mode/Detector.h"
42#include "JS8_Mode/JS8.h"
43#include "JS8_Mode/JS8Submode.h"
44#include "JS8_Mode/Modulator.h"
45#include "JS8_Network/NetworkAccessManager.h"
46#include "JS8_Network/PSKReporter.h"
47#include "JS8_Network/SpotClient.h"
48#include "JS8_Network/TCPClient.h"
49#include "JS8_Transceiver/Transceiver.h"
50#include "JS8_Transceiver/TransceiverFactory.h"
51#include "JS8_UDP/WSJTXMessageClient.h"
52#include "JS8_UDP/WSJTXMessageMapper.h"
53#include "JS8_UI/About.h"
54#include "JS8_UI/Configuration.h"
55#include "JS8_UI/WideGraph.h"
56#include "JS8_UI/MessagePanel.h"
57#include "LogQSO.h"
58#include "MessageReplyDialog.h"
59#include "styles.h"
60#include "ui_mainwindow.h"
61
62#include <QAbstractSocket>
63#include <QAction>
64#include <QActionGroup>
65#include <QApplication>
66#include <QAudioDevice>
67#include <QByteArrayView>
68#include <QCursor>
69#include <QDateTime>
70#include <QDesktopServices>
71#include <QDir>
72#include <QDockWidget>
73#include <QElapsedTimer>
74#include <QFileDialog>
75#include <QHash>
76#include <QHostAddress>
77#include <QHostInfo>
78#include <QInputDialog>
79#include <QLabel>
80#include <QLineEdit>
81#include <QList>
82#include <QLoggingCategory>
83#include <QMainWindow>
84#include <QMdiSubWindow>
85#include <QMutex>
86#include <QMutexLocker>
87#include <QNetworkAccessManager>
88#include <QNetworkReply>
89#include <QNetworkRequest>
90#include <QPair>
91#include <QPixmap>
92#include <QPointer>
93#include <QProgressBar>
94#include <QProgressDialog>
95#include <QRegularExpression>
96#include <QRegularExpressionValidator>
97#include <QScopedPointer>
98#include <QScrollBar>
99#include <QSet>
100#include <QSoundEffect>
101#include <QStandardPaths>
102#include <QStringBuilder>
103#include <QStyleFactory>
104#include <QTableWidget>
105#include <QTextEdit>
106#include <QThread>
107#include <QTime>
108#include <QTimeZone>
109#include <QTimer>
110#include <QToolTip>
111#include <QUdpSocket>
112#include <QUrl>
113#include <QVariant>
114#include <QVector>
115#include <QVersionNumber>
116#include <QtConcurrent/QtConcurrentRun>
117#include <QtGui>
118#include <boost/crc.hpp>
119#include <fftw3.h>
120
121#include <algorithm>
122#include <array>
123#include <cmath>
124#include <complex>
125#include <cstring>
126#include <functional>
127#include <iterator>
128#include <mutex>
129#include <stdexcept>
130#include <string_view>
131#include <unordered_map>
132#include <vector>
133
134Q_DECLARE_LOGGING_CATEGORY(mainwindow_js8)
135
136extern int volatile itone[JS8_NUM_SYMBOLS]; // Audio tones for all Tx symbols
137
138//--------------------------------------------------------------- mainwindow
139// How often to poll the UI, in MS.
140// Some things may depend on this being a divisor of 1000.
141constexpr quint32 UI_POLL_INTERVAL_MS = 100;
142
143namespace {
144namespace Default {
145constexpr Radio::Frequency DIAL_FREQUENCY = 14078000;
146constexpr auto FREQUENCY = 1500;
147constexpr auto SUBMODE = Varicode::JS8CallNormal;
148} // namespace Default
149
150namespace State {
151constexpr auto RX = 1;
152constexpr auto TX = 2;
153} // namespace State
154} // namespace
155
156namespace Ui {
157class UI_Constructor;
158}
159
160class QSettings;
161class QLineEdit;
162class QFont;
163class QHostInfo;
164class WideGraph;
165class LogQSO;
166class Transceiver;
167class MessageClient;
168class QTime;
169class HelpTextWindow;
170class SoundOutput;
171class Modulator;
172class SoundInput;
173class Detector;
174class AprsInboundRelay;
175class MultiSettings;
176class DecodedText;
177class JSCChecker;
178class MessagePanel;
179
180using namespace std;
181typedef std::function<void()> Callback;
182
183class WSJTXMessageMapper; // Forward declaration
184
185class UI_Constructor : public QMainWindow {
186 Q_OBJECT;
187 friend class WSJTXMessageMapper; // Allow WSJTXMessageMapper to access
188 // private members
189
190 struct CallDetail;
191 struct CommandDetail;
192
193 public:
194 using Frequency = Radio::Frequency;
195 using FrequencyDelta = Radio::FrequencyDelta;
196 using Mode = Modes::Mode;
197
198 explicit UI_Constructor(QString const &program_info,
199 QDir const &temp_directory, bool multiple,
200 MultiSettings *settings, QWidget *parent = nullptr);
202
203 private:
204 struct SortByReverse {
205 QString by;
206 bool reverse;
207 };
208
219 bool m_stopTxButtonIsLongterm;
220 bool m_hbButtonIsLongterm;
221 bool m_cqButtonIsLongterm;
222
223 public slots:
224 void showSoundInError(const QString &errorMsg);
225 void showSoundOutError(const QString &errorMsg);
226 void showStatusMessage(const QString &statusMsg);
227 void dataSink(qint64 frames);
233 void guiUpdate();
234 void setXIT(int n);
235 void qsy(int hzDelta);
236 void onDriftChanged(qint64 new_drift_ms);
237 bool tryRestoreFreqOffset();
238 void changeFreq(int);
239
240 bool hasExistingMessageBufferToMe(int *pOffset);
241 bool hasExistingMessageBuffer(int submode, int offset, bool drift,
242 int *pPrevOffset);
243 bool hasClosedExistingMessageBuffer(int offset);
244 void logCallActivity(CallDetail d, bool spot = true);
245 void logHeardGraph(QString from, QString to);
246 QString lookupCallInCompoundCache(QString const &call);
247 void cacheActivity(QString key);
248 void restoreActivity(QString key);
249 void clearActivity();
250 void clearBandActivity();
251 void clearRXActivity();
252 void clearCallActivity();
253 void createGroupCallsignTableRows(QTableWidget *table,
254 const QString &selectedCall,
255 bool &showIconColumn);
256 void displayTextForFreq(QString text, int freq, QDateTime date, bool isTx,
257 bool isNewLine, bool isLast);
258 void writeNoticeTextToUI(QDateTime date, QString text);
259 int writeMessageTextToUI(QDateTime date, QString text, int freq, bool isTx,
260 int block = -1);
261 bool isMessageQueuedForTransmit();
262 bool isInDecodeDelayThreshold(int seconds);
263 void prependMessageText(QString text);
264 void addMessageText(QString text, bool clear = false,
265 bool selectFirstPlaceholder = false);
266 void confirmThenEnqueueMessage(int timeout, int priority, QString message,
267 int offset, Callback c);
268 void enqueueMessage(int priority, QString message, int offset, Callback c);
269 void resetMessage();
270 void resetMessageUI();
271 void restoreMessage();
272 void initializeDummyData();
273 void initializeGroupMessage();
274 bool ensureCallsignSet(bool alert = true);
275 bool ensureKeyNotStuck(QString const &text);
276 bool ensureNotIdle();
277 bool ensureCanTransmit();
278 bool ensureCreateMessageReady(const QString &text);
279 QString createMessage(QString const &text, bool *pDisableTypeahead);
280 QString appendMessage(QString const &text, bool isData,
281 bool *pDisableTypeahead);
282 QString createMessageTransmitQueue(QString const &text, bool reset,
283 bool isData, bool *pDisableTypeahead);
285 QPair<QString, int> popMessageFrame();
286 void tryNotify(const QString &key);
287 void processDecodeEvent(JS8::Event::Variant const &);
288
289 void updateCQButtonDisplay();
290 void updateHBButtonDisplay();
291
292 protected:
293 void keyPressEvent(QKeyEvent *) override;
294 void closeEvent(QCloseEvent *) override;
295 void childEvent(QChildEvent *) override;
296 bool eventFilter(QObject *, QEvent *) override;
297
298 private slots:
299 void initialize_fonts();
300 void on_menuModeJS8_aboutToShow();
301 void on_menuControl_aboutToShow();
302 void on_actionCheck_for_Updates_triggered();
303 void on_actionEnable_Monitor_RX_toggled(bool checked);
304 void on_actionEnable_Transmitter_TX_toggled(bool checked);
305 void on_actionEnable_Reporting_SPOT_toggled(bool checked);
306 void on_actionEnable_Tuning_Tone_TUNE_toggled(bool checked);
307 void on_menuWindow_aboutToShow();
308 void on_actionFocus_Message_Receive_Area_triggered();
309 void on_actionFocus_Message_Reply_Area_triggered();
310 void on_actionFocus_Band_Activity_Table_triggered();
311 void on_actionFocus_Call_Activity_Table_triggered();
312 void on_actionClear_All_Activity_triggered();
313 void on_actionClear_Band_Activity_triggered();
314 void on_actionClear_RX_Activity_triggered();
315 void on_actionClear_Call_Activity_triggered();
316 void on_actionSetOffset_triggered();
317 void on_actionShow_Fullscreen_triggered(bool checked);
318 void on_actionShow_Statusbar_triggered(bool checked);
319 void on_actionShow_Frequency_Clock_triggered(bool checked);
320 void on_actionShow_Band_Activity_triggered(bool checked);
321 void on_actionShow_Band_Heartbeats_and_ACKs_triggered(bool checked);
322 void on_actionShow_Call_Activity_triggered(bool checked);
323 void on_actionShow_Waterfall_triggered(bool checked);
324 void on_actionShow_Waterfall_Controls_triggered(bool checked);
325 void on_actionShow_Waterfall_Time_Drift_Controls_triggered(bool checked);
326 void on_actionReset_Window_Sizes_triggered();
327 void on_actionSettings_triggered();
328 void openSettings(int tab = 0);
329 void prepareApi();
330 void prepareSpotting();
331 void on_spotButton_clicked(bool checked);
332 void on_monitorButton_clicked(bool);
333 void on_actionAbout_triggered();
334 void resetPushButtonToggleText(QPushButton *btn);
335 void on_stopTxButton_clicked();
336 void on_dialFreqUpButton_clicked();
337 void on_dialFreqDownButton_clicked();
338 void on_actionAdd_Log_Entry_triggered();
339 void on_actionOpen_log_directory_triggered();
340 void on_actionCopyright_Notice_triggered();
341 void on_actionUser_Guide_triggered();
342 bool decode(qint32 k);
343 bool isDecodeReady(int submode, qint32 k, qint32 k0,
344 qint32 *pCurrentDecodeStart, qint32 *pNextDecodeStart,
345 qint32 *pStart, qint32 *pSz, qint32 *pCycle);
346 bool decodeEnqueueReady(qint32 k, qint32 k0);
347 bool decodeEnqueueReadyExperiment(qint32 k, qint32 k0);
348 bool decodeProcessQueue(qint32 *pSubmode);
349 void decodeStart();
350 void decodeBusy(bool b);
351 void decodeDone();
352 void on_startTxButton_toggled(bool checked);
353 void toggleTx(bool start);
354 void on_logQSOButton_clicked();
355 void on_actionModeJS8HB_toggled(bool checked);
356 void on_actionModeJS8Normal_triggered();
357 void on_actionModeJS8Fast_triggered();
358 void on_actionModeJS8Turbo_triggered();
359 void on_actionModeJS8Slow_triggered();
360 void on_actionModeJS8Ultra_triggered();
361 void on_actionHeartbeatAcknowledgements_toggled(bool checked);
362 void on_actionModeMultiDecoder_toggled(bool checked);
363 void on_actionModeAutoreply_toggled(bool checked);
364 bool canCurrentModeSendHeartbeat() const;
365 void prepareMonitorControls();
366 void prepareHeartbeatMode(bool enabled);
367 void f11f12(int n);
368 void on_actionErase_ALL_TXT_triggered();
369 void on_actionErase_js8call_log_adi_triggered();
370 void startTx();
371 void stopTx();
372 void stopTx2();
373 void buildFrequencyMenu(QMenu *menu);
374 void buildHeartbeatMenu(QMenu *menu);
375 void buildCQMenu(QMenu *menu);
376 void buildRepeatMenu(QMenu *menu, QPushButton *button, bool isLowInterval,
377 int *interval);
378 void sendHB();
379 void sendHeartbeatAck(QString to, int snr, QString extra);
380 void on_hbMacroButton_toggled(bool checked);
381 void on_hbMacroButton_clicked();
382 void sendCQ(bool repeat = false);
383 void on_cqMacroButton_toggled(bool checked);
384 void on_cqMacroButton_clicked();
385 void on_replyMacroButton_clicked();
386 void on_snrMacroButton_clicked();
387 void on_infoMacroButton_clicked();
388 void on_statusMacroButton_clicked();
389 void setShowColumn(QString tableKey, QString columnKey, bool value);
390 bool showColumn(QString tableKey, QString columnKey, bool default_ = true);
391 void buildShowColumnsMenu(QMenu *menu, QString tableKey);
392 void setSortBy(QString key, QString value);
393 QString getSortBy(QString const &key, QString const &defaultValue) const;
394 SortByReverse getSortByReverse(QString const &key,
395 QString const &defaultValue) const;
396 void buildSortByMenu(QMenu *menu, QString key, QString defaultValue,
397 QList<QPair<QString, QString>> values);
398 void buildBandActivitySortByMenu(QMenu *menu);
399 void buildCallActivitySortByMenu(QMenu *menu);
400 void buildQueryMenu(QMenu *, QString callsign);
401 QMap<QString, QString> buildMacroValues();
402 void buildColumnLabelMap();
403 void buildSuggestionsMenu(QMenu *menu, QTextEdit *edit,
404 const QPoint &point);
405 void buildSavedMessagesMenu(QMenu *menu);
406 void buildRelayMenu(QMenu *menu);
407 QAction *buildRelayAction(QString call);
408 void buildEditMenu(QMenu *, QTextEdit *);
409 void on_queryButton_pressed();
410 void on_macrosMacroButton_pressed();
411 void on_deselectButton_pressed();
412 void on_tableWidgetRXAll_cellClicked(int row, int col);
413 void on_tableWidgetRXAll_cellDoubleClicked(int row, int col);
414 QString generateCallDetail(QString selectedCall);
415 void on_tableWidgetCalls_cellClicked(int row, int col);
416 void on_tableWidgetCalls_cellDoubleClicked(int row, int col);
417 QList<QPair<QString, int>> buildMessageFrames(QString const &text,
418 bool isData,
419 bool *pDisableTypeahead);
420 bool prepareNextMessageFrame();
421 bool isFreqOffsetFree(int f, int bw);
422 int findFreeFreqOffset(int fmin, int fmax, int bw);
423 void setDrift(int n);
424 void on_tuneButton_clicked(bool);
425 void acceptQSO(QDateTime const &, QString const &call, QString const &grid,
426 Frequency dial_freq, QString const &mode,
427 QString const &submode, QString const &rpt_sent,
428 QString const &rpt_received, QString const &comments,
429 QString const &name, QDateTime const &QSO_date_on,
430 QString const &operator_call, QString const &my_call,
431 QString const &my_grid, QByteArray const &ADIF,
432 QVariantMap const &additionalFields);
433 void on_readFreq_clicked();
434 void on_outAttenuation_valueChanged(int);
435 void rigOpen();
436 void handle_transceiver_update(Transceiver::TransceiverState const &);
437 void handle_transceiver_failure(QString const &reason);
438 void band_changed();
439 void monitor(bool);
440 void end_tuning();
441 void stop_tuning();
442 void stopTuneATU();
443 void auto_tx_mode(bool);
444 void on_monitorButton_toggled(bool checked);
445 void on_monitorTxButton_toggled(bool checked);
446 void on_tuneButton_toggled(bool checked);
447 void on_spotButton_toggled(bool checked);
448
449 void emitPTT(bool on);
450 void emitTones();
451 void udpNetworkMessage(Message const &message);
452 void tcpNetworkMessage(Message const &message);
453 void networkMessage(Message const &message);
454 bool canSendNetworkMessage();
455 void sendNetworkMessage(QString const &type, QString const &message);
456 void sendNetworkMessage(QString const &type, QString const &message,
457 const QVariantMap &params);
458 void pskReporterError(QString const &);
459 void TxAgain();
460 void checkVersion(bool alertOnUpToDate);
461 void checkStartupWarnings();
462 void clearCallsignSelected();
463 void refreshTextDisplay();
464
465 void manualBandHop(const StationList::Station station);
466
467 private:
468 Q_SIGNAL void apiSetMaxConnections(int n);
469 Q_SIGNAL void apiSetServer(QString host, quint16 port);
470 Q_SIGNAL void apiStartServer();
471 Q_SIGNAL void apiStopServer();
472
473 Q_SIGNAL void aprsClientEnqueueSpot(QString by_call, QString from_call,
474 QString grid, QString comment);
475 Q_SIGNAL void aprsClientEnqueueThirdParty(QString by_call,
476 QString from_call, QString text);
483 Q_SIGNAL void aprsClientEnqueueAck(QString from_call, QString to_call,
484 QString messageId);
485 Q_SIGNAL void aprsClientSetSkipPercent(float skipPercent);
486 Q_SIGNAL void aprsClientSetIncomingRelayEnabled(bool enabled);
487 Q_SIGNAL void aprsClientSetServer(QString host, quint16 port);
488 Q_SIGNAL void aprsClientSetPaused(bool paused);
489 Q_SIGNAL void aprsClientSetLocalStation(QString mycall, QString passcode);
490 Q_SIGNAL void aprsClientSendReports();
491
492 Q_SIGNAL void pskReporterSendReport(bool);
493 Q_SIGNAL void pskReporterSetLocalStation(QString, QString, QString);
494 Q_SIGNAL void pskReporterAddRemoteStation(QString, QString,
495 Radio::Frequency, QString, int,
496 QDateTime);
497
498 Q_SIGNAL void spotClientSetLocalStation(QString, QString, QString);
499 Q_SIGNAL void spotClientEnqueueCmd(QString, QString, QString, QString,
500 QString, QString, QString, int, int, int,
501 int);
502 Q_SIGNAL void spotClientEnqueueSpot(QString, QString, int, int, int, int);
503
504 Q_SIGNAL void decodedLineReady(QByteArray t);
505 Q_SIGNAL void playNotification(const QString &name);
506 Q_SIGNAL void initializeNotificationAudioOutputStream(const QAudioDevice &,
507 unsigned) const;
508 Q_SIGNAL void initializeAudioOutputStream(QAudioDevice, unsigned channels,
509 unsigned msBuffered) const;
510 Q_SIGNAL void stopAudioOutputStream() const;
511 Q_SIGNAL void startAudioInputStream(QAudioDevice const &,
512 int framesPerBuffer, AudioDevice *sink,
513 AudioDevice::Channel) const;
514 Q_SIGNAL void suspendAudioInputStream() const;
515 Q_SIGNAL void resumeAudioInputStream() const;
516 Q_SIGNAL void startDetector(AudioDevice::Channel) const;
517 Q_SIGNAL void FFTSize(unsigned) const;
518 Q_SIGNAL void detectorClose() const;
519 Q_SIGNAL void finished() const;
520 Q_SIGNAL void transmitFrequency(double) const;
521 Q_SIGNAL void endTransmitMessage(bool quick = false) const;
522 Q_SIGNAL void tune(bool = true) const;
523 Q_SIGNAL void sendMessage(double frequency, int submode, double txDelay,
524 SoundOutput *, AudioDevice::Channel) const;
525 Q_SIGNAL void outAttenuationChanged(qreal) const;
526 Q_SIGNAL void toggleShorthand() const;
527 Q_SIGNAL void submodeChanged(Varicode::SubmodeType) const;
528
529 Q_SIGNAL void messageAdded(int) const;
530
531 private:
532 QByteArray wisdomFileName() const;
533
534 void writeAllTxt(QStringView message);
535 void writeMsgTxt(QStringView message, int snr, int offset);
536
537 void currentTextChanged();
538 void tableSelectionChanged(QItemSelection const &, QItemSelection const &);
539 void setupJS8();
540 void applyPillSettings();
541
542 int freq() const { return m_freq; }
543
545 void refuseToSendIn30mWSPRBand();
546
547 void prepareSending(qint64 nowMS);
548
550 void updateClockUI(const QDateTime &);
551
552 void setFreq(int);
553 void transmit();
554
555 bool presentlyWantHBReplies();
556
557 QString m_nextFreeTextMsg;
558
559 NetworkAccessManager m_network_manager;
560 bool m_valid;
561 [[maybe_unused]] bool m_multiple; // Used only in Windows builds
562 MultiSettings *m_multi_settings;
563 QPushButton *m_configurations_button;
564 QSettings *m_settings;
565 bool m_settings_read;
566 QScopedPointer<Ui::UI_Constructor> ui;
567
568 // other windows
569 Configuration m_config;
570 JS8MessageBox m_rigErrorMessageBox;
571
572 QDockWidget* messageDock_ = nullptr;
573 MessagePanel* messagePanel_ = nullptr;
574 QDialog* messageFloatDialog_ = nullptr;
575
576 enum class MessageHost { Dock, Dialog };
577 MessageHost messageHost_ = MessageHost::Dock;
578
579 QScopedPointer<WideGraph> m_wideGraph;
580 QScopedPointer<LogQSO> m_logDlg;
581 QScopedPointer<HelpTextWindow> m_shortcuts;
582 QScopedPointer<HelpTextWindow> m_prefixes;
583 QScopedPointer<HelpTextWindow> m_mouseCmnds;
584
586 Frequency m_lastDialFreq;
587 QString m_lastBand;
588
589 Detector *m_detector;
590 unsigned m_FFTSize;
591 SoundInput *m_soundInput;
592 Modulator *m_modulator;
593 SoundOutput *m_soundOutput;
594 NotificationAudio *m_notification;
595
596 // Configuration might one day offer to send a txDelayChanged signal.
597 // As long as it doesn't, we poll and compare with the previous value.
598 double m_TxDelay; // in seconds.
599
600 TxLoop *m_cq_loop;
601 TxLoop *m_hb_loop;
602
603 QThread m_networkThread;
604 QThread m_audioThread;
605 QThread m_notificationAudioThread;
606 JS8::Decoder m_decoder;
607
608 qint64 m_secBandChanged;
609
610 Frequency m_freqNominal;
611 Frequency m_freqTxNominal;
612
613 int m_freq;
614
615 qint32 m_XIT;
616 qint32 m_sec0;
617 qint32 m_RxLog;
618 qint32 m_nutc0;
619 // The period of the current submode, in seconds. (15 for normal, 10 for
620 // fast, ...)
621 qint32 m_TRperiod;
622 qint32 m_inGain;
623 qint32 m_idleMinutes;
624 qint32 m_nSubMode;
625 FrequencyList_v3::const_iterator m_frequency_list_fcal_iter;
626 qint32 m_i3bit;
627
628 bool m_btxok; // True if OK to transmit
629 bool m_decoderBusy;
630 QString m_decoderBusyBand;
631 QMap<qint32, qint32>
632 m_lastDecodeStartMap; // submode, decode k start position
633 QMap<qint32, qint32>
634 m_lastDecodeCycleMap; // JS8 40 & JS8 60 submodes, last enqueued cycle start
635 Radio::Frequency m_decoderBusyFreq;
636 QDateTime m_decoderBusyStartTime;
637 bool m_auto;
638 bool m_restart;
639 bool m_bDecoded;
640 int m_currentMessageType;
641 QString m_currentMessage;
642 int m_currentMessageBits;
643 int m_lastMessageType;
644 QString m_lastMessageSent;
645 bool m_tuneup;
646 bool m_isTimeToSend;
647
648 int m_ihsym;
649 float m_px;
650 float m_pxmax;
651 float m_df3;
652 quint32 m_iptt = 0;
653 quint32 m_iptt0;
654 bool m_btxok0;
655 double m_onAirFreq0;
656 bool m_first_error;
657
658 char m_msg[100][80];
659
660 // labels and widgets in status and header bar
661 QLabel tx_status_label;
662 QLabel config_label;
663 QLabel mode_label;
664 QLabel frequency_label;
665 QLabel auto_reply_label;
666 QLabel last_tx_label;
667 QLabel auto_tx_label;
668 QProgressBar progressBar;
669 QLabel wpm_label;
670 Styles::OffsetSliderWidget *freqOffsetWidget = nullptr;
671 int m_sliderFreqBeforeHB = 0;
672
673 // QPointer<QProcess> proc_js8;
674
675 QTimer m_guiTimer;
676 // Timer to switch off PTT after end of transmission.
677 QTimer pttReleaseTimer;
678 QTimer logQSOTimer;
679 QTimer tuneButtonTimer;
680 QTimer tuneATU_Timer;
681 QTimer TxAgainTimer;
682 QTimer minuteTimer;
683 QString m_baseCall;
684 QString m_hisCall;
685 QString m_hisGrid;
686 QString m_appDir;
687 QString m_palette;
688 QString m_rptSent;
689 QString m_rptRcvd;
690 QString m_msgSent0;
691 QString m_opCall;
692
693 struct CallDetail {
694 QString call;
695 QString through;
696 QString grid;
697 int dial;
698 int offset;
699 QDateTime cqTimestamp;
700 QDateTime ackTimestamp;
701 QDateTime utcTimestamp;
702 int snr;
703 int bits;
704 float tdrift;
705 int submode;
706 };
707
708 struct CommandDetail {
709 bool isCompound;
710 bool isBuffered;
711 QString from;
712 QString to;
713 QString cmd;
714 int dial;
715 int offset;
716 QDateTime utcTimestamp;
717 int snr;
718 int bits;
719 QString grid;
720 QString text;
721 QString extra;
722 float tdrift;
723 int submode;
724 QString relayPath;
725 };
726
727 struct ActivityDetail {
728 bool isLowConfidence;
729 bool isCompound;
730 bool isDirected;
731 bool isBuffered;
732 int bits;
733 int dial;
734 int offset;
735 QString text;
736 QDateTime utcTimestamp;
737 int snr;
738 bool shouldDisplay;
739 float tdrift;
740 int submode;
741 };
742
743 struct MessageBuffer {
744 CommandDetail cmd;
745 QQueue<CallDetail> compound;
747 };
748
749 QString m_prevSelectedCallsign;
750 int m_bandActivityWidth;
751 int m_callActivityWidth;
752 int m_textActivityWidth;
753 int m_waterfallHeight;
754 bool m_bandActivityWasVisible;
755 bool m_rxDirty;
756 bool m_rxDisplayDirty;
757 int m_txFrameCountEstimate;
758 int m_txFrameCount;
759 int m_txFrameCountSent;
760 QTimer m_txTextDirtyDebounce;
761 bool m_txTextDirty;
762 QString m_txTextDirtyLastText;
763 QString m_txTextDirtyLastSelectedCall;
764 QString m_lastTxMessage;
765 QString m_totalTxMessage;
766
767 // moved from mainwindow.cpp, is used in multiple functions
768 QString since(QDateTime const &time) {
769 auto const delta = time.secsTo(DriftingDateTime::currentDateTimeUtc());
770
771 if (delta >= 60 * 60 * 24)
772 return QString("%1d").arg(delta / (60 * 60 * 24));
773 else if (delta >= 60 * 60)
774 return QString("%1h").arg(delta / (60 * 60));
775 else if (delta >= 60)
776 return QString("%1m").arg(delta / (60));
777 else if (delta >= 15)
778 return QString("%1s").arg(delta - (delta % 15));
779 else
780 return QString("now");
781 }
782
783 QDateTime m_lastTxStartTime;
784 QDateTime m_lastTxStopTime;
785 qint32 m_driftMsMMA;
786 qint32 m_driftMsMMA_N;
787
788 // moved from mainwindow.cpp, is used in multiple functions
789 auto replaceMacros(QString const &text,
790 QMap<QString, QString> const &values, bool const prune) {
791 QString output = text;
792
793 for (auto const [key, value] : values.asKeyValueRange()) {
794 output = output.replace(key, value.toUpper());
795 }
796
797 return prune ? output.replace(QRegularExpression("[<](?:[^>]+)[>]"), "")
798 : output;
799 }
800
801 QList<int> generateOffsets(int minOffset, int maxOffset) {
802 QList<int> offsets;
803
804 // TODO: these offsets aren't ordered correctly...
805
806 for (int i = minOffset; i <= maxOffset; i++) {
807 offsets.append(i);
808 }
809 return offsets;
810 }
811
812 enum Priority {
813 PriorityLow = 10,
814 PriorityNormal = 100,
815 PriorityHigh = 1000
816 };
817
818 struct PrioritizedMessage {
819 QDateTime date;
820 int priority;
821 QString message;
822 int offset;
823 Callback callback;
824
825 friend bool operator<(PrioritizedMessage const &a,
826 PrioritizedMessage const &b) {
827 if (a.priority < b.priority) {
828 return true;
829 }
830 return a.date < b.date;
831 }
832 };
833
834 struct CachedDirectedType {
835 bool isAllcall;
836 QDateTime date;
837 };
838
839 struct DecodeParams {
840 int submode;
841 int start;
842 int sz;
843 };
844
845 struct FrameCacheKey {
846 int submode;
847 QString frame;
848
849 FrameCacheKey(int submode, QString frame)
850 : submode(submode), frame(std::move(frame)) {}
851
852 bool operator==(FrameCacheKey const &) const noexcept = default;
853
854 struct Hash {
855 std::size_t operator()(FrameCacheKey const &key) const noexcept {
856 std::size_t const h1 = std::hash<int>{}(key.submode);
857 std::size_t const h2 = qHash(key.frame);
858 return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
859 }
860 };
861 };
862
863 using FrameCache =
864 std::unordered_map<FrameCacheKey, QDateTime, FrameCacheKey::Hash>;
865 using BandActivity = QMap<int, QList<ActivityDetail>>;
866
867 QQueue<DecodeParams> m_decoderQueue;
868 FrameCache m_messageDupeCache; // submode, frame -> date seen
869 QVariantMap m_showColumnsCache; // table column:key -> show boolean
870 QVariantMap m_sortCache; // table key -> sort by
871 QPriorityQueue<PrioritizedMessage> m_txMessageQueue; // messages to be sent
872 QQueue<QPair<QString, int>> m_txFrameQueue; // frames to be sent
873 QQueue<ActivityDetail> m_rxActivityQueue; // all rx activity queue
874 QQueue<CommandDetail>
875 m_rxCommandQueue; // command queue for processing commands
876 QQueue<CallDetail>
877 m_rxCallQueue; // call detail queue for spots to pskreporter
878 QMap<QString, QString>
879 m_compoundCallCache; // base callsign -> compound callsign
880 QCache<QString, QDateTime> m_txAllcallCommandCache; // callsign -> last tx
881 QCache<int, QDateTime> m_rxRecentCache; // freq -> last rx
882 QCache<int, CachedDirectedType>
883 m_rxDirectedCache; // freq -> last directed rx
884 QCache<QString, int> m_rxCallCache; // call -> last freq seen
885 QMap<int, int> m_rxFrameBlockNumbers; // freq -> block
886 BandActivity m_bandActivity; // freq -> [(text, last timestamp), ...]
887 QMap<int, MessageBuffer> m_messageBuffer; // freq -> (cmd, [frames, ...])
888 int m_lastClosedMessageBufferOffset;
889 QMap<QString, CallDetail>
890 m_callActivity; // call -> (last freq, last timestamp)
891
892 QMap<int, QString> m_origRxHeaderLabelMap; // colIndex, label
893 QMap<int, QString> m_origCallActivityHeaderLabelMap; // colIndex, label
894 QMap<QString, QString> m_columnLabelMap; // full, minimal
895
896 QMap<QString, QSet<QString>>
897 m_heardGraphOutgoing; // callsign -> [stations who've this callsign has
898 // heard]
899 QMap<QString, QSet<QString>>
900 m_heardGraphIncoming; // callsign -> [stations who've heard this
901 // callsign]
902
903 QMap<QString, int> m_rxInboxCountCache; // call -> count
904
905 QMap<QString, QMap<QString, CallDetail>>
906 m_callActivityBandCache; // band -> call activity
907 QMap<QString, QMap<int, QList<ActivityDetail>>>
908 m_bandActivityBandCache; // band -> band activity
909 QMap<QString, QString> m_rxTextBandCache; // band -> rx text
910 QMap<QString, QMap<QString, QSet<QString>>>
911 m_heardGraphOutgoingBandCache; // band -> heard in
912 QMap<QString, QMap<QString, QSet<QString>>>
913 m_heardGraphIncomingBandCache; // band -> heard out
914
915 // Pending autoreply confirmations (TCP-based, remplace Qt dialog en headless)
916 struct PendingConfirmation {
917 int id;
918 int priority;
919 QString message;
920 int offset;
921 Callback callback;
922 QTimer *timer;
923 };
924 int m_nextConfirmId = 0;
925 QMap<int, PendingConfirmation> m_pendingConfirmations;
926
927 QMap<QString, QDateTime>
928 m_callSelectedTime; // call -> timestamp when callsign was last selected
933 QHash<QString, QDateTime> m_aprsRelayDedupCache;
934 QSet<QString> m_callSeenHeartbeat; // call
935 bool m_bandHopped;
936 Frequency m_bandHoppedFreq;
937
939 int m_hbInterval;
941 int m_cqInterval;
942
944 bool m_hbPaused;
945
946 QDateTime m_dateTimeQSOOn;
947 QDateTime m_dateTimeLastTX;
948
949 QSet<int> m_rxBlockedOffsets; //callsign blocking
950
951 LogBook m_logBook;
952 unsigned m_msAudioOutputBuffered;
953 unsigned m_framesAudioInputBuffered;
954 QThread::Priority m_audioThreadPriority;
955 QThread::Priority m_notificationAudioThreadPriority;
956 QThread::Priority m_decoderThreadPriority;
957 QThread::Priority m_networkThreadPriority;
958 bool m_splitMode;
959 bool m_monitoring;
960 bool m_generateAudioWhenPttConfirmedByTX;
961 bool m_transmitting;
962 bool m_tune;
963 bool m_tx_watchdog; // true when watchdog triggered
964 bool m_block_pwr_tooltip;
965 bool m_PwrBandSetOK;
966 Frequency m_lastMonitoredFrequency;
967 MessageClient *m_messageClient;
968 MessageServer *m_messageServer;
969 WSJTXMessageClient *m_wsjtxMessageClient;
970 WSJTXMessageMapper *m_wsjtxMessageMapper;
971 TCPClient *m_n3fjpClient;
972 PSKReporter *m_pskReporter;
973 SpotClient *m_spotClient;
974 APRSISClient *m_aprsClient;
975 AprsInboundRelay *m_aprsInboundRelay;
976 QVariantHash m_pwrBandTxMemory; // Remembers power level by band
977 QVariantHash
978 m_pwrBandTuneMemory; // Remembers power level by band for tuning
979 QByteArray m_geometryNoControls;
980
981 //---------------------------------------------------- private functions
982 void readSettings();
983 void set_application_font(QFont const &);
984 void writeSettings();
985 void createStatusBar();
986 void statusChanged();
987 void rigFailure(QString const &reason);
988 void spotSetLocal();
989 void pskSetLocal();
990 void aprsSetLocal();
991 void spotReport(int submode, int dial, int offset, int snr,
992 QString const &callsign, QString const &grid);
993 void spotCmd(CommandDetail const &cmd);
994 void spotAprsCmd(CommandDetail const &cmd);
995 void pskLogReport(QString const &mode, int dial, int offset, int snr,
996 QString const &callsign, QString const &grid,
997 QDateTime const &utcTimestamp);
998 void spotAprsGrid(int dial, int offset, int snr, QString callsign,
999 QString grid);
1000 Radio::Frequency dialFrequency();
1001 void setSubmode(int submode);
1002 void updateCurrentBand();
1003 void displayDialFrequency();
1004 void transmitDisplay(bool);
1005 void postDecode(bool is_new, QString const &message);
1006 void displayTransmit();
1007 void updateModeButtonText();
1008 void updateButtonDisplay();
1009 void updateTextDisplay();
1010 void updateTextWordCheckerDisplay();
1011 void updateTextStatsDisplay(QString text, int count);
1012 void updateTxButtonDisplay();
1013 bool isMyCallIncluded(QString const &text);
1014 bool isAllCallIncluded(QString const &text);
1015 bool isGroupCallIncluded(const QString &text);
1016 QString callsignSelected(bool useInputText = false);
1017 void callsignSelectedChanged(QString old, QString current);
1018 bool isRecentOffset(int submode, int offset);
1019 void markOffsetRecent(int offset);
1020 bool isDirectedOffset(int offset, bool *pIsAllCall);
1021 void markOffsetDirected(int offset, bool isAllCall);
1022 void clearOffsetDirected(int offset);
1023 void processActivity(bool force = false);
1024 void resetTimeDeltaAverage();
1025 void processRxActivity();
1026 void processIdleActivity();
1027 void processCompoundActivity();
1028 void processBufferedActivity();
1029 void processCommandActivity();
1030 void processHeartbeatRateLimit(const QString &callsign);
1031 QString inboxPath();
1032 QString hbBlockingPath() const;
1033 void refreshInboxCounts();
1034 bool hasMessageHistory(QString call);
1035 int addCommandToMyInbox(CommandDetail d);
1036 int addCommandToStorage(QString type, CommandDetail d);
1037 int getNextMessageIdForCallsign(QString callsign);
1038 int getLookaheadMessageIdForCallsign(QString callsign, int afterMsgId);
1039 int getNextGroupMessageIdForCallsign(QString group_name, QString callsign);
1040 int getLookaheadGroupMessageIdForCallsign(QString group_name,
1041 QString callsign, int afterMsgId);
1042 int countUnreadForCallsign(const QString &callsign);
1043 int countGroupUnreadForCallsign(const QString &group_name,
1044 const QString &callsign);
1045 bool markGroupMsgDeliveredForCallsign(int msgId, QString callsign);
1046 bool markMsgDelivered(int mid, Message msg);
1047 QStringList parseRelayPathCallsigns(QString from, QString text);
1048 void processSpots();
1049 void processTxQueue();
1050 void displayActivity(bool force = false);
1051 void displayBandActivity();
1052 void displayCallActivity();
1053 void enable_DXCC_entity(bool on);
1054 void setRig(Frequency = 0); // zero frequency means no change
1055 QDateTime nextTransmitCycle();
1056 void statusUpdate();
1057 void on_the_minute();
1058 void tryBandHop();
1059 void add_child_to_event_filter(QObject *);
1060 void remove_child_from_event_filter(QObject *);
1061 void setup_status_bar();
1062 QString columnLabel(QString defaultLabel);
1063 void ensureMessageDock();
1064
1065 void resetIdleTimer();
1066 void incrementIdleTimer();
1067 void tx_watchdog(bool triggered);
1068 void write_frequency_entry(QString const &file_name);
1069 void write_transmit_entry(QString const &file_name);
1070};
1071
1072#endif // MAINWINDOW_H
APRS-IS client interface for JS8Call.
Defines the inbound APRS-IS relay handler for JS8Call.
Pill-shaped visual highlights for directed message tokens.
Definition ADIF.h:18
APRS-IS client responsible for sending and receiving APRS frames.
Definition APRSISClient.h:21
Handles inbound APRS-IS messages and enqueues JS8 relays.
Definition AprsInboundRelay.h:20
Definition AudioDevice.h:11
Definition Configuration.h:57
Definition DecodedText.h:16
Definition Detector.h:15
Definition FrequencyList.h:67
Definition HelpTextWindow.h:9
Definition JS8MessageBox.h:13
Definition JS8.h:86
Definition JSC_checker.h:12
Definition LogBook.h:19
Definition LogQSO.h:22
Definition MessageClient.h:21
Definition MessagePanel.h:12
Definition MessageServer.h:14
Definition Message.h:16
Definition Modulator.h:20
Definition MultiSettings.h:62
Definition NetworkAccessManager.h:18
Definition NotificationAudio.h:15
Definition PSKReporter.h:13
Definition qpriorityqueue.h:39
Definition qpriorityqueue.h:72
Definition SoundInput.h:16
Definition SoundOutput.h:13
Definition SpotClient.h:9
Definition styles.h:713
Definition TCPClient.h:9
Definition Transceiver.h:83
Definition Transceiver.h:50
Definition TxLoop.h:10
void dataSink(qint64 frames)
Definition dataSink.cpp:79
void guiUpdate()
Definition mainwindow.cpp:2686
void resetMessageTransmitQueue()
Resets the frame-level transmission state after a message completes.
Definition mainwindow.cpp:3539
UI_Constructor(QString const &program_info, QDir const &temp_directory, bool multiple, MultiSettings *settings, QWidget *parent=nullptr)
Definition UI_Constructor.cpp:20
void processDecodeEvent(JS8::Event::Variant const &)
Definition processDecodeEvent.cpp:10
Definition WSJTXMessageClient.h:17
Maps JS8Call events to WSJT-X protocol messages.
Definition WSJTXMessageMapper.h:21
Definition WideGraph.h:29
Definition StationList.h:50
Definition mainwindow.h:854
header file that defines platform specific label, button, widget and dialog styles used in functions ...