Reorganized the window, added beacon watch, macro buttons, etc

This commit is contained in:
Jordan Sherer 2018-07-02 15:08:26 -04:00
parent cb71c3dcf4
commit f610e946fc
5 changed files with 1712 additions and 565 deletions

View File

@ -909,6 +909,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
connect (&splashTimer, &QTimer::timeout, this, &MainWindow::splash_done);
splashTimer.setSingleShot (true);
splashTimer.start (20 * 1000);
/*
if(m_config.my_callsign()=="K1JT" or m_config.my_callsign()=="K9AN" or
m_config.my_callsign()=="G4WJS" || m_config.my_callsign () == "W9XYZ" or
@ -2169,6 +2170,11 @@ void MainWindow::closeEvent(QCloseEvent * e)
QMainWindow::closeEvent (e);
}
void MainWindow::on_labDialFreq_clicked() //dialFrequency
{
ui->bandComboBox->setFocus();
}
void MainWindow::on_stopButton_clicked() //stopButton
{
monitor (false);
@ -2939,10 +2945,45 @@ void MainWindow::readFromStdout() //readFromStdout
m_logBook,m_config.color_CQ(),m_config.color_MyCall(),
m_config.color_DXCC(), m_config.color_NewCall(),
m_config.ppfx(),(ui->cbCQonly->isVisible() and ui->cbCQonly->isChecked()));
ui->textEditRXAll->append(decodedtext.messageWords().first().trimmed());
// TODO: parse decode...
//ui->textEditRXAll->append(decodedtext.messageWords().first().trimmed());
//ui->tableWidgetRXAll->insertRow(ui->tableWidgetRXAll->rowCount());
//ui->tableWidgetRXAll->setItem(ui->tableWidgetRXAll->rowCount()-1, 0, new QTableWidgetItem(QString("%1").arg(decodedtext.frequencyOffset())));
//ui->tableWidgetRXAll->setItem(ui->tableWidgetRXAll->rowCount()-1, 1, new QTableWidgetItem(decodedtext.messageWords().first().trimmed()));
if(decodedtext.messageWords().length() > 0){
int offset = decodedtext.frequencyOffset();
if(!m_bandActivity.contains(offset)){
QList<int> offsets = {offset - 1, offset - 2, offset - 3, offset + 1, offset + 2, offset + 3};
foreach(int prevOffset, offsets){
if(!m_bandActivity.contains(prevOffset)){ continue; }
m_bandActivity[offset] = m_bandActivity[prevOffset];
m_bandActivity.remove(prevOffset);
break;
}
}
ActivityDetail d;
d.freq = offset;
d.text = decodedtext.messageWords().first().trimmed();
d.timestamp = QDateTime::currentDateTimeUtc().toMSecsSinceEpoch();
d.snr = decodedtext.snr();
m_bandActivity[offset].append(d);
while(m_bandActivity[offset].count() > 10){
m_bandActivity[offset].removeFirst();
}
}
QString cqCall = decodedtext.CQersCall();
if(!cqCall.isEmpty()){
ui->listWidget->addItem(cqCall);
CallDetail d;
d.call = cqCall;
d.snr = decodedtext.snr();
d.freq = decodedtext.frequencyOffset();
d.timestamp = QDateTime::currentDateTimeUtc().toMSecsSinceEpoch();
m_callActivity[cqCall] = d;
}
}
}
@ -2985,6 +3026,7 @@ void MainWindow::readFromStdout() //readFromStdout
}
m_QSOText = decodedtext.string ().trimmed ();
// TODO: parse decode...
//ui->textEditRXAll->insertHtml(decodedtext.messageWords().first().trimmed() + "\n");
}
@ -3055,6 +3097,8 @@ void MainWindow::readFromStdout() //readFromStdout
}
}
}
// See MainWindow::postDecode for displaying the latest decodes
}
//
@ -3700,6 +3744,11 @@ void MainWindow::guiUpdate()
QString utc = t.date().toString("yyyy MMM dd") + "\n " +
t.time().toString() + " ";
ui->labUTC->setText(utc);
auto delta = t.msecsTo(m_nextBeacon)/1000;
auto beacon = ui->beaconButton->isChecked() ? delta > 0 ? QString("%1 s").arg(delta) : "queued!" : "disabled";
ui->labBeacon->setText(QString("Next Beacon: %1").arg(beacon));
if(!m_monitoring and !m_diskData) {
ui->signal_meter_widget->setValue(0,0);
}
@ -6066,6 +6115,13 @@ void MainWindow::on_pbT2R_clicked()
}
}
void MainWindow::on_beaconButton_clicked()
{
if(ui->beaconButton->isChecked()){
m_nextBeacon = QDateTime::currentDateTimeUtc().addSecs(300);
}
}
void MainWindow::on_readFreq_clicked()
{
@ -6812,6 +6868,50 @@ void MainWindow::postDecode (bool is_new, QString const& message)
, QChar {'?'} == decode.mid (has_seconds ? 24 + 21 : 22 + 21, 1)
, m_diskData);
}
// TODO: keep track of selection
int now = QDateTime::currentDateTimeUtc().toMSecsSinceEpoch();
for(int i = ui->tableWidgetRXAll->rowCount(); i >= 0; i--){
ui->tableWidgetRXAll->removeRow(i);
}
QList<int> keys = m_bandActivity.keys();
qSort(keys.begin(), keys.end());
foreach (int offset, keys) {
auto items = m_bandActivity[offset];
if(items.length() > 0){
QStringList text;
int snr = 0;
foreach(auto item, items){
if(now - item.timestamp > 90000){
continue;
}
text.append(item.text);
snr = item.snr;
}
auto joined = text.join("");
if(joined.isEmpty()){
continue;
}
ui->tableWidgetRXAll->insertRow(ui->tableWidgetRXAll->rowCount());
ui->tableWidgetRXAll->setItem(ui->tableWidgetRXAll->rowCount() - 1, 0, new QTableWidgetItem(QString("%1").arg(offset)));
ui->tableWidgetRXAll->setItem(ui->tableWidgetRXAll->rowCount() - 1, 1, new QTableWidgetItem(QString("%1").arg(snr)));
ui->tableWidgetRXAll->setItem(ui->tableWidgetRXAll->rowCount() - 1, 2, new QTableWidgetItem(joined));
}
}
// TODO: keep track of selection
ui->listWidget->clear();
ui->listWidget->addItem("allcall");
QList<QString> calls = m_callActivity.keys();
qSort(calls.begin(), calls.end());
foreach(QString call, calls){
ui->listWidget->addItem(call);
}
}
void MainWindow::postWSPRDecode (bool is_new, QStringList parts)

View File

@ -16,6 +16,7 @@
#include <QProgressDialog>
#include <QAbstractSocket>
#include <QHostAddress>
#include <QPair>
#include <QPointer>
#include <QSet>
#include <QVector>
@ -37,6 +38,7 @@
#include "astro.h"
#include "MessageBox.hpp"
#include "NetworkAccessManager.hpp"
#include "qorderedmap.h"
#define NUM_JT4_SYMBOLS 206 //(72+31)*2, embedded sync
#define NUM_JT65_SYMBOLS 126 //63 data + 63 sync
@ -135,6 +137,7 @@ private slots:
void on_monitorButton_clicked (bool);
void on_actionAbout_triggered();
void on_autoButton_clicked (bool);
void on_labDialFreq_clicked();
void on_stopTxButton_clicked();
void on_stopButton_clicked();
void on_actionRelease_Notes_triggered ();
@ -226,6 +229,7 @@ private slots:
void on_tuneButton_clicked (bool);
void on_pbR2T_clicked();
void on_pbT2R_clicked();
void on_beaconButton_clicked();
void acceptQSO (QDateTime const&, QString const& call, QString const& grid
, Frequency dial_freq, QString const& mode
, QString const& rpt_sent, QString const& rpt_received
@ -591,6 +595,24 @@ private:
qint32 ncall;
};
struct CallDetail
{
QString call;
int freq;
int timestamp;
int snr;
};
struct ActivityDetail
{
int freq;
QString text;
int timestamp;
int snr;
};
QMap<int, QList<ActivityDetail>> m_bandActivity; // freq -> [(text, last timestamp), ...]
QMap<QString, CallDetail> m_callActivity; // call -> (last freq, last timestamp)
QMap<QString,FoxQSO> m_foxQSO;
QMap<QString,QString> m_loggedByFox;
@ -599,6 +621,7 @@ private:
QQueue<QString> m_foxRR73Queue;
QQueue<qint64> m_foxRateQueue;
QDateTime m_nextBeacon;
QDateTime m_dateTimeQSOOn;
QDateTime m_dateTimeLastTX;

File diff suppressed because it is too large Load Diff

611
qorderedmap.h Normal file
View File

@ -0,0 +1,611 @@
#ifndef ORDEREDMAP_H
#define ORDEREDMAP_H
#include <QtGlobal>
#include <QHash>
#include <QLinkedList>
#include <QList>
#include <QPair>
template <typename Key> inline bool oMHashEqualToKey(const Key &key1, const Key &key2)
{
// Key type must provide '==' operator
return key1 == key2;
}
template <typename Ptr> inline bool oMHashEqualToKey(Ptr *key1, Ptr *key2)
{
Q_ASSERT(sizeof(quintptr) == sizeof(Ptr *));
return quintptr(key1) == quintptr(key2);
}
template <typename Ptr> inline bool oMHashEqualToKey(const Ptr *key1, const Ptr *key2)
{
Q_ASSERT(sizeof(quintptr) == sizeof(const Ptr *));
return quintptr(key1) == quintptr(key2);
}
template <typename Key, typename Value>
class OrderedMap
{
class OMHash;
typedef typename QLinkedList<Key>::iterator QllIterator;
typedef typename QLinkedList<Key>::const_iterator QllConstIterator;
typedef QPair<Value, QllIterator> OMHashValue;
typedef typename OMHash::iterator OMHashIterator;
typedef typename OMHash::const_iterator OMHashConstIterator;
public:
class iterator;
class const_iterator;
typedef typename OrderedMap<Key, Value>::iterator Iterator;
typedef typename OrderedMap<Key, Value>::const_iterator ConstIterator;
explicit OrderedMap();
OrderedMap(const OrderedMap<Key, Value>& other);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
OrderedMap(OrderedMap<Key, Value>&& other);
#endif
void clear();
bool contains(const Key &key) const;
int count() const;
bool empty() const;
iterator insert(const Key &key, const Value &value);
bool isEmpty() const;
QList<Key> keys() const;
int remove(const Key &key);
int size() const;
Value take(const Key &key);
Value value(const Key &key) const;
Value value(const Key &key, const Value &defaultValue) const;
QList<Value> values() const;
OrderedMap<Key, Value> & operator=(const OrderedMap<Key, Value>& other);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
OrderedMap<Key, Value> & operator=(OrderedMap<Key, Value>&& other);
#endif
bool operator==(const OrderedMap<Key, Value> &other) const;
bool operator!=(const OrderedMap<Key, Value> &other) const;
Value& operator[](const Key &key);
const Value operator[](const Key &key) const;
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
iterator erase(iterator pos);
iterator find(const Key& key);
const_iterator find(const Key& key) const;
class const_iterator;
class iterator
{
QllIterator qllIter;
OMHash *data;
friend class const_iterator;
friend class OrderedMap;
public:
iterator() : data(NULL) {}
iterator(const QllIterator &qllIter, OMHash *data) :
qllIter(qllIter), data(data) {}
const Key & key() const
{
return *qllIter;
}
Value & value() const
{
OMHashIterator hit = data->find(*qllIter);
OMHashValue &pair = hit.value();
return pair.first;
}
Value & operator*() const
{
return value();
}
iterator operator+(int i) const
{
QllIterator q = qllIter;
q += i;
return iterator(q, data);
}
iterator operator-(int i) const
{
return operator +(- i);
}
iterator& operator+=(int i)
{
qllIter += i;
return *this;
}
iterator& operator-=(int i)
{
qllIter -= i;
return *this;
}
iterator& operator++()
{
++qllIter;
return *this;
}
iterator operator++(int)
{
iterator it = *this;
qllIter++;
return it;
}
iterator operator--()
{
--qllIter;
return *this;
}
iterator operator--(int)
{
iterator it = *this;
qllIter--;
return it;
}
bool operator ==(const iterator &other) const
{
return (qllIter == other.qllIter);
}
bool operator !=(const iterator &other) const
{
return (qllIter != other.qllIter);
}
};
class const_iterator
{
QllConstIterator qllConstIter;
const OMHash *data;
public:
const_iterator() : data(NULL) {}
const_iterator(const iterator &i) :
qllConstIter(i.qllIter), data(i.data) {}
const_iterator(const QllConstIterator &qllConstIter, const OMHash* data) :
qllConstIter(qllConstIter), data(data) {}
const Key & key() const
{
return *qllConstIter;
}
const Value & value() const
{
OMHashConstIterator hit = data->find(*qllConstIter);
const OMHashValue &pair = hit.value();
return pair.first;
}
const Value & operator*() const
{
return value();
}
const_iterator operator+(int i) const
{
QllConstIterator q = qllConstIter;
q += i;
return const_iterator(q, data);
}
const_iterator operator-(int i) const
{
return operator +(- i);
}
const_iterator& operator+=(int i)
{
qllConstIter += i;
return *this;
}
const_iterator& operator-=(int i)
{
qllConstIter -= i;
return *this;
}
const_iterator& operator++()
{
++qllConstIter;
return *this;
}
const_iterator operator++(int)
{
const_iterator it = *this;
qllConstIter++;
return it;
}
const_iterator operator--()
{
--qllConstIter;
return *this;
}
const_iterator operator--(int)
{
const_iterator it = *this;
qllConstIter--;
return it;
}
bool operator ==(const const_iterator &other) const
{
return (qllConstIter == other.qllConstIter);
}
bool operator !=(const const_iterator &other) const
{
return (qllConstIter != other.qllConstIter);
}
};
private:
class OMHash : public QHash<Key, OMHashValue >
{
public:
bool operator == (const OMHash &other) const
{
if (size() != other.size()) {
return false;
}
if (QHash<Key, OMHashValue >::operator ==(other)) {
return true;
}
typename QHash<Key, OMHashValue >::const_iterator it1 = this->constBegin();
typename QHash<Key, OMHashValue >::const_iterator it2 = other.constBegin();
while(it1 != this->end()) {
OMHashValue v1 = it1.value();
OMHashValue v2 = it2.value();
if ((v1.first != v2.first) || !oMHashEqualToKey<Key>(it1.key(), it2.key())) {
return false;
}
++it1;
++it2;
}
return true;
}
};
private:
void copy(const OrderedMap<Key, Value> &other);
OMHash data;
QLinkedList<Key> insertOrder;
};
template <typename Key, typename Value>
OrderedMap<Key, Value>::OrderedMap() {}
template <typename Key, typename Value>
OrderedMap<Key, Value>::OrderedMap(const OrderedMap<Key, Value>& other)
{
copy(other);
}
#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
template <typename Key, typename Value>
OrderedMap<Key, Value>::OrderedMap(OrderedMap<Key, Value>&& other)
{
data = std::move(other.data);
insertOrder = std::move(other.insertOrder);
}
#endif
template <typename Key, typename Value>
void OrderedMap<Key, Value>::clear()
{
data.clear();
insertOrder.clear();
}
template <typename Key, typename Value>
bool OrderedMap<Key, Value>::contains(const Key &key) const
{
return data.contains(key);
}
template <typename Key, typename Value>
int OrderedMap<Key, Value>::count() const
{
return data.count();
}
template <typename Key, typename Value>
bool OrderedMap<Key, Value>::empty() const
{
return data.empty();
}
template <typename Key, typename Value>
typename OrderedMap<Key, Value>::iterator OrderedMap<Key, Value>::insert(const Key &key, const Value &value)
{
OMHashIterator it = data.find(key);
if (it == data.end()) {
// New key
QllIterator ioIter = insertOrder.insert(insertOrder.end(), key);
OMHashValue pair(value, ioIter);
data.insert(key, pair);
return iterator(ioIter, &data);
}
OMHashValue pair = it.value();
// remove old reference
insertOrder.erase(pair.second);
// Add new reference
QllIterator ioIter = insertOrder.insert(insertOrder.end(), key);
pair.first = value;
pair.second = ioIter;
return iterator(ioIter, &data);
}
template <typename Key, typename Value>
bool OrderedMap<Key, Value>::isEmpty() const
{
return data.isEmpty();
}
template<typename Key, typename Value>
QList<Key> OrderedMap<Key, Value>::keys() const
{
return QList<Key>::fromStdList(insertOrder.toStdList());
}
template<typename Key, typename Value>
int OrderedMap<Key, Value>::remove(const Key &key)
{
OMHashIterator it = data.find(key);
if (it == data.end()) {
return 0;
}
OMHashValue pair = it.value();
insertOrder.erase(pair.second);
data.erase(it);
return 1;
}
template<typename Key, typename Value>
int OrderedMap<Key, Value>::size() const
{
return data.size();
}
template<typename Key, typename Value>
void OrderedMap<Key, Value>::copy(const OrderedMap<Key, Value> &other)
{
/* Since I'm storing iterators of QLinkedList, I simply cannot make
* a trivial copy of the linked list. This is a limitation due to implicit
* sharing used in Qt containers, due to which iterator active on one
* QLL can change the data of another QLL even after creating a copy.
*
* Because of this, the old iterators have to be invalidated and new ones
* have to be generated.
*/
insertOrder.clear();
// Copy hash
data = other.data;
QllConstIterator cit = other.insertOrder.begin();
for (; cit != other.insertOrder.end(); ++cit) {
Key key = *cit;
QllIterator ioIter = insertOrder.insert(insertOrder.end(), key);
OMHashIterator it = data.find(key);
(*it).second = ioIter;
}
}
template<typename Key, typename Value>
Value OrderedMap<Key, Value>::take(const Key &key)
{
OMHashIterator it = data.find(key);
if (it == data.end()) {
return Value();
}
OMHashValue pair = it.value();
insertOrder.erase(pair.second);
data.erase(it);
return pair.first;
}
template <typename Key, typename Value>
Value OrderedMap<Key, Value>::value(const Key &key) const
{
return data.value(key).first;
}
template <typename Key, typename Value>
Value OrderedMap<Key, Value>::value(const Key &key, const Value &defaultValue) const
{
OMHashConstIterator it = data.constFind(key);
if (it == data.end()) {
return defaultValue;
}
OMHashValue pair = it.value();
return pair.first;
}
template <typename Key, typename Value>
QList<Value> OrderedMap<Key, Value>::values() const
{
QList<Value> values;
foreach (const Key &key, insertOrder.toStdList()) {
OMHashValue v = data.value(key);
values.append(v.first);
}
return values;
}
template <typename Key, typename Value>
OrderedMap<Key, Value> & OrderedMap<Key, Value>::operator=(const OrderedMap<Key, Value>& other)
{
if (this != &other) {
copy(other);
}
return *this;
}
#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
template <typename Key, typename Value>
OrderedMap<Key, Value> & OrderedMap<Key, Value>::operator=(OrderedMap<Key, Value>&& other)
{
if (this != &other) {
data = other.data;
insertOrder = other.insertOrder;
}
return *this;
}
#endif
template <typename Key, typename Value>
bool OrderedMap<Key, Value>::operator==(const OrderedMap<Key, Value> &other) const
{
// 2 Ordered maps are equal if they have the same contents in the same order
return ((data == other.data) && (insertOrder == other.insertOrder));
}
template <typename Key, typename Value>
bool OrderedMap<Key, Value>::operator!=(const OrderedMap<Key, Value> &other) const
{
return ((data != other.data) || (insertOrder != other.insertOrder));
}
template <typename Key, typename Value>
Value& OrderedMap<Key, Value>::operator[](const Key &key)
{
OMHashIterator it = data.find(key);
if (it == data.end()) {
insert(key, Value());
it = data.find(key);
}
OMHashValue &pair = it.value();
return pair.first;
}
template <typename Key, typename Value>
const Value OrderedMap<Key, Value>::operator[](const Key &key) const
{
return value(key);
}
template <typename Key, typename Value>
typename OrderedMap<Key, Value>::iterator OrderedMap<Key, Value>::begin()
{
return iterator(insertOrder.begin(), &data);
}
template <typename Key, typename Value>
typename OrderedMap<Key, Value>::const_iterator OrderedMap<Key, Value>::begin() const
{
return const_iterator(insertOrder.begin(), &data);
}
template <typename Key, typename Value>
typename OrderedMap<Key, Value>::iterator OrderedMap<Key, Value>::end()
{
return iterator(insertOrder.end(), &data);
}
template <typename Key, typename Value>
typename OrderedMap<Key, Value>::const_iterator OrderedMap<Key, Value>::end() const
{
return const_iterator(insertOrder.end(), &data);
}
template <typename Key, typename Value>
typename OrderedMap<Key, Value>::iterator OrderedMap<Key, Value>::erase(iterator pos)
{
OMHashIterator hit = data.find(*(pos.qllIter));
if (hit == data.end()) {
return pos;
}
data.erase(hit);
QllIterator ioIter = insertOrder.erase(pos.qllIter);
return iterator(ioIter, &data);
}
template <typename Key, typename Value>
typename OrderedMap<Key, Value>::iterator OrderedMap<Key, Value>::find(const Key& key)
{
OMHashIterator hit = data.find(key);
if (hit == data.end()) {
return end();
}
return iterator(hit.value().second, &data);
}
template <typename Key, typename Value>
typename OrderedMap<Key, Value>::const_iterator OrderedMap<Key, Value>::find(const Key& key) const
{
OMHashConstIterator hit = data.find(key);
if (hit == data.end()) {
return end();
}
return const_iterator(hit.value().second, &data);
}
#endif // ORDEREDMAP_H

View File

@ -83,7 +83,8 @@ HEADERS += qt_helpers.hpp \
logbook/logbook.h logbook/countrydat.h logbook/countriesworked.h logbook/adif.h \
messageaveraging.h echoplot.h echograph.h fastgraph.h fastplot.h Modes.hpp WSPRBandHopping.hpp \
WsprTxScheduler.h SampleDownloader.hpp MultiSettings.hpp PhaseEqualizationDialog.hpp \
IARURegions.hpp MessageBox.hpp EqualizationToolsDialog.hpp
IARURegions.hpp MessageBox.hpp EqualizationToolsDialog.hpp \
qorderedmap.h
INCLUDEPATH += qmake_only