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/HelpTextWindow.h"
22#include "JS8_Main/Inbox.h"
23#include "JS8_Main/JS8MessageBox.h"
24#include "JS8_Main/MessageClient.h"
25#include "JS8_Main/MessageServer.h"
26#include "JS8_Main/Modes.h"
27#include "JS8_Main/MultiSettings.h"
29#include "JS8_Main/ProcessThread.h"
30#include "JS8_Main/Radio.h"
31#include "JS8_Main/SelfDestructMessageBox.h"
32#include "JS8_Main/SignalMeter.h"
33#include "JS8_Main/StationList.h"
34#include "JS8_Main/TxLoop.h"
35#include "JS8_Main/Varicode.h"
36#include "JS8_Main/qt_helpers.h"
37#include "JS8_Main/revision_utils.h"
38#include "JS8_Mode/DecodedText.h"
39#include "JS8_Mode/Decoder.h"
40#include "JS8_Mode/Detector.h"
41#include "JS8_Mode/JS8.h"
42#include "JS8_Mode/JS8Submode.h"
43#include "JS8_Mode/Modulator.h"
44#include "JS8_Network/NetworkAccessManager.h"
45#include "JS8_Network/PSKReporter.h"
46#include "JS8_Network/SpotClient.h"
47#include "JS8_Network/TCPClient.h"
48#include "JS8_Transceiver/Transceiver.h"
49#include "JS8_Transceiver/TransceiverFactory.h"
50#include "JS8_UDP/WSJTXMessageClient.h"
51#include "JS8_UDP/WSJTXMessageMapper.h"
52#include "JS8_UI/About.h"
53#include "JS8_UI/Configuration.h"
54#include "JS8_UI/WideGraph.h"
55#include "JS8_UI/MessagePanel.h"
56#include "LogQSO.h"
57#include "MessageReplyDialog.h"
58#include "styles.h"
59#include "ui_mainwindow.h"
60
61#include <QAbstractSocket>
62#include <QAction>
63#include <QActionGroup>
64#include <QApplication>
65#include <QAudioDevice>
66#include <QByteArrayView>
67#include <QCursor>
68#include <QDateTime>
69#include <QDesktopServices>
70#include <QDir>
71#include <QDockWidget>
72#include <QElapsedTimer>
73#include <QFileDialog>
74#include <QHash>
75#include <QHostAddress>
76#include <QHostInfo>
77#include <QInputDialog>
78#include <QLabel>
79#include <QLineEdit>
80#include <QList>
81#include <QLoggingCategory>
82#include <QMainWindow>
83#include <QMdiSubWindow>
84#include <QMutex>
85#include <QMutexLocker>
86#include <QNetworkAccessManager>
87#include <QNetworkReply>
88#include <QNetworkRequest>
89#include <QPair>
90#include <QPixmap>
91#include <QPointer>
92#include <QProgressBar>
93#include <QProgressDialog>
94#include <QRegularExpression>
95#include <QRegularExpressionValidator>
96#include <QScopedPointer>
97#include <QScrollBar>
98#include <QSet>
99#include <QSoundEffect>
100#include <QStandardPaths>
101#include <QStringBuilder>
102#include <QStyleFactory>
103#include <QTableWidget>
104#include <QTextEdit>
105#include <QThread>
106#include <QTime>
107#include <QTimeZone>
108#include <QTimer>
109#include <QToolTip>
110#include <QUdpSocket>
111#include <QUrl>
112#include <QVariant>
113#include <QVector>
114#include <QVersionNumber>
115#include <QtConcurrent/QtConcurrentRun>
116#include <QtGui>
117#include <boost/crc.hpp>
118#include <fftw3.h>
119
120#include <algorithm>
121#include <array>
122#include <cmath>
123#include <complex>
124#include <cstring>
125#include <functional>
126#include <iterator>
127#include <mutex>
128#include <stdexcept>
129#include <string_view>
130#include <unordered_map>
131#include <vector>
132
133Q_DECLARE_LOGGING_CATEGORY(mainwindow_js8)
134
135extern int volatile itone[JS8_NUM_SYMBOLS]; // Audio tones for all Tx symbols
136
137//--------------------------------------------------------------- mainwindow
138// How often to poll the UI, in MS.
139// Some things may depend on this being a divisor of 1000.
140constexpr quint32 UI_POLL_INTERVAL_MS = 100;
141
142namespace {
143namespace Default {
144constexpr Radio::Frequency DIAL_FREQUENCY = 14078000;
145constexpr auto FREQUENCY = 1500;
146constexpr auto SUBMODE = Varicode::JS8CallNormal;
147} // namespace Default
148
149namespace State {
150constexpr auto RX = 1;
151constexpr auto TX = 2;
152} // namespace State
153} // namespace
154
155namespace Ui {
156class UI_Constructor;
157}
158
159class QSettings;
160class QLineEdit;
161class QFont;
162class QHostInfo;
163class WideGraph;
164class LogQSO;
165class Transceiver;
166class MessageClient;
167class QTime;
168class HelpTextWindow;
169class SoundOutput;
170class Modulator;
171class SoundInput;
172class Detector;
173class AprsInboundRelay;
174class MultiSettings;
175class DecodedText;
176class JSCChecker;
177class MessagePanel;
178
179using namespace std;
180typedef std::function<void()> Callback;
181
182class WSJTXMessageMapper; // Forward declaration
183
184class UI_Constructor : public QMainWindow {
185 Q_OBJECT;
186 friend class WSJTXMessageMapper; // Allow WSJTXMessageMapper to access
187 // private members
188
189 struct CallDetail;
190 struct CommandDetail;
191
192 public:
193 using Frequency = Radio::Frequency;
194 using FrequencyDelta = Radio::FrequencyDelta;
195 using Mode = Modes::Mode;
196
197 explicit UI_Constructor(QString const &program_info,
198 QDir const &temp_directory, bool multiple,
199 MultiSettings *settings, QWidget *parent = nullptr);
201
202 private:
203 struct SortByReverse {
204 QString by;
205 bool reverse;
206 };
207
218 bool m_stopTxButtonIsLongterm;
219 bool m_hbButtonIsLongterm;
220 bool m_cqButtonIsLongterm;
221
222 public slots:
223 void showSoundInError(const QString &errorMsg);
224 void showSoundOutError(const QString &errorMsg);
225 void showStatusMessage(const QString &statusMsg);
226 void dataSink(qint64 frames);
232 void guiUpdate();
233 void setXIT(int n);
234 void qsy(int hzDelta);
235 void onDriftChanged(qint64 new_drift_ms);
236 void setFreqOffsetForRestore(int freq, bool shouldRestore);
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 in status 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 // MacOS frequency slider widget
671#if defined(Q_OS_MACOS)
672 Styles::OffsetSliderWidget *freqOffsetWidget = nullptr;
673 int m_sliderFreqBeforeHB = 0;
674#endif
675
676 // QPointer<QProcess> proc_js8;
677
678 QTimer m_guiTimer;
679 // Timer to switch off PTT after end of transmission.
680 QTimer pttReleaseTimer;
681 QTimer logQSOTimer;
682 QTimer tuneButtonTimer;
683 QTimer tuneATU_Timer;
684 QTimer TxAgainTimer;
685 QTimer minuteTimer;
686 QString m_baseCall;
687 QString m_hisCall;
688 QString m_hisGrid;
689 QString m_appDir;
690 QString m_palette;
691 QString m_rptSent;
692 QString m_rptRcvd;
693 QString m_msgSent0;
694 QString m_opCall;
695
696 struct CallDetail {
697 QString call;
698 QString through;
699 QString grid;
700 int dial;
701 int offset;
702 QDateTime cqTimestamp;
703 QDateTime ackTimestamp;
704 QDateTime utcTimestamp;
705 int snr;
706 int bits;
707 float tdrift;
708 int submode;
709 };
710
711 struct CommandDetail {
712 bool isCompound;
713 bool isBuffered;
714 QString from;
715 QString to;
716 QString cmd;
717 int dial;
718 int offset;
719 QDateTime utcTimestamp;
720 int snr;
721 int bits;
722 QString grid;
723 QString text;
724 QString extra;
725 float tdrift;
726 int submode;
727 QString relayPath;
728 };
729
730 struct ActivityDetail {
731 bool isLowConfidence;
732 bool isCompound;
733 bool isDirected;
734 bool isBuffered;
735 int bits;
736 int dial;
737 int offset;
738 QString text;
739 QDateTime utcTimestamp;
740 int snr;
741 bool shouldDisplay;
742 float tdrift;
743 int submode;
744 };
745
746 struct MessageBuffer {
747 CommandDetail cmd;
748 QQueue<CallDetail> compound;
750 };
751
752 QString m_prevSelectedCallsign;
753 int m_bandActivityWidth;
754 int m_callActivityWidth;
755 int m_textActivityWidth;
756 int m_waterfallHeight;
757 bool m_bandActivityWasVisible;
758 bool m_rxDirty;
759 bool m_rxDisplayDirty;
760 int m_txFrameCountEstimate;
761 int m_txFrameCount;
762 int m_txFrameCountSent;
763 QTimer m_txTextDirtyDebounce;
764 bool m_txTextDirty;
765 QString m_txTextDirtyLastText;
766 QString m_txTextDirtyLastSelectedCall;
767 QString m_lastTxMessage;
768 QString m_totalTxMessage;
769
770 // moved from mainwindow.cpp, is used in multiple functions
771 QString since(QDateTime const &time) {
772 auto const delta = time.secsTo(DriftingDateTime::currentDateTimeUtc());
773
774 if (delta >= 60 * 60 * 24)
775 return QString("%1d").arg(delta / (60 * 60 * 24));
776 else if (delta >= 60 * 60)
777 return QString("%1h").arg(delta / (60 * 60));
778 else if (delta >= 60)
779 return QString("%1m").arg(delta / (60));
780 else if (delta >= 15)
781 return QString("%1s").arg(delta - (delta % 15));
782 else
783 return QString("now");
784 }
785
786 QDateTime m_lastTxStartTime;
787 QDateTime m_lastTxStopTime;
788 qint32 m_driftMsMMA;
789 qint32 m_driftMsMMA_N;
790
791 // moved from mainwindow.cpp, is used in multiple functions
792 auto replaceMacros(QString const &text,
793 QMap<QString, QString> const &values, bool const prune) {
794 QString output = text;
795
796 for (auto const [key, value] : values.asKeyValueRange()) {
797 output = output.replace(key, value.toUpper());
798 }
799
800 return prune ? output.replace(QRegularExpression("[<](?:[^>]+)[>]"), "")
801 : output;
802 }
803
804 QList<int> generateOffsets(int minOffset, int maxOffset) {
805 QList<int> offsets;
806
807 // TODO: these offsets aren't ordered correctly...
808
809 for (int i = minOffset; i <= maxOffset; i++) {
810 offsets.append(i);
811 }
812 return offsets;
813 }
814
815 enum Priority {
816 PriorityLow = 10,
817 PriorityNormal = 100,
818 PriorityHigh = 1000
819 };
820
821 struct PrioritizedMessage {
822 QDateTime date;
823 int priority;
824 QString message;
825 int offset;
826 Callback callback;
827
828 friend bool operator<(PrioritizedMessage const &a,
829 PrioritizedMessage const &b) {
830 if (a.priority < b.priority) {
831 return true;
832 }
833 return a.date < b.date;
834 }
835 };
836
837 struct CachedDirectedType {
838 bool isAllcall;
839 QDateTime date;
840 };
841
842 struct DecodeParams {
843 int submode;
844 int start;
845 int sz;
846 };
847
848 struct FrameCacheKey {
849 int submode;
850 QString frame;
851
852 FrameCacheKey(int submode, QString frame)
853 : submode(submode), frame(std::move(frame)) {}
854
855 bool operator==(FrameCacheKey const &) const noexcept = default;
856
857 struct Hash {
858 std::size_t operator()(FrameCacheKey const &key) const noexcept {
859 std::size_t const h1 = std::hash<int>{}(key.submode);
860 std::size_t const h2 = qHash(key.frame);
861 return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
862 }
863 };
864 };
865
866 using FrameCache =
867 std::unordered_map<FrameCacheKey, QDateTime, FrameCacheKey::Hash>;
868 using BandActivity = QMap<int, QList<ActivityDetail>>;
869
870 QQueue<DecodeParams> m_decoderQueue;
871 FrameCache m_messageDupeCache; // submode, frame -> date seen
872 QVariantMap m_showColumnsCache; // table column:key -> show boolean
873 QVariantMap m_sortCache; // table key -> sort by
874 QPriorityQueue<PrioritizedMessage> m_txMessageQueue; // messages to be sent
875 QQueue<QPair<QString, int>> m_txFrameQueue; // frames to be sent
876 QQueue<ActivityDetail> m_rxActivityQueue; // all rx activity queue
877 QQueue<CommandDetail>
878 m_rxCommandQueue; // command queue for processing commands
879 QQueue<CallDetail>
880 m_rxCallQueue; // call detail queue for spots to pskreporter
881 QMap<QString, QString>
882 m_compoundCallCache; // base callsign -> compound callsign
883 QCache<QString, QDateTime> m_txAllcallCommandCache; // callsign -> last tx
884 QCache<int, QDateTime> m_rxRecentCache; // freq -> last rx
885 QCache<int, CachedDirectedType>
886 m_rxDirectedCache; // freq -> last directed rx
887 QCache<QString, int> m_rxCallCache; // call -> last freq seen
888 QMap<int, int> m_rxFrameBlockNumbers; // freq -> block
889 BandActivity m_bandActivity; // freq -> [(text, last timestamp), ...]
890 QMap<int, MessageBuffer> m_messageBuffer; // freq -> (cmd, [frames, ...])
891 int m_lastClosedMessageBufferOffset;
892 QMap<QString, CallDetail>
893 m_callActivity; // call -> (last freq, last timestamp)
894
895 QMap<int, QString> m_origRxHeaderLabelMap; // colIndex, label
896 QMap<int, QString> m_origCallActivityHeaderLabelMap; // colIndex, label
897 QMap<QString, QString> m_columnLabelMap; // full, minimal
898
899 QMap<QString, QSet<QString>>
900 m_heardGraphOutgoing; // callsign -> [stations who've this callsign has
901 // heard]
902 QMap<QString, QSet<QString>>
903 m_heardGraphIncoming; // callsign -> [stations who've heard this
904 // callsign]
905
906 QMap<QString, int> m_rxInboxCountCache; // call -> count
907
908 QMap<QString, QMap<QString, CallDetail>>
909 m_callActivityBandCache; // band -> call activity
910 QMap<QString, QMap<int, QList<ActivityDetail>>>
911 m_bandActivityBandCache; // band -> band activity
912 QMap<QString, QString> m_rxTextBandCache; // band -> rx text
913 QMap<QString, QMap<QString, QSet<QString>>>
914 m_heardGraphOutgoingBandCache; // band -> heard in
915 QMap<QString, QMap<QString, QSet<QString>>>
916 m_heardGraphIncomingBandCache; // band -> heard out
917
918 // Pending autoreply confirmations (TCP-based, remplace Qt dialog en headless)
919 struct PendingConfirmation {
920 int id;
921 int priority;
922 QString message;
923 int offset;
924 Callback callback;
925 QTimer *timer;
926 };
927 int m_nextConfirmId = 0;
928 QMap<int, PendingConfirmation> m_pendingConfirmations;
929
930 QMap<QString, QDateTime>
931 m_callSelectedTime; // call -> timestamp when callsign was last selected
936 QHash<QString, QDateTime> m_aprsRelayDedupCache;
937 QSet<QString> m_callSeenHeartbeat; // call
938 int m_previousFreq;
939 bool m_shouldRestoreFreq;
940 bool m_bandHopped;
941 Frequency m_bandHoppedFreq;
942
944 int m_hbInterval;
946 int m_cqInterval;
947
949 bool m_hbPaused;
950
951 QDateTime m_dateTimeQSOOn;
952 QDateTime m_dateTimeLastTX;
953
954 LogBook m_logBook;
955 unsigned m_msAudioOutputBuffered;
956 unsigned m_framesAudioInputBuffered;
957 QThread::Priority m_audioThreadPriority;
958 QThread::Priority m_notificationAudioThreadPriority;
959 QThread::Priority m_decoderThreadPriority;
960 QThread::Priority m_networkThreadPriority;
961 bool m_splitMode;
962 bool m_monitoring;
963 bool m_generateAudioWhenPttConfirmedByTX;
964 bool m_transmitting;
965 bool m_tune;
966 bool m_tx_watchdog; // true when watchdog triggered
967 bool m_block_pwr_tooltip;
968 bool m_PwrBandSetOK;
969 Frequency m_lastMonitoredFrequency;
970 MessageClient *m_messageClient;
971 MessageServer *m_messageServer;
972 WSJTXMessageClient *m_wsjtxMessageClient;
973 WSJTXMessageMapper *m_wsjtxMessageMapper;
974 TCPClient *m_n3fjpClient;
975 PSKReporter *m_pskReporter;
976 SpotClient *m_spotClient;
977 APRSISClient *m_aprsClient;
978 AprsInboundRelay *m_aprsInboundRelay;
979 QVariantHash m_pwrBandTxMemory; // Remembers power level by band
980 QVariantHash
981 m_pwrBandTuneMemory; // Remembers power level by band for tuning
982 QByteArray m_geometryNoControls;
983
984 //---------------------------------------------------- private functions
985 void readSettings();
986 void set_application_font(QFont const &);
987 void writeSettings();
988 void createStatusBar();
989 void statusChanged();
990 void rigFailure(QString const &reason);
991 void spotSetLocal();
992 void pskSetLocal();
993 void aprsSetLocal();
994 void spotReport(int submode, int dial, int offset, int snr,
995 QString const &callsign, QString const &grid);
996 void spotCmd(CommandDetail const &cmd);
997 void spotAprsCmd(CommandDetail const &cmd);
998 void pskLogReport(QString const &mode, int dial, int offset, int snr,
999 QString const &callsign, QString const &grid,
1000 QDateTime const &utcTimestamp);
1001 void spotAprsGrid(int dial, int offset, int snr, QString callsign,
1002 QString grid);
1003 Radio::Frequency dialFrequency();
1004 void setSubmode(int submode);
1005 void updateCurrentBand();
1006 void displayDialFrequency();
1007 void transmitDisplay(bool);
1008 void postDecode(bool is_new, QString const &message);
1009 void displayTransmit();
1010 void updateModeButtonText();
1011 void updateButtonDisplay();
1012 void updateTextDisplay();
1013 void updateTextWordCheckerDisplay();
1014 void updateTextStatsDisplay(QString text, int count);
1015 void updateTxButtonDisplay();
1016 bool isMyCallIncluded(QString const &text);
1017 bool isAllCallIncluded(QString const &text);
1018 bool isGroupCallIncluded(const QString &text);
1019 QString callsignSelected(bool useInputText = false);
1020 void callsignSelectedChanged(QString old, QString current);
1021 bool isRecentOffset(int submode, int offset);
1022 void markOffsetRecent(int offset);
1023 bool isDirectedOffset(int offset, bool *pIsAllCall);
1024 void markOffsetDirected(int offset, bool isAllCall);
1025 void clearOffsetDirected(int offset);
1026 void processActivity(bool force = false);
1027 void resetTimeDeltaAverage();
1028 void processRxActivity();
1029 void processIdleActivity();
1030 void processCompoundActivity();
1031 void processBufferedActivity();
1032 void processCommandActivity();
1033 QString inboxPath();
1034 void refreshInboxCounts();
1035 bool hasMessageHistory(QString call);
1036 int addCommandToMyInbox(CommandDetail d);
1037 int addCommandToStorage(QString type, CommandDetail d);
1038 int getNextMessageIdForCallsign(QString callsign);
1039 int getLookaheadMessageIdForCallsign(QString callsign, int afterMsgId);
1040 int getNextGroupMessageIdForCallsign(QString group_name, QString callsign);
1041 int getLookaheadGroupMessageIdForCallsign(QString group_name,
1042 QString callsign, int afterMsgId);
1043 int countUnreadForCallsign(const QString &callsign);
1044 int countGroupUnreadForCallsign(const QString &group_name,
1045 const QString &callsign);
1046 bool markGroupMsgDeliveredForCallsign(int msgId, QString callsign);
1047 bool markMsgDelivered(int mid, Message msg);
1048 QStringList parseRelayPathCallsigns(QString from, QString text);
1049 void processSpots();
1050 void processTxQueue();
1051 void displayActivity(bool force = false);
1052 void displayBandActivity();
1053 void displayCallActivity();
1054 void enable_DXCC_entity(bool on);
1055 void setRig(Frequency = 0); // zero frequency means no change
1056 QDateTime nextTransmitCycle();
1057 void statusUpdate();
1058 void on_the_minute();
1059 void tryBandHop();
1060 void add_child_to_event_filter(QObject *);
1061 void remove_child_from_event_filter(QObject *);
1062 void setup_status_bar();
1063 QString columnLabel(QString defaultLabel);
1064 void ensureMessageDock();
1065
1066 void resetIdleTimer();
1067 void incrementIdleTimer();
1068 void tx_watchdog(bool triggered);
1069 void write_frequency_entry(QString const &file_name);
1070 void write_transmit_entry(QString const &file_name);
1071};
1072
1073#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:13
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 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:2689
void resetMessageTransmitQueue()
Resets the frame-level transmission state after a message completes.
Definition mainwindow.cpp:3514
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:857
header file that defines platform specific label, button, widget and dialog styles used in functions ...