mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-04-10 13:40:37 -04:00
FT8 demod: use table model and view to optimize messge table update and filtering
This commit is contained in:
parent
c5a9f5fe12
commit
e1640ffaf4
@ -32,6 +32,7 @@ if(NOT SERVER_MODE)
|
||||
set(demodft8_SOURCES
|
||||
${demodft8_SOURCES}
|
||||
ft8demodgui.cpp
|
||||
ft8demodfilterproxy.cpp
|
||||
ft8demodgui.ui
|
||||
ft8demodsettingsdialog.cpp
|
||||
ft8demodsettingsdialog.ui
|
||||
@ -39,6 +40,7 @@ if(NOT SERVER_MODE)
|
||||
set(demodft8_HEADERS
|
||||
${demodft8_HEADERS}
|
||||
ft8demodgui.h
|
||||
ft8demodfilterproxy.h
|
||||
ft8demodsettingsdialog.h
|
||||
)
|
||||
set(TARGET_NAME demodft8)
|
||||
|
93
plugins/channelrx/demodft8/ft8demodfilterproxy.cpp
Normal file
93
plugins/channelrx/demodft8/ft8demodfilterproxy.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Edouard Griffiths, F4EXB //
|
||||
// //
|
||||
// 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 as 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 V3 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/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
#include "ft8demodfilterproxy.h"
|
||||
|
||||
FT8DemodFilterProxy::FT8DemodFilterProxy(QObject *parent) :
|
||||
QSortFilterProxyModel(parent),
|
||||
m_filterActive(FILTER_NONE)
|
||||
{
|
||||
}
|
||||
|
||||
void FT8DemodFilterProxy::resetFilter()
|
||||
{
|
||||
m_filterActive = FILTER_NONE;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void FT8DemodFilterProxy::setFilterUTC(const QString& utcString)
|
||||
{
|
||||
m_filterActive = FILTER_UTC;
|
||||
m_utc = utcString;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void FT8DemodFilterProxy::setFilterDf(int df)
|
||||
{
|
||||
m_filterActive = FILTER_DF;
|
||||
m_df = df;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void FT8DemodFilterProxy::setFilterCall(const QString& callString)
|
||||
{
|
||||
m_filterActive = FILTER_CALL;
|
||||
m_call = callString;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void FT8DemodFilterProxy::setFilterLoc(const QString& locString)
|
||||
{
|
||||
m_filterActive = FILTER_LOC;
|
||||
m_loc = locString;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
bool FT8DemodFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
if (m_filterActive == FILTER_NONE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_filterActive == FILTER_UTC)
|
||||
{
|
||||
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||
return sourceModel()->data(index).toString() == m_utc;
|
||||
}
|
||||
|
||||
if (m_filterActive == FILTER_DF)
|
||||
{
|
||||
QModelIndex index = sourceModel()->index(sourceRow, 4, sourceParent);
|
||||
int df = sourceModel()->data(index).toInt();
|
||||
return (df >= m_df - 4) && (df <= m_df + 4); // +/- 4 Hz tolerance which is about one symbol width
|
||||
}
|
||||
|
||||
if (m_filterActive == FILTER_CALL)
|
||||
{
|
||||
QModelIndex indexCall1 = sourceModel()->index(sourceRow, 6, sourceParent);
|
||||
QModelIndex indexCall2 = sourceModel()->index(sourceRow, 7, sourceParent);
|
||||
return (sourceModel()->data(indexCall1).toString() == m_call) ||
|
||||
(sourceModel()->data(indexCall2).toString() == m_call);
|
||||
}
|
||||
|
||||
if (m_filterActive == FILTER_LOC)
|
||||
{
|
||||
QModelIndex index = sourceModel()->index(sourceRow, 8, sourceParent);
|
||||
return sourceModel()->data(index).toString() == m_loc;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
55
plugins/channelrx/demodft8/ft8demodfilterproxy.h
Normal file
55
plugins/channelrx/demodft8/ft8demodfilterproxy.h
Normal file
@ -0,0 +1,55 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Edouard Griffiths, F4EXB //
|
||||
// //
|
||||
// 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 as 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 V3 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/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef INCLUDE_FT8DEMODFILTERPROXY_H
|
||||
#define INCLUDE_FT8DEMODFILTERPROXY_H
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class FT8DemodFilterProxy : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FT8DemodFilterProxy(QObject *parent = nullptr);
|
||||
|
||||
void resetFilter();
|
||||
void setFilterUTC(const QString& utcString);
|
||||
void setFilterDf(int df);
|
||||
void setFilterCall(const QString& utcString);
|
||||
void setFilterLoc(const QString& utcString);
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
|
||||
private:
|
||||
enum filterActive
|
||||
{
|
||||
FILTER_NONE,
|
||||
FILTER_UTC,
|
||||
FILTER_DF,
|
||||
FILTER_CALL,
|
||||
FILTER_LOC
|
||||
};
|
||||
|
||||
bool dfInRange(int df) const;
|
||||
filterActive m_filterActive;
|
||||
QString m_utc;
|
||||
int m_df;
|
||||
QString m_call;
|
||||
QString m_loc;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FT8DEMODFILTERPROXY_H
|
@ -38,6 +38,200 @@
|
||||
#include "ft8demod.h"
|
||||
#include "ft8demodsettingsdialog.h"
|
||||
|
||||
FT8MessagesTableModel::FT8MessagesTableModel(QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{}
|
||||
|
||||
int FT8MessagesTableModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : m_ft8Messages.size();
|
||||
}
|
||||
|
||||
int FT8MessagesTableModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : m_columnCount;
|
||||
}
|
||||
|
||||
QVariant FT8MessagesTableModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (index.row() >= m_ft8Messages.size() || index.row() < 0) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
const auto &ft8Message = m_ft8Messages.at(index.row());
|
||||
|
||||
switch (index.column()) {
|
||||
case FT8DemodSettings::MESSAGE_COL_UTC:
|
||||
return ft8Message.m_utc;
|
||||
case FT8DemodSettings::MESSAGE_COL_PASS:
|
||||
return ft8Message.m_pass;
|
||||
case FT8DemodSettings::MESSAGE_COL_OKBITS:
|
||||
return ft8Message.m_okBits;
|
||||
case FT8DemodSettings::MESSAGE_COL_DT:
|
||||
return tr("%1").arg(ft8Message.m_dt, 4, 'f', 1);
|
||||
case FT8DemodSettings::MESSAGE_COL_DF:
|
||||
return ft8Message.m_df;
|
||||
case FT8DemodSettings::MESSAGE_COL_SNR:
|
||||
return ft8Message.m_snr;
|
||||
case FT8DemodSettings::MESSAGE_COL_CALL1:
|
||||
return ft8Message.m_call1;
|
||||
case FT8DemodSettings::MESSAGE_COL_CALL2:
|
||||
return ft8Message.m_call2;
|
||||
case FT8DemodSettings::MESSAGE_COL_LOC:
|
||||
return ft8Message.m_loc;
|
||||
case FT8DemodSettings::MESSAGE_COL_INFO:
|
||||
return ft8Message.m_info;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (role == Qt::TextAlignmentRole)
|
||||
{
|
||||
switch (index.column()) {
|
||||
case FT8DemodSettings::MESSAGE_COL_DT:
|
||||
case FT8DemodSettings::MESSAGE_COL_DF:
|
||||
case FT8DemodSettings::MESSAGE_COL_SNR:
|
||||
return Qt::AlignRight;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant FT8MessagesTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if ((role == Qt::DisplayRole) && (orientation == Qt::Horizontal))
|
||||
{
|
||||
switch (section) {
|
||||
case FT8DemodSettings::MESSAGE_COL_UTC:
|
||||
return tr("UTC");
|
||||
case FT8DemodSettings::MESSAGE_COL_PASS:
|
||||
return tr("P");
|
||||
case FT8DemodSettings::MESSAGE_COL_OKBITS:
|
||||
return tr("OKb");
|
||||
case FT8DemodSettings::MESSAGE_COL_DT:
|
||||
return tr("dt");
|
||||
case FT8DemodSettings::MESSAGE_COL_DF:
|
||||
return tr("df");
|
||||
case FT8DemodSettings::MESSAGE_COL_SNR:
|
||||
return tr("SNR");
|
||||
case FT8DemodSettings::MESSAGE_COL_CALL1:
|
||||
return tr("Call1");
|
||||
case FT8DemodSettings::MESSAGE_COL_CALL2:
|
||||
return tr("Call2");
|
||||
case FT8DemodSettings::MESSAGE_COL_LOC:
|
||||
return tr("Loc");
|
||||
case FT8DemodSettings::MESSAGE_COL_INFO:
|
||||
return tr("Info");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (role == Qt::ToolTipRole)
|
||||
{
|
||||
switch (section) {
|
||||
case FT8DemodSettings::MESSAGE_COL_UTC:
|
||||
return tr("Sequence UTC time HHMMSS");
|
||||
case FT8DemodSettings::MESSAGE_COL_PASS:
|
||||
return tr("Successful decoder pass index");
|
||||
case FT8DemodSettings::MESSAGE_COL_OKBITS:
|
||||
return tr("Number of correct bits before correction");
|
||||
case FT8DemodSettings::MESSAGE_COL_DT:
|
||||
return tr("Message start time delay in sequence (s)");
|
||||
case FT8DemodSettings::MESSAGE_COL_DF:
|
||||
return tr("Carrier frequency shift (Hz)");
|
||||
case FT8DemodSettings::MESSAGE_COL_SNR:
|
||||
return tr("Signal to noise ratio (dB) in 2.5 kHz bandwidth");
|
||||
case FT8DemodSettings::MESSAGE_COL_CALL1:
|
||||
return tr("Fist call area");
|
||||
case FT8DemodSettings::MESSAGE_COL_CALL2:
|
||||
return tr("Second call area");
|
||||
case FT8DemodSettings::MESSAGE_COL_LOC:
|
||||
return tr("Locator area");
|
||||
case FT8DemodSettings::MESSAGE_COL_INFO:
|
||||
return tr("Decoder information");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const QVector<FT8MesssageData> &FT8MessagesTableModel::getMessages() const
|
||||
{
|
||||
return m_ft8Messages;
|
||||
}
|
||||
|
||||
void FT8MessagesTableModel::messagesReceived(const QList<FT8Message>& messages)
|
||||
{
|
||||
int position = m_ft8Messages.size();
|
||||
int rows = messages.size();
|
||||
beginInsertRows(QModelIndex(), position, position + rows - 1);
|
||||
|
||||
for (const auto& message : messages)
|
||||
{
|
||||
m_ft8Messages.push_back(FT8MesssageData{
|
||||
message.ts.toString("HHmmss"),
|
||||
message.pass,
|
||||
message.nbCorrectBits,
|
||||
message.dt,
|
||||
(int) message.df,
|
||||
message.snr,
|
||||
message.call1,
|
||||
message.call2,
|
||||
message.loc,
|
||||
message.decoderInfo
|
||||
});
|
||||
}
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void FT8MessagesTableModel::setDefaultMessage()
|
||||
{
|
||||
if (m_ft8Messages.size() != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
beginInsertRows(QModelIndex(), 0, 0);
|
||||
m_ft8Messages.push_back(FT8MesssageData{
|
||||
"000000",
|
||||
0,
|
||||
174,
|
||||
-8.0,
|
||||
8000,
|
||||
-24,
|
||||
"CQ PA900RAALTE",
|
||||
"PA900RAALTE",
|
||||
"JN000",
|
||||
"OSD-0-73"
|
||||
});
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void FT8MessagesTableModel::clearMessages()
|
||||
{
|
||||
if (m_ft8Messages.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
beginRemoveRows(QModelIndex(), 0, m_ft8Messages.size()-1);
|
||||
m_ft8Messages.clear();
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
|
||||
FT8DemodGUI* FT8DemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
|
||||
{
|
||||
FT8DemodGUI* gui = new FT8DemodGUI(pluginAPI, deviceUISet, rxChannel);
|
||||
@ -216,16 +410,13 @@ void FT8DemodGUI::on_filterIndex_valueChanged(int value)
|
||||
|
||||
void FT8DemodGUI::on_moveToBottom_clicked()
|
||||
{
|
||||
ui->messages->scrollToBottom();
|
||||
ui->messagesView->scrollToBottom();
|
||||
}
|
||||
|
||||
void FT8DemodGUI::on_filterMessages_toggled(bool checked)
|
||||
{
|
||||
m_filterMessages = checked;
|
||||
|
||||
for (int row = 0; row < ui->messages->rowCount(); row++) {
|
||||
filterMessageRow(row);
|
||||
}
|
||||
filterMessages();
|
||||
}
|
||||
|
||||
void FT8DemodGUI::on_applyBandPreset_clicked()
|
||||
@ -246,8 +437,8 @@ void FT8DemodGUI::on_applyBandPreset_clicked()
|
||||
|
||||
void FT8DemodGUI::on_clearMessages_clicked()
|
||||
{
|
||||
ui->messages->setRowCount(0);
|
||||
ui->nbDecodesInTable->setText("0");
|
||||
m_messagesModel.clearMessages();
|
||||
}
|
||||
|
||||
void FT8DemodGUI::on_recordWav_toggled(bool checked)
|
||||
@ -429,11 +620,8 @@ FT8DemodGUI::FT8DemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseban
|
||||
applyBandwidths(m_settings.m_filterBank[m_settings.m_filterIndex].m_spanLog2, true); // does applySettings(true)
|
||||
DialPopup::addPopupsToChildDials(this);
|
||||
|
||||
// Resize the table using dummy data
|
||||
resizeMessageTable();
|
||||
populateBandPresets();
|
||||
|
||||
connect(ui->messages, &QTableWidget::cellClicked, this, &FT8DemodGUI::messageCellClicked);
|
||||
setupMessagesView();
|
||||
}
|
||||
|
||||
FT8DemodGUI::~FT8DemodGUI()
|
||||
@ -665,83 +853,19 @@ void FT8DemodGUI::updateAbsoluteCenterFrequency()
|
||||
setStatusFrequency(m_deviceCenterFrequency + m_settings.m_inputFrequencyOffset);
|
||||
}
|
||||
|
||||
void FT8DemodGUI::resizeMessageTable()
|
||||
{
|
||||
// Fill table with a row of dummy data that will size the columns nicely
|
||||
// Trailing spaces are for sort arrow
|
||||
int row = ui->messages->rowCount();
|
||||
ui->messages->setRowCount(row + 1);
|
||||
ui->messages->setItem(row, MESSAGE_COL_UTC, new QTableWidgetItem("000000"));
|
||||
ui->messages->setItem(row, MESSAGE_COL_N, new QTableWidgetItem("0"));
|
||||
ui->messages->setItem(row, MESSAGE_COL_SNR, new QTableWidgetItem("-24"));
|
||||
ui->messages->setItem(row, MESSAGE_COL_DEC, new QTableWidgetItem("174"));
|
||||
ui->messages->setItem(row, MESSAGE_COL_DT, new QTableWidgetItem("-0.0"));
|
||||
ui->messages->setItem(row, MESSAGE_COL_DF, new QTableWidgetItem("0000"));
|
||||
ui->messages->setItem(row, MESSAGE_COL_CALL1, new QTableWidgetItem("CQ PA900RAALTE"));
|
||||
ui->messages->setItem(row, MESSAGE_COL_CALL2, new QTableWidgetItem("PA900RAALTE"));
|
||||
ui->messages->setItem(row, MESSAGE_COL_LOC, new QTableWidgetItem("JN000"));
|
||||
ui->messages->setItem(row, MESSAGE_COL_INFO, new QTableWidgetItem("OSD-0-73"));
|
||||
ui->messages->resizeColumnsToContents();
|
||||
ui->messages->removeRow(row);
|
||||
}
|
||||
|
||||
void FT8DemodGUI::messagesReceived(const QList<FT8Message>& messages)
|
||||
{
|
||||
ui->nbDecodesText->setText(tr("%1").arg(messages.size()));
|
||||
|
||||
// Is scroll bar at bottom
|
||||
QScrollBar *sb = ui->messages->verticalScrollBar();
|
||||
QScrollBar *sb = ui->messagesView->verticalScrollBar();
|
||||
bool scrollToBottom = sb->value() == sb->maximum();
|
||||
|
||||
// Add to messages table
|
||||
int row = ui->messages->rowCount();
|
||||
|
||||
for (const auto& message : messages)
|
||||
{
|
||||
ui->messages->setRowCount(row + 1);
|
||||
|
||||
QTableWidgetItem *utcItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *passItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *snrItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *correctItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *dtItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *dfItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *call1Item = new QTableWidgetItem();
|
||||
QTableWidgetItem *call2Item = new QTableWidgetItem();
|
||||
QTableWidgetItem *locItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *infoItem = new QTableWidgetItem();
|
||||
|
||||
ui->messages->setItem(row, MESSAGE_COL_UTC, utcItem);
|
||||
ui->messages->setItem(row, MESSAGE_COL_N, passItem);
|
||||
ui->messages->setItem(row, MESSAGE_COL_SNR, snrItem);
|
||||
ui->messages->setItem(row, MESSAGE_COL_DEC, correctItem);
|
||||
ui->messages->setItem(row, MESSAGE_COL_DT, dtItem);
|
||||
ui->messages->setItem(row, MESSAGE_COL_DF, dfItem);
|
||||
ui->messages->setItem(row, MESSAGE_COL_CALL1, call1Item);
|
||||
ui->messages->setItem(row, MESSAGE_COL_CALL2, call2Item);
|
||||
ui->messages->setItem(row, MESSAGE_COL_LOC, locItem);
|
||||
ui->messages->setItem(row, MESSAGE_COL_INFO, infoItem);
|
||||
|
||||
utcItem->setText(message.ts.toString("HHmmss"));
|
||||
passItem->setText(tr("%1").arg(message.pass));
|
||||
correctItem->setText(tr("%1").arg(message.nbCorrectBits));
|
||||
dtItem->setText(tr("%1").arg(message.dt, 4, 'f', 1));
|
||||
dfItem->setText(tr("%1").arg((int) message.df, 4));
|
||||
snrItem->setText(tr("%1").arg(message.snr, 3));
|
||||
call1Item->setText(message.call1);
|
||||
call2Item->setText(message.call2);
|
||||
locItem->setText(message.loc);
|
||||
infoItem->setText(message.decoderInfo);
|
||||
|
||||
filterMessageRow(row);
|
||||
|
||||
row++;
|
||||
}
|
||||
|
||||
ui->nbDecodesInTable->setText(tr("%1").arg(row));
|
||||
m_messagesModel.messagesReceived(messages);
|
||||
ui->nbDecodesInTable->setText(tr("%1").arg(m_messagesModel.countAllMessages()));
|
||||
|
||||
if (scrollToBottom) {
|
||||
ui->messages->scrollToBottom();
|
||||
ui->messagesView->scrollToBottom();
|
||||
}
|
||||
}
|
||||
|
||||
@ -757,45 +881,43 @@ void FT8DemodGUI::populateBandPresets()
|
||||
ui->bandPreset->blockSignals(false);
|
||||
}
|
||||
|
||||
void FT8DemodGUI::messageCellClicked(int row, int col)
|
||||
void FT8DemodGUI::messageViewClicked(const QModelIndex &index)
|
||||
{
|
||||
m_selectedColumn = col;
|
||||
m_selectedValue = ui->messages->item(row, col)->text();
|
||||
qDebug("FT8DemodGUI::messageCellChanged: %d %s", m_selectedColumn, qPrintable(m_selectedValue));
|
||||
if (index.isValid())
|
||||
{
|
||||
m_selectedColumn = index.column();
|
||||
m_selectedData = index.data();
|
||||
filterMessages();
|
||||
}
|
||||
}
|
||||
|
||||
void FT8DemodGUI::filterMessageRow(int row)
|
||||
void FT8DemodGUI::filterMessages()
|
||||
{
|
||||
if (!m_filterMessages)
|
||||
{
|
||||
ui->messages->setRowHidden(row, false);
|
||||
m_messagesFilterProxy.resetFilter();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((m_selectedColumn == MESSAGE_COL_CALL1) || (m_selectedColumn == MESSAGE_COL_CALL2))
|
||||
{
|
||||
const QString& call1 = ui->messages->item(row, MESSAGE_COL_CALL1)->text();
|
||||
const QString& call2 = ui->messages->item(row, MESSAGE_COL_CALL2)->text();
|
||||
bool visible = ((call1 == m_selectedValue) || (call2 == m_selectedValue));
|
||||
ui->messages->setRowHidden(row, !visible);
|
||||
return;
|
||||
if ((m_selectedColumn == FT8DemodSettings::MESSAGE_COL_CALL1) || (m_selectedColumn == FT8DemodSettings::MESSAGE_COL_CALL2)) {
|
||||
m_messagesFilterProxy.setFilterCall(m_selectedData.toString());
|
||||
} else if (m_selectedColumn == FT8DemodSettings::MESSAGE_COL_LOC) {
|
||||
m_messagesFilterProxy.setFilterLoc(m_selectedData.toString());
|
||||
} else if (m_selectedColumn == FT8DemodSettings::MESSAGE_COL_UTC) {
|
||||
m_messagesFilterProxy.setFilterUTC(m_selectedData.toString());
|
||||
} else if (m_selectedColumn == FT8DemodSettings::MESSAGE_COL_DF) {
|
||||
m_messagesFilterProxy.setFilterDf(m_selectedData.toInt());
|
||||
}
|
||||
|
||||
if (m_selectedColumn == MESSAGE_COL_LOC)
|
||||
{
|
||||
const QString& loc = ui->messages->item(row, MESSAGE_COL_LOC)->text();
|
||||
bool visible = (loc == m_selectedValue);
|
||||
ui->messages->setRowHidden(row, !visible);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_selectedColumn == MESSAGE_COL_UTC)
|
||||
{
|
||||
const QString& utc = ui->messages->item(row, MESSAGE_COL_UTC)->text();
|
||||
bool visible = (utc == m_selectedValue);
|
||||
ui->messages->setRowHidden(row, !visible);
|
||||
return;
|
||||
}
|
||||
|
||||
ui->messages->setRowHidden(row, false);
|
||||
}
|
||||
|
||||
void FT8DemodGUI::setupMessagesView()
|
||||
{
|
||||
m_messagesFilterProxy.setSourceModel(&m_messagesModel);
|
||||
ui->messagesView->setModel(&m_messagesFilterProxy);
|
||||
// resize columns
|
||||
m_messagesModel.setDefaultMessage();
|
||||
ui->messagesView->resizeColumnsToContents();
|
||||
m_messagesModel.clearMessages();
|
||||
|
||||
connect(ui->messagesView, &QTableView::clicked, this, &FT8DemodGUI::messageViewClicked);
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
#ifndef INCLUDE_SSBDEMODGUI_H
|
||||
#define INCLUDE_SSBDEMODGUI_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
#include "channel/channelgui.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
@ -24,10 +26,12 @@
|
||||
#include "util/ft8message.h"
|
||||
#include "settings/rollupstate.h"
|
||||
#include "ft8demodsettings.h"
|
||||
#include "ft8demodfilterproxy.h"
|
||||
|
||||
class QModelIndex;
|
||||
|
||||
class PluginAPI;
|
||||
class DeviceUISet;
|
||||
|
||||
class AudioFifo;
|
||||
class FT8Demod;
|
||||
class SpectrumVis;
|
||||
@ -37,6 +41,41 @@ namespace Ui {
|
||||
class FT8DemodGUI;
|
||||
}
|
||||
|
||||
struct FT8MesssageData
|
||||
{
|
||||
QString m_utc;
|
||||
int m_pass;
|
||||
int m_okBits;
|
||||
float m_dt;
|
||||
int m_df;
|
||||
int m_snr;
|
||||
QString m_call1;
|
||||
QString m_call2;
|
||||
QString m_loc;
|
||||
QString m_info;
|
||||
};
|
||||
|
||||
class FT8MessagesTableModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FT8MessagesTableModel(QObject *parent = nullptr);
|
||||
|
||||
virtual int rowCount(const QModelIndex &parent) const;
|
||||
virtual int columnCount(const QModelIndex &parent) const;
|
||||
virtual QVariant data(const QModelIndex &index, int role) const;
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
const QVector<FT8MesssageData> &getMessages() const;
|
||||
void messagesReceived(const QList<FT8Message>& messages);
|
||||
void setDefaultMessage();
|
||||
void clearMessages();
|
||||
int countAllMessages() const { return m_ft8Messages.size(); }
|
||||
|
||||
private:
|
||||
QVector<FT8MesssageData> m_ft8Messages;
|
||||
static const int m_columnCount = 10;
|
||||
};
|
||||
|
||||
class FT8DemodGUI : public ChannelGUI {
|
||||
Q_OBJECT
|
||||
|
||||
@ -84,11 +123,15 @@ private:
|
||||
bool m_filterMessages;
|
||||
int m_selectedColumn;
|
||||
QString m_selectedValue;
|
||||
QVariant m_selectedData;
|
||||
|
||||
FT8Demod* m_ft8Demod;
|
||||
SpectrumVis* m_spectrumVis;
|
||||
MessageQueue m_inputMessageQueue;
|
||||
|
||||
FT8MessagesTableModel m_messagesModel;
|
||||
FT8DemodFilterProxy m_messagesFilterProxy;
|
||||
|
||||
explicit FT8DemodGUI(PluginAPI* pluginAPI, DeviceUISet* deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0);
|
||||
virtual ~FT8DemodGUI();
|
||||
|
||||
@ -104,23 +147,10 @@ private:
|
||||
void leaveEvent(QEvent*);
|
||||
void enterEvent(EnterEventType*);
|
||||
|
||||
void resizeMessageTable();
|
||||
void messagesReceived(const QList<FT8Message>& messages);
|
||||
void populateBandPresets();
|
||||
void filterMessageRow(int row);
|
||||
|
||||
enum MessageCol {
|
||||
MESSAGE_COL_UTC,
|
||||
MESSAGE_COL_N,
|
||||
MESSAGE_COL_DEC,
|
||||
MESSAGE_COL_DT,
|
||||
MESSAGE_COL_DF,
|
||||
MESSAGE_COL_SNR,
|
||||
MESSAGE_COL_CALL1,
|
||||
MESSAGE_COL_CALL2,
|
||||
MESSAGE_COL_LOC,
|
||||
MESSAGE_COL_INFO,
|
||||
};
|
||||
void filterMessages();
|
||||
void setupMessagesView();
|
||||
|
||||
private slots:
|
||||
void on_deltaFrequency_changed(qint64 value);
|
||||
@ -142,7 +172,7 @@ private slots:
|
||||
void onMenuDialogCalled(const QPoint& p);
|
||||
void handleInputMessages();
|
||||
void tick();
|
||||
void messageCellClicked(int row, int col);
|
||||
void messageViewClicked(const QModelIndex &index);
|
||||
};
|
||||
|
||||
#endif // INCLUDE_SSBDEMODGUI_H
|
||||
|
@ -1005,19 +1005,13 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="messages">
|
||||
<widget class="QTableView" name="messagesView">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Liberation Mono</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Decoded messages</string>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
@ -1027,86 +1021,6 @@
|
||||
<attribute name="verticalHeaderDefaultSectionSize">
|
||||
<number>15</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>UTC</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Sequence UTC time HHMMSS</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>P</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Successful decoder pass index</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>OKb</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Number of correct bits before correction</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>dt</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Time delay</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>df</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Frequency shift</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>SNR</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Signal to noise ratio (dB) in 2.5 kHz bandwidth</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Call1</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Fist call area</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Call2</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Second call area</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Loc</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Locator area</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Info</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Extra decoder information</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -50,6 +50,19 @@ struct FT8DemodBandPreset
|
||||
|
||||
struct FT8DemodSettings
|
||||
{
|
||||
enum MessageCol {
|
||||
MESSAGE_COL_UTC,
|
||||
MESSAGE_COL_PASS,
|
||||
MESSAGE_COL_OKBITS,
|
||||
MESSAGE_COL_DT,
|
||||
MESSAGE_COL_DF,
|
||||
MESSAGE_COL_SNR,
|
||||
MESSAGE_COL_CALL1,
|
||||
MESSAGE_COL_CALL2,
|
||||
MESSAGE_COL_LOC,
|
||||
MESSAGE_COL_INFO,
|
||||
};
|
||||
|
||||
qint32 m_inputFrequencyOffset;
|
||||
// Real m_rfBandwidth;
|
||||
// Real m_lowCutoff;
|
||||
|
Loading…
Reference in New Issue
Block a user