code:
echo make
echo cp wsjtx js8call
echo linuxdeployqt ./js8call -appimage -bundle-non-qt-libs -no-strip -no-translations

license: mit


code:
[Desktop Entry]
Version=1.0
Name=Message Aggregator
Comment=Amateur Radio Weak Signal Operating
Exec=message_aggregator
Icon=wsjtx_icon
Terminal=false
X-MultipleArgs=false
Type=Application
Categories=AudioVideo;Audio;HamRadio;
StartupNotify=true


code:
#include "messageaveraging.h"

#include <QSettings>
#include <QApplication>
#include <QTextCharFormat>

#include "SettingsGroup.hpp"
#include "qt_helpers.hpp"
#include "ui_messageaveraging.h"

MessageAveraging::MessageAveraging(QSettings * settings, QFont const& font, QWidget *parent) :
  QWidget(parent),
  settings_ {settings},
  ui(new Ui::MessageAveraging)
{
  ui->setupUi(this);
//  setWindowTitle (QApplication::applicationName () + " - " + tr ("Message Averaging"));
  ui->msgAvgPlainTextEdit->setReadOnly (true);
  changeFont (font);
  read_settings ();
  if(m_title_.contains("Fox")) {
    ui->header_label->setText("   Date     Time   Call Grid Sent Rcvd Band");
  } else {
    ui->header_label->setText("   UTC  Sync    DT  Freq   ");
    ui->lab1->setVisible(false);
    ui->lab2->setVisible(false);
    ui->lab3->setVisible(false);
    ui->lab4->setVisible(false);
  }
  setWindowTitle(m_title_);
  m_nLogged_=0;
}

MessageAveraging::~MessageAveraging()
{
  if (isVisible ()) write_settings ();
}

void MessageAveraging::changeFont (QFont const& font)
{
  ui->header_label->setStyleSheet (font_as_stylesheet (font));
  ui->msgAvgPlainTextEdit->setStyleSheet (font_as_stylesheet (font));
  setContentFont (font);
  updateGeometry ();
}

void MessageAveraging::setContentFont(QFont const& font)
{
  ui->msgAvgPlainTextEdit->setFont (font);
  QTextCharFormat charFormat;
  charFormat.setFont (font);
  ui->msgAvgPlainTextEdit->selectAll ();
  auto cursor = ui->msgAvgPlainTextEdit->textCursor ();
  cursor.mergeCharFormat (charFormat);
  cursor.clearSelection ();
  cursor.movePosition (QTextCursor::End);

  // position so viewport scrolled to left
  cursor.movePosition (QTextCursor::Up);
  cursor.movePosition (QTextCursor::StartOfLine);

  ui->msgAvgPlainTextEdit->setTextCursor (cursor);
  ui->msgAvgPlainTextEdit->ensureCursorVisible ();
}

void MessageAveraging::closeEvent (QCloseEvent * e)
{
  write_settings ();
  QWidget::closeEvent (e);
}

void MessageAveraging::read_settings ()
{
  SettingsGroup group {settings_, "MessageAveraging"};
  restoreGeometry (settings_->value ("window/geometry").toByteArray ());
  m_title_=settings_->value("window/title","Message Averaging").toString();
}

void MessageAveraging::write_settings ()
{
  SettingsGroup group {settings_, "MessageAveraging"};
  settings_->setValue ("window/geometry", saveGeometry ());
  settings_->setValue("window/title",m_title_);
}

void MessageAveraging::displayAvg(QString const& t)
{
  ui->msgAvgPlainTextEdit->setPlainText(t);
}

void MessageAveraging::foxLogSetup()
{
  m_title_=QApplication::applicationName () + " - Fox Log";
  setWindowTitle(m_title_);
  ui->header_label->setText("   Date    Time  Call    Grid Sent Rcvd Band");
}

void MessageAveraging::foxLabCallers(int n)
{
  QString t;
  t.sprintf("Callers: %3d",n);
  ui->lab1->setText(t);
}

void MessageAveraging::foxLabQueued(int n)
{
  QString t;
  t.sprintf("In progress: %3d",n);
  ui->lab2->setText(t);
}

void MessageAveraging::foxLabRate(int n)
{
  QString t;
  t.sprintf("Rate: %3d",n);
  ui->lab4->setText(t);
}

void MessageAveraging::foxAddLog(QString logLine)
{
  ui->msgAvgPlainTextEdit->appendPlainText(logLine);
  m_nLogged_++;
  QString t;
  t.sprintf("Logged: %d",m_nLogged_);
  ui->lab3->setText(t);
}


code:
#ifndef MESSAGEAVERAGING_H
#define MESSAGEAVERAGING_H

#include <QWidget>

class QSettings;
class QFont;

namespace Ui {
  class MessageAveraging;
}

class MessageAveraging : public QWidget
{
public:
  explicit MessageAveraging(QSettings *, QFont const&, QWidget * parent = 0);
  ~MessageAveraging();
  void displayAvg(QString const&);
  void changeFont (QFont const&);
  void foxLogSetup();
  void foxLabCallers(int n);
  void foxLabQueued(int n);
  void foxLabRate(int n);
  void foxAddLog(QString logLine);

protected:
  void closeEvent (QCloseEvent *) override;

private:
  void read_settings ();
  void write_settings ();
  void setContentFont (QFont const&);
  QSettings * settings_;
  QString m_title_;
  qint32  m_nLogged_;

  QScopedPointer<Ui::MessageAveraging> ui;
};

#endif // MESSAGEAVERAGING_H


code:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MessageAveraging</class>
 <widget class="QWidget" name="MessageAveraging">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>354</width>
    <height>268</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Message Averaging</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <layout class="QGridLayout" name="gridLayout">
     <item row="0" column="0">
      <widget class="QLabel" name="header_label">
       <property name="text">
        <string>   UTC  Sync    DT  Freq   </string>
       </property>
       <property name="margin">
        <number>3</number>
       </property>
      </widget>
     </item>
     <item row="1" column="0">
      <widget class="QPlainTextEdit" name="msgAvgPlainTextEdit">
       <property name="lineWrapMode">
        <enum>QPlainTextEdit::NoWrap</enum>
       </property>
      </widget>
     </item>
     <item row="2" column="0">
      <layout class="QHBoxLayout" name="horizontalLayout">
       <item>
        <spacer name="horizontalSpacer">
         <property name="orientation">
          <enum>Qt::Horizontal</enum>
         </property>
         <property name="sizeType">
          <enum>QSizePolicy::Fixed</enum>
         </property>
         <property name="sizeHint" stdset="0">
          <size>
           <width>20</width>
           <height>20</height>
          </size>
         </property>
        </spacer>
       </item>
       <item>
        <widget class="QLabel" name="lab1">
         <property name="minimumSize">
          <size>
           <width>77</width>
           <height>20</height>
          </size>
         </property>
         <property name="text">
          <string>Callers:    0</string>
         </property>
        </widget>
       </item>
       <item>
        <widget class="QLabel" name="lab2">
         <property name="minimumSize">
          <size>
           <width>77</width>
           <height>20</height>
          </size>
         </property>
         <property name="text">
          <string>In progress:    0</string>
         </property>
        </widget>
       </item>
       <item>
        <spacer name="horizontalSpacer_2">
         <property name="orientation">
          <enum>Qt::Horizontal</enum>
         </property>
         <property name="sizeType">
          <enum>QSizePolicy::Fixed</enum>
         </property>
         <property name="sizeHint" stdset="0">
          <size>
           <width>25</width>
           <height>20</height>
          </size>
         </property>
        </spacer>
       </item>
       <item>
        <widget class="QLabel" name="lab3">
         <property name="minimumSize">
          <size>
           <width>77</width>
           <height>0</height>
          </size>
         </property>
         <property name="text">
          <string>Logged:    0</string>
         </property>
        </widget>
       </item>
       <item>
        <widget class="QLabel" name="lab4">
         <property name="minimumSize">
          <size>
           <width>77</width>
           <height>20</height>
          </size>
         </property>
         <property name="text">
          <string>Rate:     0</string>
         </property>
        </widget>
       </item>
      </layout>
     </item>
    </layout>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>


code:
#include "messagereplydialog.h"
#include "ui_messagereplydialog.h"

#include "varicode.h"

#include <QSet>

MessageReplyDialog::MessageReplyDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::MessageReplyDialog)
{
    ui->setupUi(this);

    auto enterFilter = new EnterKeyPressEater();
    connect(enterFilter, &EnterKeyPressEater::enterKeyPressed, this, [this](QObject *, QKeyEvent *, bool *pProcessed){
        if(QApplication::keyboardModifiers() & Qt::ShiftModifier){
            if(pProcessed) *pProcessed = false;
            return;
        }
        if(pProcessed) *pProcessed = true;

        this->accept();
    });
    ui->textEdit->installEventFilter(enterFilter);
}

MessageReplyDialog::~MessageReplyDialog()
{
    delete ui;
}

void MessageReplyDialog::setLabel(QString value){
    ui->label->setText(value);
}

void MessageReplyDialog::setTextValue(QString text){
    ui->textEdit->setPlainText(text);
}

QString MessageReplyDialog::textValue() const {
    return ui->textEdit->toPlainText();
}

void MessageReplyDialog::on_textEdit_textChanged(){
    auto text = ui->textEdit->toPlainText();

    QString x;
    QString::const_iterator i;
    for(i = text.constBegin(); i != text.constEnd(); i++){
        auto ch = (*i).toUpper().toLatin1();
        if(ch == 10 || (32 <= ch && ch <= 126)){
            // newline or printable 7-bit ascii
            x += ch;
        }
    }

    if(x != text){
      int pos = ui->textEdit->textCursor().position();
      int maxpos = x.size();
      ui->textEdit->setPlainText(x);
      QTextCursor c = ui->textEdit->textCursor();
      c.setPosition(pos < maxpos ? pos : maxpos, QTextCursor::MoveAnchor);

      ui->textEdit->setTextCursor(c);
    }
}


code:
#ifndef MESSAGEREPLYDIALOG_H
#define MESSAGEREPLYDIALOG_H

#include <QDialog>
#include "keyeater.h"

namespace Ui {
class MessageReplyDialog;
}

class QTextEdit;

class MessageReplyDialog : public QDialog
{
    Q_OBJECT

public:
    explicit MessageReplyDialog(QWidget *parent = 0);
    ~MessageReplyDialog();

    void setLabel(QString);
    void setTextValue(QString);
    QString textValue() const;

    QTextEdit * textEdit();

private slots:
    void on_textEdit_textChanged();

private:
    Ui::MessageReplyDialog *ui;
};

#endif // MESSAGEREPLAYDIALOG_H


code:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MessageReplyDialog</class>
 <widget class="QDialog" name="MessageReplyDialog">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>520</width>
    <height>260</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Dialog</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <widget class="QLabel" name="label">
     <property name="text">
      <string>TextLabel</string>
     </property>
    </widget>
   </item>
   <item>
    <widget class="QTextEdit" name="textEdit"/>
   </item>
   <item>
    <widget class="QDialogButtonBox" name="buttonBox">
     <property name="orientation">
      <enum>Qt::Horizontal</enum>
     </property>
     <property name="standardButtons">
      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>buttonBox</sender>
   <signal>accepted()</signal>
   <receiver>MessageReplyDialog</receiver>
   <slot>accept()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>248</x>
     <y>254</y>
    </hint>
    <hint type="destinationlabel">
     <x>157</x>
     <y>274</y>
    </hint>
   </hints>
  </connection>
  <connection>
   <sender>buttonBox</sender>
   <signal>rejected()</signal>
   <receiver>MessageReplyDialog</receiver>
   <slot>reject()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>316</x>
     <y>260</y>
    </hint>
    <hint type="destinationlabel">
     <x>286</x>
     <y>274</y>
    </hint>
   </hints>
  </connection>
 </connections>
</ui>


code:
// Simple bargraph meter
// Implemented by Edson Pereira PY2SDR

#include "meterwidget.h"

#include <QPainter>
#include <QPolygon>

#include "moc_meterwidget.cpp"

#define MAXDB 90

MeterWidget::MeterWidget(QWidget * parent)
  : QWidget {parent}
  , m_signal {0}
  , m_noisePeak {0}
  , m_sigPeak {0}
{
  for ( int i = 0; i < 10; i++ ) {
    signalQueue.enqueue(0);
  }
}

void MeterWidget::setValue(int value)
{
    m_signal = value;
    signalQueue.enqueue(value);
    signalQueue.dequeue();

    // Get signal peak
    int tmp = 0;
    for (int i = 0; i < signalQueue.size(); ++i) {
        if (signalQueue.at(i) > tmp)
            tmp = signalQueue.at(i);
    }
    m_noisePeak = tmp;

    update();
}

QSize MeterWidget::sizeHint () const
{
  return {10, 100};
}

void MeterWidget::paintEvent (QPaintEvent * event)
{
  QWidget::paintEvent (event);

  // Sanitize
  m_signal = m_signal < 0 ? 0 : m_signal;
  m_signal = m_signal > MAXDB ? MAXDB : m_signal;

  QPainter p {this};
  p.setPen (Qt::NoPen);

  auto const& target = contentsRect ();
  QRect r {QPoint {target.left (), static_cast<int> (target.top () + target.height () - m_signal / (double)MAXDB * target.height ())}
    , QPoint {target.right (), target.bottom ()}};
  //p.setBrush (QColor(85,170,85));
  p.setBrush (Qt::green);
  if (m_sigPeak > 85) {
      p.setBrush(Qt::red);
  }
  else if (m_noisePeak < 15) {
      //p.setBrush(QColor(232,81,0));
      p.setBrush(Qt::yellow);
  }
  p.drawRect (r);

  if (m_noisePeak)
    {
      // Draw peak hold indicator
      auto peak = static_cast<int> (target.top () + target.height () - m_noisePeak / (double)MAXDB * target.height ());
      //p.setBrush (Qt::black);
      p.setBrush (Qt::white);
      p.translate (target.left (), peak);
      //p.drawPolygon (QPolygon {{{0, -4}, {0, 4}, {target.width (), 0}}});
      p.drawPolygon (QPolygon { { {target.width (), -4}, {target.width (), 4}, {0, 0} } });
    }
}

//
void MeterWidget::set_sigPeak(int value)
{
    m_sigPeak = value;
}


code:
// -*- Mode: C++ -*-
#ifndef METERWIDGET_H
#define METERWIDGET_H

#include <QWidget>
#include <QQueue>

class MeterWidget : public QWidget
{
  Q_OBJECT
  Q_PROPERTY (int value READ value WRITE setValue)

public:
  explicit MeterWidget (QWidget *parent = 0);

  // value property
  int value () const {return m_signal;}
  Q_SLOT void setValue (int value);

  // QWidget implementation
  QSize sizeHint () const override;
  void set_sigPeak(int value);
protected:
  void paintEvent( QPaintEvent * ) override;

private:
  QQueue<int> signalQueue;
  int m_signal;
  int m_noisePeak;
  int m_sigPeak; // peak value for color coding
};

#endif // METERWIDGET_H


code:
#ifndef PIMPL_H_HPP_
#define PIMPL_H_HPP_

#include <memory>

//
// opaque implementation type with perfect forwarding of constructor arguments
//
// see pimpl_impl.hpp for the out-of-line definitions of the members and lifetime management
//
// thanks to Herb Sutter (http://herbsutter.com/gotw/_101/) for the implementation
//
template<typename T>
class pimpl
{
private:
  std::unique_ptr<T> m_;

public:
  pimpl ();
  template<typename ...Args> pimpl (Args&& ...);
  ~pimpl ();
  T * operator -> ();
  T const * operator -> () const;
  T& operator * ();
  T const& operator * () const;
};

#endif


code:
#ifndef PIMPL_IMPL_HPP_
#define PIMPL_IMPL_HPP_

#include <utility>

template<typename T>
pimpl<T>::pimpl () : m_ {new T {}} {}

template<typename T>
template<typename ...Args>
pimpl<T>::pimpl (Args&& ...args) : m_ {new T {std::forward<Args> (args)...} } {}

template<typename T>
pimpl<T>::~pimpl () {}

template<typename T>
T * pimpl<T>::operator -> () {return m_.get ();}

template<typename T>
T const * pimpl<T>::operator -> () const {return m_.get ();}

template<typename T>
T& pimpl<T>::operator * () {return *m_.get ();}

template<typename T>
T const& pimpl<T>::operator * () const {return *m_.get ();}

#endif


code:
/***************************************************************************
**                                                                        **
**  QCustomPlot, an easy to use, modern plotting widget for Qt            **
**  Copyright (C) 2011-2016 Emanuel Eichhammer                            **
**                                                                        **
**  This program is free software: you can redistribute it and/or modify  **
**  it under the terms of the GNU General Public License as published by  **
**  the Free Software Foundation, either version 3 of the License, or     **
**  (at your option) any later version.                                   **
**                                                                        **
**  This program is distributed in the hope that it will be useful,       **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of        **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         **
**  GNU General Public License for more details.                          **
**                                                                        **
**  You should have received a copy of the GNU General Public License     **
**  along with this program.  If not, see http://www.gnu.org/licenses/.   **
**                                                                        **
****************************************************************************
**           Author: Emanuel Eichhammer                                   **
**  Website/Contact: http://www.qcustomplot.com/                          **
**             Date: 13.09.16                                             **
**          Version: 2.0.0-beta                                           **
****************************************************************************/

#include <QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
  QApplication::setGraphicsSystem("raster");
#endif
  QApplication a(argc, argv);
  MainWindow w;
  w.show();

  return a.exec();
}


code:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QDesktopWidget>
#include <QScreen>
#include <QMessageBox>
#include <QMetaEnum>

#include <fstream>
#include <iostream>

using namespace std;
#define NPTS 3456

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  setGeometry(400, 250, 542, 390);

  setupPlot();
}

MainWindow::~MainWindow()
{
  delete ui;
}

void MainWindow::setupPlot()
{
  plotspec(ui->customPlot);
  setWindowTitle("Reference Spectrum");
  statusBar()->clearMessage();
  ui->customPlot->replot();
}

void MainWindow::plotspec(QCustomPlot *customPlot)
{
  QVector<double> x(NPTS), y1(NPTS), y2(NPTS), y3(NPTS), y4(NPTS);
  ifstream inFile;
  double ymin=1.0e30;
  double ymax=-ymin;
  inFile.open("c:/users/joe/appdata/local/WSJT-X/refspec.dat");

  for (int i = 0; i < NPTS; i++) {
    inFile >> x[i] >> y1[i] >> y2[i] >> y3[3] >> y4[4];
    if(y2[i]>ymax) ymax=y2[i];
    if(y2[i]<ymin) ymin=y2[i];
  }

  customPlot->addGraph();
  customPlot->graph(0)->setData(x, y2);
  customPlot->xAxis->setLabel("Frequency (Hz)");
  customPlot->yAxis->setLabel("Relative power (dB)");
  customPlot->xAxis->setRange(0, 6000);
  customPlot->yAxis->setRange(ymin, ymax);
}


code:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTimer>
#include "qcustomplot.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
  Q_OBJECT

public:
  explicit MainWindow(QWidget *parent = 0);
  ~MainWindow();

  void setupPlot();
  void plotspec(QCustomPlot *customPlot);

private:
  Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H


code:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>548</width>
    <height>420</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>QCustomPlot plot examples</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QCustomPlot" name="customPlot" native="true"/>
    </item>
   </layout>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <customwidgets>
  <customwidget>
   <class>QCustomPlot</class>
   <extends>QWidget</extends>
   <header>qcustomplot.h</header>
   <container>1</container>
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>