mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-26 09:48:45 -05:00
Heat Map: Handle memory allocation errors. Allow selecting which data to be saved to reduce memory requirements.
This commit is contained in:
parent
deb4feed3b
commit
64d75baadf
@ -22,7 +22,6 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QRegExp>
|
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
|
|
||||||
@ -226,9 +225,17 @@ void HeatMapGUI::on_mode_currentIndexChanged(int index)
|
|||||||
ui->writeImage->setEnabled(!none);
|
ui->writeImage->setEnabled(!none);
|
||||||
ui->writeCSV->setEnabled(!none);
|
ui->writeCSV->setEnabled(!none);
|
||||||
ui->readCSV->setEnabled(!none);
|
ui->readCSV->setEnabled(!none);
|
||||||
if (none) {
|
ui->colorMapLabel->setEnabled(!none);
|
||||||
|
ui->colorMap->setEnabled(!none);
|
||||||
|
if (none)
|
||||||
|
{
|
||||||
deleteFromMap();
|
deleteFromMap();
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_image.isNull()) {
|
||||||
|
createImage(m_width, m_height);
|
||||||
|
}
|
||||||
plotMap();
|
plotMap();
|
||||||
}
|
}
|
||||||
applySettings();
|
applySettings();
|
||||||
@ -551,6 +558,9 @@ HeatMapGUI::HeatMapGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandS
|
|||||||
m_heatMap = reinterpret_cast<HeatMap*>(rxChannel);
|
m_heatMap = reinterpret_cast<HeatMap*>(rxChannel);
|
||||||
m_heatMap->setMessageQueueToGUI(getInputMessageQueue());
|
m_heatMap->setMessageQueueToGUI(getInputMessageQueue());
|
||||||
|
|
||||||
|
// Disable 256MB limit on image size
|
||||||
|
QImageReader::setAllocationLimit(0);
|
||||||
|
|
||||||
connect(&MainCore::instance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); // 50 ms
|
connect(&MainCore::instance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); // 50 ms
|
||||||
|
|
||||||
m_scopeVis = m_heatMap->getScopeSink();
|
m_scopeVis = m_heatMap->getScopeSink();
|
||||||
@ -708,6 +718,11 @@ void HeatMapGUI::displaySettings()
|
|||||||
ui->displayPulseAverage->setChecked(m_settings.m_displayPulseAverage);
|
ui->displayPulseAverage->setChecked(m_settings.m_displayPulseAverage);
|
||||||
ui->displayPathLoss->setChecked(m_settings.m_displayPathLoss);
|
ui->displayPathLoss->setChecked(m_settings.m_displayPathLoss);
|
||||||
ui->displayMins->setValue(m_settings.m_displayMins);
|
ui->displayMins->setValue(m_settings.m_displayMins);
|
||||||
|
ui->recordAverage->setChecked(m_settings.m_recordAverage);
|
||||||
|
ui->recordMax->setChecked(m_settings.m_recordMax);
|
||||||
|
ui->recordMin->setChecked(m_settings.m_recordMin);
|
||||||
|
ui->recordPulseAverage->setChecked(m_settings.m_recordPulseAverage);
|
||||||
|
ui->recordPathLoss->setChecked(m_settings.m_recordPathLoss);
|
||||||
|
|
||||||
m_scopeVis->setLiveRate(m_settings.m_sampleRate);
|
m_scopeVis->setLiveRate(m_settings.m_sampleRate);
|
||||||
|
|
||||||
@ -765,7 +780,9 @@ void HeatMapGUI::tick()
|
|||||||
if (!std::isnan(magAvg))
|
if (!std::isnan(magAvg))
|
||||||
{
|
{
|
||||||
powDbAvg = CalcDb::dbPower(magAvg * magAvg);
|
powDbAvg = CalcDb::dbPower(magAvg * magAvg);
|
||||||
|
if (m_powerAverage) {
|
||||||
m_powerAverage[idx] = powDbAvg;
|
m_powerAverage[idx] = powDbAvg;
|
||||||
|
}
|
||||||
if (m_tickCount % 4 == 0) {
|
if (m_tickCount % 4 == 0) {
|
||||||
ui->average->setText(QString::number(powDbAvg, 'f', 1));
|
ui->average->setText(QString::number(powDbAvg, 'f', 1));
|
||||||
}
|
}
|
||||||
@ -777,7 +794,9 @@ void HeatMapGUI::tick()
|
|||||||
if (!std::isnan(magPulseAvg))
|
if (!std::isnan(magPulseAvg))
|
||||||
{
|
{
|
||||||
powDbPulseAvg = CalcDb::dbPower(magPulseAvg * magPulseAvg);
|
powDbPulseAvg = CalcDb::dbPower(magPulseAvg * magPulseAvg);
|
||||||
|
if (m_powerPulseAverage) {
|
||||||
m_powerPulseAverage[idx] = powDbPulseAvg;
|
m_powerPulseAverage[idx] = powDbPulseAvg;
|
||||||
|
}
|
||||||
if (m_tickCount % 4 == 0) {
|
if (m_tickCount % 4 == 0) {
|
||||||
ui->pulseAverage->setText(QString::number(powDbPulseAvg, 'f', 1));
|
ui->pulseAverage->setText(QString::number(powDbPulseAvg, 'f', 1));
|
||||||
}
|
}
|
||||||
@ -789,7 +808,9 @@ void HeatMapGUI::tick()
|
|||||||
if (magMaxPeak != -std::numeric_limits<double>::max())
|
if (magMaxPeak != -std::numeric_limits<double>::max())
|
||||||
{
|
{
|
||||||
powDbMaxPeak = CalcDb::dbPower(magMaxPeak * magMaxPeak);
|
powDbMaxPeak = CalcDb::dbPower(magMaxPeak * magMaxPeak);
|
||||||
|
if (m_powerMaxPeak) {
|
||||||
m_powerMaxPeak[idx] = powDbMaxPeak;
|
m_powerMaxPeak[idx] = powDbMaxPeak;
|
||||||
|
}
|
||||||
if (m_tickCount % 4 == 0) {
|
if (m_tickCount % 4 == 0) {
|
||||||
ui->maxPeak->setText(QString::number(powDbMaxPeak, 'f', 1));
|
ui->maxPeak->setText(QString::number(powDbMaxPeak, 'f', 1));
|
||||||
}
|
}
|
||||||
@ -801,7 +822,9 @@ void HeatMapGUI::tick()
|
|||||||
if (magMinPeak != std::numeric_limits<double>::max())
|
if (magMinPeak != std::numeric_limits<double>::max())
|
||||||
{
|
{
|
||||||
powDbMinPeak = CalcDb::dbPower(magMinPeak * magMinPeak);
|
powDbMinPeak = CalcDb::dbPower(magMinPeak * magMinPeak);
|
||||||
|
if (m_powerMinPeak) {
|
||||||
m_powerMinPeak[idx] = powDbMinPeak;
|
m_powerMinPeak[idx] = powDbMinPeak;
|
||||||
|
}
|
||||||
if (m_tickCount % 4 == 0) {
|
if (m_tickCount % 4 == 0) {
|
||||||
ui->minPeak->setText(QString::number(powDbMinPeak, 'f', 1));
|
ui->minPeak->setText(QString::number(powDbMinPeak, 'f', 1));
|
||||||
}
|
}
|
||||||
@ -814,7 +837,9 @@ void HeatMapGUI::tick()
|
|||||||
double range = calcRange(m_latitude, m_longitude);
|
double range = calcRange(m_latitude, m_longitude);
|
||||||
double frequency = m_deviceCenterFrequency + m_settings.m_inputFrequencyOffset;
|
double frequency = m_deviceCenterFrequency + m_settings.m_inputFrequencyOffset;
|
||||||
powDbPathLoss = m_settings.m_txPower - calcFreeSpacePathLoss(range, frequency);
|
powDbPathLoss = m_settings.m_txPower - calcFreeSpacePathLoss(range, frequency);
|
||||||
|
if (m_powerPathLoss) {
|
||||||
m_powerPathLoss[idx] = powDbPathLoss;
|
m_powerPathLoss[idx] = powDbPathLoss;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_heatMap->getDeviceAPI()->state(0) == DeviceAPI::StRunning)
|
if (m_heatMap->getDeviceAPI()->state(0) == DeviceAPI::StRunning)
|
||||||
{
|
{
|
||||||
@ -823,11 +848,14 @@ void HeatMapGUI::tick()
|
|||||||
{
|
{
|
||||||
// Plot newest measurement on map
|
// Plot newest measurement on map
|
||||||
float *power = getCurrentModePowerData();
|
float *power = getCurrentModePowerData();
|
||||||
|
if (power)
|
||||||
|
{
|
||||||
double powDb = power[idx];
|
double powDb = power[idx];
|
||||||
if (!std::isnan(powDb)) {
|
if (!std::isnan(powDb)) {
|
||||||
plotPixel(m_x, m_y, powDb);
|
plotPixel(m_x, m_y, powDb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_tickCount % 15 == 0)
|
if (m_tickCount % 15 == 0)
|
||||||
{
|
{
|
||||||
@ -882,9 +910,15 @@ void HeatMapGUI::updatePower(double latitude, double longitude, float power)
|
|||||||
|
|
||||||
void HeatMapGUI::plotMap()
|
void HeatMapGUI::plotMap()
|
||||||
{
|
{
|
||||||
|
if ((m_settings.m_mode != HeatMapSettings::None) && !m_image.isNull())
|
||||||
|
{
|
||||||
clearImage();
|
clearImage();
|
||||||
plotMap(getCurrentModePowerData());
|
float *data = getCurrentModePowerData();
|
||||||
|
if (data) {
|
||||||
|
plotMap(data);
|
||||||
|
}
|
||||||
sendToMap();
|
sendToMap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeatMapGUI::clearPower()
|
void HeatMapGUI::clearPower()
|
||||||
@ -903,7 +937,35 @@ void HeatMapGUI::clearPower(float *power)
|
|||||||
|
|
||||||
void HeatMapGUI::clearPower(float *power, int size)
|
void HeatMapGUI::clearPower(float *power, int size)
|
||||||
{
|
{
|
||||||
|
if (power) {
|
||||||
std::fill_n(power, size, std::numeric_limits<float>::quiet_NaN());
|
std::fill_n(power, size, std::numeric_limits<float>::quiet_NaN());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeatMapGUI::createImage(int width, int height)
|
||||||
|
{
|
||||||
|
if (!m_image.isNull()) {
|
||||||
|
m_painter.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (m_settings.m_mode != HeatMapSettings::None)
|
||||||
|
{
|
||||||
|
qDebug() << "HeatMapGUI::createImage" << width << "*" << height;
|
||||||
|
m_image = QImage(width, height, QImage::Format_ARGB32);
|
||||||
|
m_painter.begin(&m_image);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_image = QImage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
m_image = QImage();
|
||||||
|
QMessageBox::critical(this, "Heat Map", QString("Failed to allocate memory (width=%1 height=%2)").arg(m_width).arg(m_height));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeatMapGUI::clearImage()
|
void HeatMapGUI::clearImage()
|
||||||
@ -929,6 +991,10 @@ void HeatMapGUI::plotMap(float *power)
|
|||||||
|
|
||||||
void HeatMapGUI::plotPixel(int x, int y, double power)
|
void HeatMapGUI::plotPixel(int x, int y, double power)
|
||||||
{
|
{
|
||||||
|
if (m_image.isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Normalise to [0,1]
|
// Normalise to [0,1]
|
||||||
float powNorm = (power - m_settings.m_minPower) / (m_settings.m_maxPower - m_settings.m_minPower);
|
float powNorm = (power - m_settings.m_minPower) / (m_settings.m_maxPower - m_settings.m_minPower);
|
||||||
if (powNorm < 0) {
|
if (powNorm < 0) {
|
||||||
@ -1017,6 +1083,11 @@ void HeatMapGUI::makeUIConnections()
|
|||||||
QObject::connect(ui->displayPulseAverage, &QCheckBox::clicked, this, &HeatMapGUI::on_displayPulseAverage_clicked);
|
QObject::connect(ui->displayPulseAverage, &QCheckBox::clicked, this, &HeatMapGUI::on_displayPulseAverage_clicked);
|
||||||
QObject::connect(ui->displayPathLoss, &QCheckBox::clicked, this, &HeatMapGUI::on_displayPathLoss_clicked);
|
QObject::connect(ui->displayPathLoss, &QCheckBox::clicked, this, &HeatMapGUI::on_displayPathLoss_clicked);
|
||||||
QObject::connect(ui->displayMins, QOverload<int>::of(&QSpinBox::valueChanged), this, &HeatMapGUI::on_displayMins_valueChanged);
|
QObject::connect(ui->displayMins, QOverload<int>::of(&QSpinBox::valueChanged), this, &HeatMapGUI::on_displayMins_valueChanged);
|
||||||
|
QObject::connect(ui->recordAverage, &QCheckBox::clicked, this, &HeatMapGUI::on_recordAverage_clicked);
|
||||||
|
QObject::connect(ui->recordMax, &QCheckBox::clicked, this, &HeatMapGUI::on_recordMax_clicked);
|
||||||
|
QObject::connect(ui->recordMin, &QCheckBox::clicked, this, &HeatMapGUI::on_recordMin_clicked);
|
||||||
|
QObject::connect(ui->recordPulseAverage, &QCheckBox::clicked, this, &HeatMapGUI::on_recordPulseAverage_clicked);
|
||||||
|
QObject::connect(ui->recordPathLoss, &QCheckBox::clicked, this, &HeatMapGUI::on_recordPathLoss_clicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeatMapGUI::updateAbsoluteCenterFrequency()
|
void HeatMapGUI::updateAbsoluteCenterFrequency()
|
||||||
@ -1171,11 +1242,33 @@ void HeatMapGUI::createMap()
|
|||||||
m_degreesLonPerPixel = m_resolution / scale / (earthCircumference / 360.0);
|
m_degreesLonPerPixel = m_resolution / scale / (earthCircumference / 360.0);
|
||||||
m_degreesLatPerPixel = m_resolution / (earthCircumference / 360.0);
|
m_degreesLatPerPixel = m_resolution / (earthCircumference / 360.0);
|
||||||
int size = m_width * m_height;
|
int size = m_width * m_height;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (m_settings.m_recordAverage) {
|
||||||
m_powerAverage = new float[size];
|
m_powerAverage = new float[size];
|
||||||
|
} else {
|
||||||
|
m_powerAverage = nullptr;
|
||||||
|
}
|
||||||
|
if (m_settings.m_recordPulseAverage) {
|
||||||
m_powerPulseAverage = new float[size];
|
m_powerPulseAverage = new float[size];
|
||||||
|
} else {
|
||||||
|
m_powerPulseAverage = nullptr;
|
||||||
|
}
|
||||||
|
if (m_settings.m_recordMax) {
|
||||||
m_powerMaxPeak = new float[size];
|
m_powerMaxPeak = new float[size];
|
||||||
|
} else {
|
||||||
|
m_powerMaxPeak = nullptr;
|
||||||
|
}
|
||||||
|
if (m_settings.m_recordMin) {
|
||||||
m_powerMinPeak = new float[size];
|
m_powerMinPeak = new float[size];
|
||||||
|
} else {
|
||||||
|
m_powerMinPeak = nullptr;
|
||||||
|
}
|
||||||
|
if (m_settings.m_recordPathLoss) {
|
||||||
m_powerPathLoss = new float[size];
|
m_powerPathLoss = new float[size];
|
||||||
|
} else {
|
||||||
|
m_powerPathLoss = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
m_north = m_latitude + m_degreesLatPerPixel * m_height / 2;
|
m_north = m_latitude + m_degreesLatPerPixel * m_height / 2;
|
||||||
m_south = m_latitude - m_degreesLatPerPixel * m_height / 2;
|
m_south = m_latitude - m_degreesLatPerPixel * m_height / 2;
|
||||||
@ -1184,8 +1277,13 @@ void HeatMapGUI::createMap()
|
|||||||
m_x = m_width / 2;
|
m_x = m_width / 2;
|
||||||
m_y = m_height / 2;
|
m_y = m_height / 2;
|
||||||
|
|
||||||
m_image = QImage(m_width, m_height, QImage::Format_ARGB32);
|
createImage(m_width, m_height);
|
||||||
m_painter.begin(&m_image);
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
deleteMap();
|
||||||
|
QMessageBox::critical(this, "Heat Map", QString("Failed to allocate memory (width=%1 height=%2)").arg(m_width).arg(m_height));
|
||||||
|
}
|
||||||
|
|
||||||
on_clearHeatMap_clicked();
|
on_clearHeatMap_clicked();
|
||||||
}
|
}
|
||||||
@ -1203,7 +1301,9 @@ void HeatMapGUI::deleteMap()
|
|||||||
m_powerMinPeak = nullptr;
|
m_powerMinPeak = nullptr;
|
||||||
delete[] m_powerPathLoss;
|
delete[] m_powerPathLoss;
|
||||||
m_powerPathLoss = nullptr;
|
m_powerPathLoss = nullptr;
|
||||||
|
if (!m_image.isNull()) {
|
||||||
m_painter.end();
|
m_painter.end();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeatMapGUI::resizeMap(int x, int y)
|
void HeatMapGUI::resizeMap(int x, int y)
|
||||||
@ -1245,12 +1345,34 @@ void HeatMapGUI::resizeMap(int x, int y)
|
|||||||
m_south -= m_blockSize * m_degreesLatPerPixel;
|
m_south -= m_blockSize * m_degreesLatPerPixel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float *powerAverage = nullptr;
|
||||||
|
float *powerPulseAverage = nullptr;
|
||||||
|
float *powerMaxPeak = nullptr;
|
||||||
|
float *powerMinPeak = nullptr;
|
||||||
|
float *powerPathLoss = nullptr;
|
||||||
|
|
||||||
int newSize = newWidth * newHeight;
|
int newSize = newWidth * newHeight;
|
||||||
float *powerAverage = new float[newSize];
|
qDebug() << "HeatMapGUI::resizeMap:" << m_width << "*" << m_height << "to" << newWidth << "*" << newHeight;
|
||||||
float *powerPulseAverage = new float[newSize];
|
|
||||||
float *powerMaxPeak = new float[newSize];
|
try
|
||||||
float *powerMinPeak = new float[newSize];
|
{
|
||||||
float *powerPathLoss = new float[newSize];
|
// Allocate new memory
|
||||||
|
if (m_settings.m_recordAverage) {
|
||||||
|
powerAverage = new float[newSize];
|
||||||
|
}
|
||||||
|
if (m_settings.m_recordPulseAverage) {
|
||||||
|
powerPulseAverage = new float[newSize];
|
||||||
|
}
|
||||||
|
if (m_settings.m_recordMax) {
|
||||||
|
powerMaxPeak = new float[newSize];
|
||||||
|
}
|
||||||
|
if (m_settings.m_recordMin) {
|
||||||
|
powerMinPeak = new float[newSize];
|
||||||
|
}
|
||||||
|
if (m_settings.m_recordPathLoss) {
|
||||||
|
powerPathLoss = new float[newSize];
|
||||||
|
}
|
||||||
|
|
||||||
clearPower(powerAverage, newSize);
|
clearPower(powerAverage, newSize);
|
||||||
clearPower(powerPulseAverage, newSize);
|
clearPower(powerPulseAverage, newSize);
|
||||||
clearPower(powerMaxPeak, newSize);
|
clearPower(powerMaxPeak, newSize);
|
||||||
@ -1264,13 +1386,29 @@ void HeatMapGUI::resizeMap(int x, int y)
|
|||||||
int srcEnd = (j + 1) * m_width;
|
int srcEnd = (j + 1) * m_width;
|
||||||
int destStart = j * newWidth + yOffset + xOffset;
|
int destStart = j * newWidth + yOffset + xOffset;
|
||||||
//qDebug() << srcStart << srcEnd << destStart;
|
//qDebug() << srcStart << srcEnd << destStart;
|
||||||
|
if (powerAverage && m_powerAverage) {
|
||||||
std::copy(m_powerAverage + srcStart, m_powerAverage + srcEnd, powerAverage + destStart);
|
std::copy(m_powerAverage + srcStart, m_powerAverage + srcEnd, powerAverage + destStart);
|
||||||
|
}
|
||||||
|
if (powerPulseAverage && m_powerPulseAverage) {
|
||||||
std::copy(m_powerPulseAverage + srcStart, m_powerPulseAverage + srcEnd, powerPulseAverage + destStart);
|
std::copy(m_powerPulseAverage + srcStart, m_powerPulseAverage + srcEnd, powerPulseAverage + destStart);
|
||||||
|
}
|
||||||
|
if (powerMaxPeak && m_powerMaxPeak) {
|
||||||
std::copy(m_powerMaxPeak + srcStart, m_powerMaxPeak + srcEnd, powerMaxPeak + destStart);
|
std::copy(m_powerMaxPeak + srcStart, m_powerMaxPeak + srcEnd, powerMaxPeak + destStart);
|
||||||
|
}
|
||||||
|
if (powerMinPeak && m_powerMinPeak) {
|
||||||
std::copy(m_powerMinPeak + srcStart, m_powerMinPeak + srcEnd, powerMinPeak + destStart);
|
std::copy(m_powerMinPeak + srcStart, m_powerMinPeak + srcEnd, powerMinPeak + destStart);
|
||||||
|
}
|
||||||
|
if (powerPathLoss && m_powerPathLoss) {
|
||||||
std::copy(m_powerPathLoss + srcStart, m_powerPathLoss + srcEnd, powerPathLoss + destStart);
|
std::copy(m_powerPathLoss + srcStart, m_powerPathLoss + srcEnd, powerPathLoss + destStart);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createImage(newWidth, newHeight);
|
||||||
|
|
||||||
|
m_width = newWidth;
|
||||||
|
m_height = newHeight;
|
||||||
|
|
||||||
|
// Delete old memory
|
||||||
delete[] m_powerAverage;
|
delete[] m_powerAverage;
|
||||||
delete[] m_powerPulseAverage;
|
delete[] m_powerPulseAverage;
|
||||||
delete[] m_powerMaxPeak;
|
delete[] m_powerMaxPeak;
|
||||||
@ -1280,13 +1418,20 @@ void HeatMapGUI::resizeMap(int x, int y)
|
|||||||
m_powerMaxPeak = powerMaxPeak;
|
m_powerMaxPeak = powerMaxPeak;
|
||||||
m_powerMinPeak = powerMinPeak;
|
m_powerMinPeak = powerMinPeak;
|
||||||
m_powerPathLoss = powerPathLoss;
|
m_powerPathLoss = powerPathLoss;
|
||||||
m_width = newWidth;
|
|
||||||
m_height = newHeight;
|
|
||||||
m_painter.end();
|
|
||||||
m_image = QImage(m_width, m_height, QImage::Format_ARGB32);
|
|
||||||
m_painter.begin(&m_image);
|
|
||||||
plotMap();
|
plotMap();
|
||||||
}
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
// Detete partially allocated memory
|
||||||
|
delete[] powerAverage;
|
||||||
|
delete[] powerPulseAverage;
|
||||||
|
delete[] powerMaxPeak;
|
||||||
|
delete[] powerMinPeak;
|
||||||
|
delete[] powerPathLoss;
|
||||||
|
QMessageBox::critical(this, "Heat Map", QString("Failed to allocate memory (width=%1 height=%2)").arg(newWidth).arg(newHeight));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeatMapGUI::plotPowerVsTimeChart()
|
void HeatMapGUI::plotPowerVsTimeChart()
|
||||||
@ -1462,3 +1607,37 @@ void HeatMapGUI::on_displayMins_valueChanged(int value)
|
|||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HeatMapGUI::on_recordAverage_clicked(bool checked)
|
||||||
|
{
|
||||||
|
m_settings.m_recordAverage = checked;
|
||||||
|
resizeMap(0, 0);
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeatMapGUI::on_recordMax_clicked(bool checked)
|
||||||
|
{
|
||||||
|
m_settings.m_recordMax = checked;
|
||||||
|
resizeMap(0, 0);
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeatMapGUI::on_recordMin_clicked(bool checked)
|
||||||
|
{
|
||||||
|
m_settings.m_recordMin = checked;
|
||||||
|
resizeMap(0, 0);
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeatMapGUI::on_recordPulseAverage_clicked(bool checked)
|
||||||
|
{
|
||||||
|
m_settings.m_recordPulseAverage = checked;
|
||||||
|
resizeMap(0, 0);
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeatMapGUI::on_recordPathLoss_clicked(bool checked)
|
||||||
|
{
|
||||||
|
m_settings.m_recordPathLoss = checked;
|
||||||
|
resizeMap(0, 0);
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
@ -142,7 +142,6 @@ private:
|
|||||||
void blockApplySettings(bool block);
|
void blockApplySettings(bool block);
|
||||||
void applySettings(bool force = false);
|
void applySettings(bool force = false);
|
||||||
void displaySettings();
|
void displaySettings();
|
||||||
void messageReceived(const QByteArray& message, const QDateTime& dateTime);
|
|
||||||
bool handleMessage(const Message& message);
|
bool handleMessage(const Message& message);
|
||||||
void makeUIConnections();
|
void makeUIConnections();
|
||||||
void updateAbsoluteCenterFrequency();
|
void updateAbsoluteCenterFrequency();
|
||||||
@ -158,6 +157,7 @@ private:
|
|||||||
void clearPower();
|
void clearPower();
|
||||||
void clearPower(float *power);
|
void clearPower(float *power);
|
||||||
void clearPower(float *power, int size);
|
void clearPower(float *power, int size);
|
||||||
|
void createImage(int width, int height);
|
||||||
void clearImage();
|
void clearImage();
|
||||||
void updatePower(double latitude, double longitude, float power);
|
void updatePower(double latitude, double longitude, float power);
|
||||||
void plotMap();
|
void plotMap();
|
||||||
@ -209,6 +209,11 @@ private slots:
|
|||||||
void on_displayPulseAverage_clicked(bool checked=false);
|
void on_displayPulseAverage_clicked(bool checked=false);
|
||||||
void on_displayPathLoss_clicked(bool checked=false);
|
void on_displayPathLoss_clicked(bool checked=false);
|
||||||
void on_displayMins_valueChanged(int value);
|
void on_displayMins_valueChanged(int value);
|
||||||
|
void on_recordAverage_clicked(bool checked=false);
|
||||||
|
void on_recordMax_clicked(bool checked=false);
|
||||||
|
void on_recordMin_clicked(bool checked=false);
|
||||||
|
void on_recordPulseAverage_clicked(bool checked=false);
|
||||||
|
void on_recordPathLoss_clicked(bool checked=false);
|
||||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||||
void onMenuDialogCalled(const QPoint& p);
|
void onMenuDialogCalled(const QPoint& p);
|
||||||
void handleInputMessages();
|
void handleInputMessages();
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>390</width>
|
<width>390</width>
|
||||||
<height>191</height>
|
<height>211</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
@ -800,13 +800,127 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_20">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="recordLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="recordLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Record</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="recordAverage">
|
||||||
|
<property name="statusTip">
|
||||||
|
<string>Check to record average power</string>
|
||||||
|
</property>
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Avg</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="recordMax">
|
||||||
|
<property name="statusTip">
|
||||||
|
<string>Check to record max power</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Max</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="recordMin">
|
||||||
|
<property name="statusTip">
|
||||||
|
<string>Check to record min power</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Min</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="recordPulseAverage">
|
||||||
|
<property name="statusTip">
|
||||||
|
<string>Check to record pulse average power</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Pulse</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="recordPathLoss">
|
||||||
|
<property name="statusTip">
|
||||||
|
<string>Check to record path loss</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Path Loss</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_9">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="dataContainer" native="true">
|
<widget class="QWidget" name="dataContainer" native="true">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>200</y>
|
<y>220</y>
|
||||||
<width>391</width>
|
<width>391</width>
|
||||||
<height>91</height>
|
<height>91</height>
|
||||||
</rect>
|
</rect>
|
||||||
@ -1349,7 +1463,7 @@
|
|||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>300</y>
|
<y>320</y>
|
||||||
<width>381</width>
|
<width>381</width>
|
||||||
<height>121</height>
|
<height>121</height>
|
||||||
</rect>
|
</rect>
|
||||||
@ -1617,7 +1731,6 @@
|
|||||||
</tabstops>
|
</tabstops>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../../sdrgui/resources/res.qrc"/>
|
<include location="../../../sdrgui/resources/res.qrc"/>
|
||||||
<include location="../demodadsb/icons.qrc"/>
|
|
||||||
</resources>
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
@ -50,6 +50,11 @@ void HeatMapSettings::resetToDefaults()
|
|||||||
m_displayPulseAverage = true;
|
m_displayPulseAverage = true;
|
||||||
m_displayPathLoss = true;
|
m_displayPathLoss = true;
|
||||||
m_displayMins = 2;
|
m_displayMins = 2;
|
||||||
|
m_recordAverage = true;
|
||||||
|
m_recordMax = true;
|
||||||
|
m_recordMin = true;
|
||||||
|
m_recordPulseAverage = true;
|
||||||
|
m_recordPathLoss = true;
|
||||||
m_rgbColor = QColor(102, 40, 220).rgb();
|
m_rgbColor = QColor(102, 40, 220).rgb();
|
||||||
m_title = "Heat Map";
|
m_title = "Heat Map";
|
||||||
m_streamIndex = 0;
|
m_streamIndex = 0;
|
||||||
@ -86,6 +91,11 @@ QByteArray HeatMapSettings::serialize() const
|
|||||||
s.writeBool(18, m_displayPulseAverage);
|
s.writeBool(18, m_displayPulseAverage);
|
||||||
s.writeBool(19, m_displayPathLoss);
|
s.writeBool(19, m_displayPathLoss);
|
||||||
s.writeS32(20, m_displayMins);
|
s.writeS32(20, m_displayMins);
|
||||||
|
s.writeBool(40, m_recordAverage);
|
||||||
|
s.writeBool(41, m_recordMax);
|
||||||
|
s.writeBool(42, m_recordMin);
|
||||||
|
s.writeBool(43, m_recordPulseAverage);
|
||||||
|
s.writeBool(44, m_recordPathLoss);
|
||||||
|
|
||||||
s.writeU32(21, m_rgbColor);
|
s.writeU32(21, m_rgbColor);
|
||||||
s.writeString(22, m_title);
|
s.writeString(22, m_title);
|
||||||
@ -148,6 +158,11 @@ bool HeatMapSettings::deserialize(const QByteArray& data)
|
|||||||
d.readBool(18, &m_displayPulseAverage, true);
|
d.readBool(18, &m_displayPulseAverage, true);
|
||||||
d.readBool(19, &m_displayPathLoss, true);
|
d.readBool(19, &m_displayPathLoss, true);
|
||||||
d.readS32(20, &m_displayMins, 2);
|
d.readS32(20, &m_displayMins, 2);
|
||||||
|
d.readBool(40, &m_recordAverage, true);
|
||||||
|
d.readBool(41, &m_recordMax, true);
|
||||||
|
d.readBool(42, &m_recordMin, true);
|
||||||
|
d.readBool(43, &m_recordPulseAverage, true);
|
||||||
|
d.readBool(44, &m_recordPathLoss, true);
|
||||||
|
|
||||||
d.readU32(21, &m_rgbColor, QColor(102, 40, 220).rgb());
|
d.readU32(21, &m_rgbColor, QColor(102, 40, 220).rgb());
|
||||||
d.readString(22, &m_title, "Heat Map");
|
d.readString(22, &m_title, "Heat Map");
|
||||||
|
@ -57,6 +57,11 @@ struct HeatMapSettings
|
|||||||
bool m_displayPulseAverage;
|
bool m_displayPulseAverage;
|
||||||
bool m_displayPathLoss;
|
bool m_displayPathLoss;
|
||||||
int m_displayMins;
|
int m_displayMins;
|
||||||
|
bool m_recordAverage;
|
||||||
|
bool m_recordMax;
|
||||||
|
bool m_recordMin;
|
||||||
|
bool m_recordPulseAverage;
|
||||||
|
bool m_recordPathLoss;
|
||||||
|
|
||||||
quint32 m_rgbColor;
|
quint32 m_rgbColor;
|
||||||
QString m_title;
|
QString m_title;
|
||||||
|
Loading…
Reference in New Issue
Block a user