Files
cudaSDR/Source/src/GL/cusdr_oglDistancePanel.cpp
T
2015-04-04 16:53:58 -04:00

2761 lines
76 KiB
C++

/**
* @file cusdr_oglDistancePanel.cpp
* @brief distance panel class for cuSDR
* @author Hermann von Hasseln, DL3HVH
* @version 0.1
* @date 2012-02-14
*/
/*
* Copyright 2012 Hermann von Hasseln, DL3HVH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2 as
* published by the Free Software Foundation
*
* 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 Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#define LOG_GRAPHICS
#include "cusdr_oglDistancePanel.h"
//#include <QtGui>
//#include <QDebug>
////#include <QFileInfo>
//#include <QTimer>
//#include <QImage>
//#include <QString>
//#include <QGLFramebufferObject>
#ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE 0x809D
#endif
QGLDistancePanel::QGLDistancePanel(QWidget *parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers|QGL::AlphaChannel), parent)
, set(Settings::instance())
, m_serverMode(set->getCurrentServerMode())
, m_hwInterface(set->getHWInterface())
, m_dataEngineState(QSDR::DataEngineDown)
, m_panMode(set->getPanadapterMode(0))
, m_mousePos(QPoint(-1, -1))
, m_mouseDownPos(QPoint(-1, -1))
, m_specAveragingCnt(set->getSpectrumAveragingCnt(0))
, m_freqRulerDisplayWidth(0)
, m_panSpectrumMinimumHeight(70)
, m_spectrumUpdate(false)
, m_showZerodBmLine(false)
, m_spectrumVertexColorUpdate(false)
, m_spectrumColorsChanged(true)
, m_showChirpFFT(false)
, m_spectrumAveraging(set->getSpectrumAveraging(0))
, m_spectrumAveragingOld(m_spectrumAveraging)
, m_crossHairCursor(false)
, m_panGrid(set->getPanGridStatus(0))
, m_freqRulerPosition(0.5)
, m_distRulerDisplayDelta(0.0)
, m_distRulerDisplayDeltaStep(500.0)
, m_distRulerMaxDist(150000.0)
, m_freqScaleZoomFactor(1.0f)
, m_distScaleZoomFactor(1.0) // 0.2 .. 1.0
, m_scaleMult(1.0f)
, m_filterLowerFrequency(-3050.0)
, m_filterUpperFrequency(-150.0)
, m_snapMouse(3)
, m_sampleRate(set->getSampleRate())
, m_downRate(set->getChirpDownSampleRate())
, m_chirpBufferLength(set->getChirpBufferLength())
{
// QGL::setPreferredPaintEngine(QPaintEngine::OpenGL);
setAutoBufferSwap(true);
setAutoFillBackground(false);
setMouseTracking(true);
setFocusPolicy(Qt::StrongFocus);
setupDisplayRegions(size());
m_oldWidth = size().width();
m_rxDataList = set->getReceiverDataList();
//m_frequency = m_rxDataList.at(0).frequency;
m_frequency = m_rxDataList.at(0).vfoFrequency;
m_dBmScalePanadapterRenew = true;
m_dBmScalePanadapterUpdate = true;
m_freqScalePanadapterRenew = true;
m_freqScalePanadapterUpdate = true;
m_panGridRenew = true;
m_panGridUpdate = true;
HamBand band = m_rxDataList.at(0).hamBand;
m_dBmPanMin = m_rxDataList.at(0).dBmPanScaleMinList.at(band);
m_dBmPanMax = m_rxDataList.at(0).dBmPanScaleMaxList.at(band);
m_filterLowerFrequency = m_rxDataList.at(0).filterLo;
m_filterUpperFrequency = m_rxDataList.at(0).filterHi;
fonts = new CFonts(this);
m_fonts = fonts->getFonts();
m_oglTextTiny = new OGLText(m_fonts.tinyFont);
m_oglTextSmall = new OGLText(m_fonts.smallFont);
m_oglTextNormal = new OGLText(m_fonts.normalFont);
timer = 0;
setupConnections();
m_displayTime.start();
m_resizeTime.start();
//freqChangeTimer.start();
memset(m_spectrumBuffer, -10000, 4 * BUFFER_SIZE * sizeof(float));
memset(m_distanceSpectrumBuffer, -10000, 16 * BUFFER_SIZE * sizeof(float));
m_kilometersPerGate = 0.5f * 3E5 / (m_sampleRate/m_downRate);
m_dBmPanLogGain = 69; // allow user to calibrate this value
m_dBmDistMin = set->getdBmDistScaleMin();
m_dBmDistMax = set->getdBmDistScaleMax();
m_dBmDistScaleMin = m_dBmDistMin;
m_dBmDistScaleMax = m_dBmDistMax;
m_panSpectrumBinsLength = 0;
/*m_bkgRed = (GLfloat)(set->getPanadapterColors().panBackgroundColor.red() / 256.0);
m_bkgGreen = (GLfloat)(set->getPanadapterColors().panBackgroundColor.green() / 256.0);
m_bkgBlue = (GLfloat)(set->getPanadapterColors().panBackgroundColor.blue() / 256.0);*/
m_red = (GLfloat)(set->getPanadapterColors().panLineColor.red() / 256.0);
m_green = (GLfloat)(set->getPanadapterColors().panLineColor.green() / 256.0);
m_blue = (GLfloat)(set->getPanadapterColors().panLineColor.blue() / 256.0);
m_redF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.red() / 256.0);
m_greenF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.green() / 256.0);
m_blueF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.blue() / 256.0);
m_redST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.red() / 256.0);
m_greenST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.green() / 256.0);
m_blueST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.blue() / 256.0);
m_redSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.red() / 256.0);
m_greenSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.green() / 256.0);
m_blueSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.blue() / 256.0);
m_frequencyScaleFBO = 0;
m_dBmScaleFBO = 0;
m_panadapterGridFBO = 0;
m_textureFBO = 0;
if (m_specAveragingCnt > 0)
m_scale = 1.0f / m_specAveragingCnt;
else
m_scale = 1.0f;
memset(m_tmpBuf, 0, SAMPLE_BUFFER_SIZE * sizeof(float));
updateGL();
}
QGLDistancePanel::~QGLDistancePanel() {
disconnect(set, 0, this, 0);
makeCurrent();
glFinish();
if (m_frequencyScaleFBO) {
delete m_frequencyScaleFBO;
m_frequencyScaleFBO = 0;
}
if (m_textureFBO) {
delete m_textureFBO;
m_textureFBO = 0;
}
if (m_dBmScaleFBO) {
delete m_dBmScaleFBO;
m_dBmScaleFBO = 0;
}
if (m_panadapterGridFBO) {
delete m_panadapterGridFBO;
m_panadapterGridFBO = 0;
}
while (!specAv_queue.isEmpty())
specAv_queue.dequeue();
}
//QSize QGLDistancePanel::minimumSizeHint() const {
//
// //return QSize(1000, 1024);
// return QSize(width(), height());
//}
QSize QGLDistancePanel::sizeHint() const {
return QSize(width(), height());
}
void QGLDistancePanel::setupConnections() {
CHECKED_CONNECT(
set,
SIGNAL(systemStateChanged(
QObject *,
QSDR::_Error,
QSDR::_HWInterfaceMode,
QSDR::_ServerMode,
QSDR::_DataEngineState)),
this,
SLOT(systemStateChanged(
QObject *,
QSDR::_Error,
QSDR::_HWInterfaceMode,
QSDR::_ServerMode,
QSDR::_DataEngineState)));
CHECKED_CONNECT(
set,
SIGNAL(graphicModeChanged(
QObject *,
int,
PanGraphicsMode,
WaterfallColorMode)),
this,
SLOT(graphicModeChanged(
QObject *,
int,
PanGraphicsMode,
WaterfallColorMode)));
CHECKED_CONNECT(
set,
SIGNAL(freqRulerPositionChanged(float, int)),
this,
SLOT(freqRulerPositionChanged(float, int)));
CHECKED_CONNECT(
set,
SIGNAL(sampleRateChanged(QObject *, int)),
this,
SLOT(sampleRateChanged(QObject *, int)));
CHECKED_CONNECT(
set,
SIGNAL(filterFrequenciesChanged(QObject *, int, qreal, qreal)),
this,
SLOT(setFilterFrequencies(QObject *, int, qreal, qreal)));
CHECKED_CONNECT_OPT(
set,
SIGNAL(chirpSpectrumBufferChanged(int, qint64, const float *)),
this,
SLOT(distanceSpectrumBufferChanged(int, qint64, const float *)),
Qt::DirectConnection);
CHECKED_CONNECT(
set,
SIGNAL(chirpFFTShowChanged(bool)),
this,
SLOT(setChirpFFTShow(bool)));
CHECKED_CONNECT(
set,
SIGNAL(waterfallTimeChanged(int, int)),
this,
SLOT(setWaterfallTime(int, int)));
CHECKED_CONNECT(
set,
SIGNAL(waterfallOffesetLoChanged(int, int)),
this,
SLOT(setWaterfallOffesetLo(int, int)));
CHECKED_CONNECT(
set,
SIGNAL(waterfallOffesetHiChanged(int, int)),
this,
SLOT(setWaterfallOffesetHi(int, int)));
CHECKED_CONNECT(
set,
SIGNAL(spectrumAveragingChanged(bool)),
this,
SLOT(setSpectrumAveraging(bool)));
CHECKED_CONNECT(
set,
SIGNAL(spectrumAveragingCntChanged(int)),
this,
SLOT(setSpectrumAveragingCnt(int)));
CHECKED_CONNECT(
set,
SIGNAL(panGridStatusChanged(bool)),
this,
SLOT(setPanGridStatus(bool)));
CHECKED_CONNECT(
set,
SIGNAL(panadapterColorChanged()),
this,
SLOT(setPanadapterColors()));
}
void QGLDistancePanel::initializeGL() {
if (!isValid()) return;
/*QOpenGLInfo glInfo;
glInfo.getInfo();
glInfo.printSelf();*/
//*****************************************************************
// default initialization
//glShadeModel(GL_FLAT);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
//glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
m_cnt = 0;
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
void QGLDistancePanel::paintGL() {
switch (m_serverMode) {
case QSDR::SDRMode:
drawGLRect(QRect(0, 0, width(), height()), QColor(0, 0, 0));
break;
case QSDR::ChirpWSPR:
case QSDR::ChirpWSPRFile:
//if (freqChangeTimer.elapsed() > 50) m_spectrumAveraging = m_spectrumAveragingOld;
if (m_resizeTime.elapsed() > 100 || m_dataEngineState == QSDR::DataEngineDown) {
paintReceiverDisplay();
paintChirpWSPRDisplay();
}
break;
default:
break;
}
}
//****************************************************
// painting modes
void QGLDistancePanel::paintReceiverDisplay() {
QRect mouse_rect(0, 0, 100, 100);
mouse_rect.moveCenter(m_mousePos);
drawPanadapter();
drawPanHorizontalScale();
drawPanVerticalScale();
if (m_panGrid)
drawPanadapterGrid();
drawPanFilter();
if (m_mouseRegion == panadapterRegion && m_crossHairCursor)
drawCrossHair();
m_oldFreq = m_frequency;
}
void QGLDistancePanel::paintChirpWSPRDisplay() {
//drawGLBackground(m_distanceSpectrumRect);
distanceSpectrumBufferMutex.lock();
drawDistanceSpectrum();
distanceSpectrumBufferMutex.unlock();
drawDistHorizontalScale();
drawDistVerticalScale();
//// chirp distance spectrum
//m_distancePanadapter->drawGLDistanceRuler(
// m_freqScaleDistancePanRect,
// m_freqScalePanadapterRect,
// m_mouseRegion,
// m_distRulerZoomFactor,
// m_distRulerDisplayDelta,
// m_kilometersPerGate,
// m_showChirpFFT,
// m_chirpBufferLength);
//m_distancePanadapter->drawGLdBmScale(
// m_dBmScaleDistancePanRect,
// m_distanceSpectrumRect,
// m_mouseRegion,
// m_dBmDistScaleMin,
// m_dBmDistScaleMax,
// m_showZerodBmLine);
//m_distancePanadapter->drawGLGrid(m_distanceSpectrumRect, m_dBmScaleDistancePanRect);
}
void QGLDistancePanel::drawPanadapter() {
GLint vertexArrayLength = (GLint)m_panadapterBins.size();
GLint height = m_panRect.height();
GLint x1 = m_panRect.left();
GLint y1 = m_panRect.top();
GLint x2 = x1 + m_panRect.width();
GLint y2 = y1 + m_panRect.height();
// y scale
float yScale;
float yScaleColor;
float yTop;
qreal dBmRange = qAbs(m_dBmPanMax - m_dBmPanMin);
yScale = m_panRect.height() / dBmRange;
//yScaleColor = 4.0f / dBmRange;
yScaleColor = 10.0f / dBmRange;
yTop = (float) y2;
if (m_dataEngineState == QSDR::DataEngineUp)
glClear(GL_DEPTH_BUFFER_BIT);
else
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_MULTISAMPLE);
glEnable(GL_LINE_SMOOTH);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glLineWidth(1);
// draw background
if (m_dataEngineState == QSDR::DataEngineUp) {
if (m_panGrid) {
glBegin(GL_TRIANGLE_STRIP);
glColor3f(0.15f, 0.15f, 0.3f); glVertex3f(x1, y1, -3.0); // top left corner
glColor3f(0.15f, 0.15f, 0.3f); glVertex3f(x2, y1, -3.0); // top right corner
glColor3f(0.15f, 0.15f, 0.51f); glVertex3f(x1, y2, -3.0); // bottom left corner
glColor3f(0.15f, 0.15f, 0.61f); glVertex3f(x2, y2, -3.0); // bottom right corner
glEnd();
}
else {
glBegin(GL_TRIANGLE_STRIP);
glColor3f(0.05f, 0.05f, 0.2f); glVertex3f(x1, y1, -3.0); // top left corner
glColor3f(0.05f, 0.05f, 0.2f); glVertex3f(x2, y1, -3.0); // top right corner
glColor3f(0.05f, 0.05f, 0.31f); glVertex3f(x1, y2, -3.0); // bottom left corner
glColor3f(0.05f, 0.05f, 0.41f); glVertex3f(x2, y2, -3.0); // bottom right corner
glEnd();
}
}
else {
drawGLRect(m_panRect, QColor(30, 30, 50, 155), -3.0f);
}
//glBegin(GL_TRIANGLE_STRIP);
//glColor3f(m_bkgRed, m_bkgGreen, m_bkgBlue); glVertex3f(x1, y1, -3.0); // top left corner
//glColor3f(m_bkgRed, m_bkgGreen, m_bkgBlue); glVertex3f(x2, y1, -3.0); // top right corner
//glColor3f(m_bkgRed * 1.2, m_bkgGreen * 1.2, m_bkgBlue * 1.2); glVertex3f(x1, y2, -3.0); // bottom left corner
//glColor3f(m_bkgRed * 1.6, m_bkgGreen * 1.6, m_bkgBlue * 1.6); glVertex3f(x2, y2, -3.0); // bottom right corner
//glEnd();
// set a scissor box
glScissor(x1, size().height() - y2, x2, height);
glEnable(GL_SCISSOR_TEST);
TGL3float *vertexArray = new TGL3float[vertexArrayLength];
TGL3float *vertexColorArray = new TGL3float[vertexArrayLength];
TGL3float *vertexArrayBg = new TGL3float[2*vertexArrayLength];
TGL3float *vertexColorArrayBg = new TGL3float[2*vertexArrayLength];
switch (m_panMode) {
case (PanGraphicsMode) FilledLine:
for (int i = 0; i < vertexArrayLength; i++) {
mutex.lock();
vertexColorArrayBg[2*i].x = m_redF;
vertexColorArrayBg[2*i].y = m_greenF;
vertexColorArrayBg[2*i].z = m_blueF;
vertexColorArrayBg[2*i+1].x = 0.3 * m_redF;
vertexColorArrayBg[2*i+1].y = 0.3 * m_greenF;
vertexColorArrayBg[2*i+1].z = 0.3 * m_blueF;
vertexColorArray[i].x = m_red * (yScaleColor * m_panadapterBins.at(i));
vertexColorArray[i].y = m_green * (yScaleColor * m_panadapterBins.at(i));
vertexColorArray[i].z = m_blue * (yScaleColor * m_panadapterBins.at(i));
mutex.unlock();
vertexArrayBg[2*i].x = (GLfloat)(i/m_scaleMult);
vertexArrayBg[2*i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i));
vertexArrayBg[2*i].z = -2.5;
vertexArrayBg[2*i+1].x = (GLfloat)(i/m_scaleMult);
vertexArrayBg[2*i+1].y = (GLfloat)yTop;
vertexArrayBg[2*i+1].z = -2.5;
vertexArray[i].x = (GLfloat)(i/m_scaleMult);
vertexArray[i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i));
vertexArray[i].z = -1.0;
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertexArrayBg);
glColorPointer(3, GL_FLOAT, 0, vertexColorArrayBg);
glDrawArrays(GL_QUAD_STRIP, 0, 2*vertexArrayLength);
glVertexPointer(3, GL_FLOAT, 0, vertexArray);
glColorPointer(3, GL_FLOAT, 0, vertexColorArray);
glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
delete[] vertexArray;
delete[] vertexColorArray;
delete[] vertexArrayBg;
delete[] vertexColorArrayBg;
break;
case (PanGraphicsMode) Line:
for (int i = 0; i < vertexArrayLength; i++) {
mutex.lock();
vertexColorArray[i].x = m_red * (yScaleColor * m_panadapterBins.at(i));
vertexColorArray[i].y = m_green * (yScaleColor * m_panadapterBins.at(i));
vertexColorArray[i].z = m_blue * (yScaleColor * m_panadapterBins.at(i));
mutex.unlock();
vertexArray[i].x = (GLfloat)(i/m_scaleMult);
vertexArray[i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i));
vertexArray[i].z = -1.0;
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertexArray);
glColorPointer(3, GL_FLOAT, 0, vertexColorArray);
glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
delete[] vertexArray;
delete[] vertexColorArray;
delete[] vertexArrayBg;
delete[] vertexColorArrayBg;
break;
case (PanGraphicsMode) Solid:
glDisable(GL_MULTISAMPLE);
glDisable(GL_LINE_SMOOTH);
for (int i = 0; i < vertexArrayLength; i++) {
mutex.lock();
vertexColorArrayBg[2*i].x = m_redST;
vertexColorArrayBg[2*i].y = m_greenST;
vertexColorArrayBg[2*i].z = m_blueST;
vertexColorArrayBg[2*i+1].x = m_redSB;
vertexColorArrayBg[2*i+1].y = m_greenSB;
vertexColorArrayBg[2*i+1].z = m_blueSB;
mutex.unlock();
vertexArrayBg[2*i].x = (GLfloat)(i/m_scaleMult);
vertexArrayBg[2*i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i));
vertexArrayBg[2*i].z = -2.0f;
vertexArrayBg[2*i+1].x = (GLfloat)(i/m_scaleMult);
vertexArrayBg[2*i+1].y = (GLfloat)yTop;
vertexArrayBg[2*i+1].z = -2.0f;
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertexArrayBg);
glColorPointer(3, GL_FLOAT, 0, vertexColorArrayBg);
//glDrawArrays(GL_QUAD_STRIP, 0, 2*vertexArrayLength);
glDrawArrays(GL_LINES, 0, 2*vertexArrayLength);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
//glEnable(GL_MULTISAMPLE);
//glEnable(GL_LINE_SMOOTH);
delete[] vertexArray;
delete[] vertexColorArray;
delete[] vertexArrayBg;
delete[] vertexColorArrayBg;
break;
}
glDisable(GL_MULTISAMPLE);
glDisable(GL_LINE_SMOOTH);
// disable scissor box
glDisable(GL_SCISSOR_TEST);
}
void QGLDistancePanel::drawPanVerticalScale() {
if (!m_dBmScalePanRect.isValid()) return;
int width = m_dBmScalePanRect.width();
int height = m_dBmScalePanRect.height();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glColor3f(0.65f, 0.76f, 0.81f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
if (!m_dBmScaleFBO || m_dBmScalePanadapterUpdate || m_dBmScalePanadapterRenew) {
if (!m_dBmScaleFBO || m_dBmScalePanadapterRenew) {
if (m_dBmScaleFBO) {
delete m_dBmScaleFBO;
m_dBmScaleFBO = 0;
}
m_dBmScaleFBO = new QGLFramebufferObject(width, height);
}
m_dBmScaleFBO->bind();
renderPanVerticalScale();
m_dBmScaleFBO->release();
m_dBmScalePanadapterUpdate = false;
m_dBmScalePanadapterRenew = false;
}
renderTexture(m_dBmScalePanRect, m_dBmScaleFBO->texture(), 0.0f);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColor3f(0.65f, 0.76f, 0.81f);
}
void QGLDistancePanel::drawPanHorizontalScale() {
if (!m_freqScalePanRect.isValid()) return;
int width = m_freqScalePanRect.width();
int height = m_freqScalePanRect.height();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glColor3f(0.65f, 0.76f, 0.81f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
if (!m_frequencyScaleFBO || m_freqScalePanadapterUpdate || m_freqScalePanadapterRenew) {
if (!m_frequencyScaleFBO || m_freqScalePanadapterRenew) {
if (m_frequencyScaleFBO) {
delete m_frequencyScaleFBO;
m_frequencyScaleFBO = 0;
}
m_frequencyScaleFBO = new QGLFramebufferObject(width, height);
}
glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0, 0, width, height);
setProjectionOrthographic(width, height);
m_frequencyScaleFBO->bind();
renderPanHorizontalScale();
m_frequencyScaleFBO->release();
glPopAttrib();
glViewport(0, 0, size().width(), size().height());
setProjectionOrthographic(size().width(), size().height());
m_freqScalePanadapterUpdate = false;
m_freqScalePanadapterRenew = false;
}
renderTexture(m_freqScalePanRect, m_frequencyScaleFBO->texture(), 0.0f);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColor3f(0.65f, 0.76f, 0.81f);
}
void QGLDistancePanel::drawPanadapterGrid() {
if (!m_panRect.isValid()) return;
int width = m_panRect.width();
int height = m_panRect.height();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//glColor4f(0.35, 0.46, 0.51, 0.7);
//glColor4f(0.45, 0.56, 0.61, 1.0);
glColor4f(0.45f, 0.56f, 0.61f, 0.8f);
glDisable(GL_MULTISAMPLE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
if (!m_panadapterGridFBO || m_panGridUpdate || m_panGridRenew) {
if (!m_panadapterGridFBO || m_panGridRenew) {
if (m_panadapterGridFBO) {
delete m_panadapterGridFBO;
m_panadapterGridFBO = 0;
}
m_panadapterGridFBO = new QGLFramebufferObject(width, height);
}
glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0, 0, width, height);
setProjectionOrthographic(width, height);
m_panadapterGridFBO->bind();
renderPanadapterGrid();
m_panadapterGridFBO->release();
glPopAttrib();
glViewport(0, 0, size().width(), size().height());
setProjectionOrthographic(size().width(), size().height());
m_panGridUpdate = false;
m_panGridRenew = false;
}
//renderTexture(m_panRect, m_panadapterGridFBO->texture(), -2.0f);
//renderTexture(m_panRect, m_panadapterGridFBO->texture(), -1.5f);
renderTexture(m_panRect, m_panadapterGridFBO->texture(), -2.0f);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColor3f(0.65f, 0.76f, 0.81f);
glEnable(GL_MULTISAMPLE);
}
void QGLDistancePanel::drawPanFilter() {
qreal freqLo = m_filterLowerFrequency / m_sampleRate;
qreal freqHi = m_filterUpperFrequency / m_sampleRate;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
//glColor4f(0.65, 0.65, 0.65, 0.25);
QColor color = QColor(150, 150, 150, 100);
GLint x1 = m_panRect.left() + qRound((qreal)(m_panRect.width()/2.0f) + freqLo * m_panRect.width() / m_freqScaleZoomFactor);
GLint x2 = m_panRect.left() + qRound((qreal)(m_panRect.width()/2.0f) + freqHi * m_panRect.width() / m_freqScaleZoomFactor);
GLint y1 = m_panRect.top() + 1;
GLint y2 = m_panRect.top() + m_panRect.height() - 1;
QRect filterRect = QRect(x1, y1, x2 - x1, y2 - y1);
if ((x1 >= m_panRect.left() && x1 <= m_panRect.right()) ||
(x2 >= m_panRect.left() && x2 <= m_panRect.right()) ||
(x1 < m_panRect.left() && x2 > m_panRect.right()))
{
if (filterRect.height() > 5)
drawGLRect(filterRect, color, 3.0);
}
// draw a line for the display center
y1 = m_panRect.top() + 3;
y2 = m_panRect.top() + (m_panRect.height() - 3);
if (y2 > y1 + 3) {
GLint x = m_panRect.width()/2;
color = set->getPanadapterColors().panCenterLineColor;
//glDisable(GL_LINE_SMOOTH);
glDisable(GL_MULTISAMPLE);
glLineWidth(1);
glColor4ub(color.red(), color.green(), color.blue(), color.alpha());
glBegin(GL_LINES);
/*glVertex2i(x, y1);
glVertex2i(x, y2);*/
glVertex3f(x, y1, 4.0f);
glVertex3f(x, y2, 4.0f);
glEnd();
glEnable(GL_MULTISAMPLE);
}
}
void QGLDistancePanel::drawCrossHair() {
QRect rect(0, m_panRect.top(), width(), height() - m_panRect.top());
int x = m_mousePos.x();
int y = m_mousePos.y();
glDisable(GL_MULTISAMPLE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_LINE_SMOOTH);
glLineWidth(1.0f);
qglColor(QColor(255, 255, 255, 80));
// set a scissor box
glScissor(rect.left(), rect.top(), rect.width() - 1, rect.height());
glEnable(GL_SCISSOR_TEST);
// horizontal line
glBegin(GL_LINES);
glVertex3f(m_dBmScalePanRect.right() - 2, y, 4.0f);
glVertex3f(rect.right() - 1, y, 4.0f);
glEnd();
// vertical line
glBegin(GL_LINES);
glVertex3f(x, rect.top() + 1, 4.0f);
glVertex3f(x, rect.bottom() - 1, 4.0f);
glEnd();
// cross hair
qglColor(QColor(255, 255, 255, 180));
glBegin(GL_LINES);
glVertex3f(x , y - 20, 5.0f);
glVertex3f(x , y + 20, 5.0f);
glVertex3f(x - 20, y, 5.0f);
glVertex3f(x + 20, y, 5.0f);
glEnd();
// text only on panadapter
//if (m_mouseRegion == panadapterRegion) {
QString str;
qglColor(QColor(255, 255, 255, 255));
int dx = m_panRect.width()/2 - x;
qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width());
qreal df = unit * dx;
qreal frequency = m_frequency - df;
str = frequencyString(-df, true);
if (x > m_panRect.width() - 85)
m_oglTextSmall->renderText(x -90, y - 30, 5.0f, str);
else
m_oglTextSmall->renderText(x + 4, y - 30, 5.0f, str);
str = frequencyString(frequency);
if (x > m_panRect.width() - 85)
m_oglTextSmall->renderText(x - 90, y - 18, 5.0f, str);
else
m_oglTextSmall->renderText(x + 4, y - 18, 5.0f, str);
if (m_mouseRegion == panadapterRegion) {
qreal dBm = m_dBmPanMax - ((m_dBmPanMax - m_dBmPanMin) * ((qreal)(y - m_panRect.top()) / m_panRect.height()));
str = QString::number(dBm, 'f', 1) + " dBm";
if (x > m_panRect.width() - 85)
m_oglTextSmall->renderText(x - 90, y + 6, 5.0f, str);
else
m_oglTextSmall->renderText(x + 4, y + 6, 5.0f, str);
}
// disable scissor box
glDisable(GL_SCISSOR_TEST);
glEnable(GL_MULTISAMPLE);
}
//************
void QGLDistancePanel::drawDistanceSpectrum() {
//float yScale;
//float yScaleColor;
//float yTop;
float localMax;
GLint displayWidth = (GLint)m_distanceSpectrumRect.width();
double distScale = 0;
//freqScale = (float)m_sampleRate / rect.width();
//distScale = 1024.0f / rect.width();
distScale = (double)(1.0f * qRound(m_chirpBufferLength * m_distScaleZoomFactor) / m_distanceSpectrumRect.width());
if (distScale < 1.0) distScale = 1.0;
if (distScale < 0) {
drawGLRect(m_distanceSpectrumRect, Qt::black);
//GRAPHICS_DEBUG << "drawDistanceSpectrum bad distance scale:" << distScale;
return;
}
//qreal dBmRange = qAbs(dBmMax - dBmMin);
qreal dBmRange = (m_dBmDistMax - m_dBmDistMin) * m_distScaleZoomFactor;
float yScale = m_distanceSpectrumRect.height() / dBmRange;
//float yScaleColor = 2.0f / dBmRange;
float yTop = m_distanceSpectrumRect.top() + m_distanceSpectrumRect.height();
int idx = 0;
int lIdx = 0;
int rIdx = 0;
// set a scissor box
glScissor(m_distanceSpectrumRect.left(), size().height() - m_distanceSpectrumRect.bottom() - 1, m_distanceSpectrumRect.left() + m_distanceSpectrumRect.width(), m_distanceSpectrumRect.height());
glEnable(GL_SCISSOR_TEST);
GLint vertexArrayLength = 0;
/*if (m_vertexArray) {
delete [] m_vertexArray;
m_vertexArray = 0;
}
if (m_vertexColorArray) {
delete [] m_vertexColorArray;
m_vertexColorArray = 0;
}*/
glLineWidth(1);
glShadeModel(GL_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
vertexArrayLength = displayWidth;
TGL2float *vertexArray = new TGL2float[vertexArrayLength];
TGL3float *vertexColorArray = new TGL3float[vertexArrayLength];
//TGL3float *vertexArrayBg = new TGL3float[2*vertexArrayLength];
//TGL3float *vertexColorArrayBg = new TGL3float[2*vertexArrayLength];
//m_vertexArray = new TGL2float[vertexArrayLength];
//m_vertexColorArray = new TGL3float[vertexArrayLength];
m_redD = (GLfloat)(set->getPanadapterColors().distanceLineColor.red() / 256.0);
m_greenD = (GLfloat)(set->getPanadapterColors().distanceLineColor.green() / 256.0);
m_blueD = (GLfloat)(set->getPanadapterColors().distanceLineColor.blue() / 256.0);
/*m_rf = (GLfloat)(set->getPanadapterColors().panLineFilledColor.red() / 256.0);
m_gf = (GLfloat)(set->getPanadapterColors().panLineFilledColor.green() / 256.0);
m_bf = (GLfloat)(set->getPanadapterColors().panLineFilledColor.blue() / 256.0);*/
for (int i = 0; i < vertexArrayLength; i++) {
lIdx = (int)floor((qreal)(i * distScale));
rIdx = (int)floor((qreal)(i * distScale) + distScale);
// max value; later we try mean value also!
localMax = -10000.0F;
for (int j = lIdx; j < rIdx; j++) {
if (m_distanceSpectrumBuffer[j] > localMax) {
localMax = m_distanceSpectrumBuffer[j];
idx = j;
}
}
/*m_spectrumVertexColorArrayBg[2*i].x = 0.10;
m_spectrumVertexColorArrayBg[2*i].y = 0.20;
m_spectrumVertexColorArrayBg[2*i].z = 0.25;*/
vertexColorArray[i].x = m_redD;// * (yScaleColor * (m_distanceSpectrumBuffer[idx] - dBmMin));
vertexColorArray[i].y = m_greenD;// * (yScaleColor * (m_distanceSpectrumBuffer[idx] - dBmMin));
vertexColorArray[i].z = m_blueD;// * (yScaleColor * (m_distanceSpectrumBuffer[idx] - dBmMin));
vertexArray[i].x = i;
vertexArray[i].y = yTop - yScale * (m_distanceSpectrumBuffer[idx] - m_dBmDistMin);
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, vertexArray);
glColorPointer(3, GL_FLOAT, 0, vertexColorArray);
glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
delete[] vertexArray;
delete[] vertexColorArray;
// disable scissor box
glDisable(GL_SCISSOR_TEST);
}
void QGLDistancePanel::drawDistHorizontalScale() {
if (m_freqScaleDistancePanRect.isEmpty()) return;
//QFontMetrics d_fm(m_smallFont);
int rulerFontHeight;
int rulerFontMaxWidth;
double maxSpanDist;
if (m_showChirpFFT) {
rulerFontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0Hz").height();
rulerFontMaxWidth = m_fonts.smallFontMetrics->boundingRect("000000").width();
//maxSpanDist = m_sampleRate / 2;
maxSpanDist = m_sampleRate / 4;
//maxSpanDist = m_sampleRate;
}
else {
rulerFontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0kmM").height();
rulerFontMaxWidth = m_fonts.smallFontMetrics->boundingRect("0000000").width();
maxSpanDist = m_chirpBufferLength * m_kilometersPerGate;
}
qreal kilometerSpan = maxSpanDist * m_distScaleZoomFactor;
qreal lowerDist = 0;
qreal upperDist = 0;
if (m_showChirpFFT)
lowerDist = -maxSpanDist/2;
else {
lowerDist = m_dBmDistDelta;
if (lowerDist < 0.0) lowerDist = 0.0;
}
upperDist = lowerDist + kilometerSpan;
if (upperDist > maxSpanDist) {
upperDist = maxSpanDist;
lowerDist = maxSpanDist - kilometerSpan;
}
qreal unit = (float)(m_freqScaleDistancePanRect.width() / kilometerSpan);
m_distanceScale = getXRuler(m_freqScaleDistancePanRect, rulerFontMaxWidth, unit, lowerDist, upperDist);
// draw the scale background
drawGLScaleBackground(m_freqScaleDistancePanRect, Qt::black);
// draw the distance scale
int offset_X = -1;
int textOffset_y = 17;
double distScale = 1;
// char *str;
// if (m_showChirpFFT)
// str = " Hz ";
// else
// str = " km ";
QRect scaledTextRect(0, textOffset_y, 1, rulerFontHeight);
//scaledTextRect.setWidth(d_fm.width(str));
scaledTextRect.moveLeft(m_freqScaleDistancePanRect.width() - scaledTextRect.width());// - menu_pull_right_rect.width());
glColor3f(0.94f, 0.22f, 0.43f);
glRasterPos3f(m_freqScaleDistancePanRect.width() - 30, m_freqScaleDistancePanRect.top() + textOffset_y, 0.0);
//writeBitmapString(GLUT_BITMAP_HELVETICA_10, str);
if (m_mouseRegion == freqScaleDistancePanRegion)
glColor3f(0.8f, 0.92f, 0.97f);
else
glColor3f(0.65f, 0.76f, 0.81f);
int len = m_distanceScale.mainPointPositions.length();
if (len > 0) {
glLineWidth(3);
glBegin(GL_LINES);
for (int i = 0; i < len; i++) {
glVertex3f(m_distanceScale.mainPointPositions.at(i), m_freqScaleDistancePanRect.top() + 1, 0.0f); // origin of the line
glVertex3f(m_distanceScale.mainPointPositions.at(i), m_freqScaleDistancePanRect.top() + 4, 0.0f); // ending point of the line
}
glEnd();
for (int i = 0; i < len; i++) {
QString str = QString::number(m_distanceScale.mainPoints.at(i) / distScale, 'f', 0);
int textWidth = m_fonts.smallFontMetrics->width(str);
QRect textRect(m_distanceScale.mainPointPositions.at(i) + offset_X - (textWidth / 2), textOffset_y, textWidth, rulerFontHeight);
QByteArray ba = str.toLatin1();
char *cstr = ba.data();
if (textRect.left() < 0 || textRect.right() >= scaledTextRect.left()) continue;
glRasterPos3f(m_distanceScale.mainPointPositions.at(i) + offset_X - (textWidth / 2), m_freqScaleDistancePanRect.top() + textOffset_y, 0.0);
m_oglTextSmall->renderText(textRect.x(), textRect.y(), cstr);
//writeBitmapString(GLUT_BITMAP_HELVETICA_10, cstr);
}
}
len = m_distanceScale.subPointPositions.length();
if (len > 0) {
glLineWidth(1);
glBegin(GL_LINES);
for (int i = 0; i < len; i++) {
glVertex3f(m_distanceScale.subPointPositions.at(i), m_freqScaleDistancePanRect.top() + 1, 0.0f); // origin of the line
glVertex3f(m_distanceScale.subPointPositions.at(i), m_freqScaleDistancePanRect.top() + 3, 0.0f); // ending point of the line
}
glEnd();
}
}
void QGLDistancePanel::drawDistVerticalScale() {
/*const QRect &rect,
const QRect &distRect,
int region,
qreal dBmMin,
qreal dBmMax,
bool showZerodBmLine*/
if (m_dBmScaleDistancePanRect.isEmpty()) return;
//QFontMetrics d_fm(m_smallFont);
int spacing = 5;
int fontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0dBm").height() + spacing;
int fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("-000.0").width();
qreal dBmRange = qAbs(m_dBmDistScaleMax - m_dBmDistScaleMin);
//if (dBmRange <= 0) return;
qreal unit = (float)(m_dBmScaleDistancePanRect.height() / dBmRange);
m_dBmScale = getYRuler(m_dBmScaleDistancePanRect, fontHeight, unit, m_dBmDistScaleMin, m_dBmDistScaleMax);
// draw the scale background
drawGLScaleBackground(m_dBmScaleDistancePanRect, QColor(60, 60, 60, 80));
QRect textRect(0, 0, fontMaxWidth, fontHeight);
textRect.moveRight(14);
int yOld = -textRect.height();
if (m_mouseRegion == dBmScaleDistancePanRegion)
glColor3f(0.8f, 0.92f, 0.97f);
else
glColor3f(0.65f, 0.76f, 0.81f);
glLineWidth(1);
int len = m_dBmScale.mainPointPositions.length();
if (len > 0) {
glBegin(GL_LINES);
for (int i = 0; i < len; i++) {
glVertex3f(m_dBmScaleDistancePanRect.left(), m_dBmScale.mainPointPositions.at(i), 0.0f); // origin of the line
glVertex3f(m_dBmScaleDistancePanRect.left() + 4, m_dBmScale.mainPointPositions.at(i), 0.0f); // ending point of the line
}
glEnd();
for (int i = 0; i < len; i++) {
textRect.moveTop(m_dBmScale.mainPointPositions.at(i) + textRect.height()/3);
QString str;
if (textRect.y() >= yOld &&
textRect.bottom() <= (m_dBmScaleDistancePanRect.top() + m_dBmScaleDistancePanRect.height() - textRect.height()) &&
m_dBmScale.mainPointPositions.at(i) > 10 + m_dBmScaleDistancePanRect.top())
{
str = QString::number(m_dBmScale.mainPoints.at(i), 'f', 1);
QByteArray ba = str.toLatin1();
//char *cstr = ba.data();
glRasterPos3f(textRect.right() + m_dBmScaleDistancePanRect.left(), textRect.y(), 0.0);
//writeBitmapString(GLUT_BITMAP_TIMES_ROMAN_10, cstr);
yOld = textRect.bottom();
}
if (qRound(m_dBmScale.mainPoints.at(i)) == 0 && m_showZerodBmLine) {
int zerodBmLine = m_dBmScale.mainPointPositions.at(i);
if (zerodBmLine > m_dBmScaleDistancePanRect.top() && zerodBmLine < m_dBmScaleDistancePanRect.bottom()) {
glColor3f(0.2f, 0.87f, 0.87f);
glBegin(GL_LINES);
glVertex3f(m_distanceSpectrumRect.left(), zerodBmLine, 0.0f); // origin of the line
glVertex3f(m_distanceSpectrumRect.width() - m_dBmScaleDistancePanRect.width() + 4, zerodBmLine, 0.0f); // ending point of the line
glEnd();
if (m_mouseRegion == dBmScaleDistancePanRegion)
glColor3f(0.8f, 0.92f, 0.97f);
else
glColor3f(0.65f, 0.76f, 0.81f);
}
}
}
}
if (m_mouseRegion == dBmScaleDistancePanRegion)
glColor3f(0.5f, 0.62f, 0.67f);
else
glColor3f(0.35f, 0.46f, 0.51f);
if (m_dBmScale.subPointPositions.length() > 0) {
glBegin(GL_LINES);
for (int i = 0; i < m_dBmScale.subPointPositions.length(); i++) {
glVertex3f(m_dBmScaleDistancePanRect.left(), m_dBmScale.subPointPositions.at(i), 0.0f); // origin of the line
glVertex3f(m_dBmScaleDistancePanRect.left() + 2, m_dBmScale.subPointPositions.at(i), 0.0f); // ending point of the line
}
glEnd();
}
//char* s = "dBm";
textRect.moveTop(m_dBmScaleDistancePanRect.top() + m_dBmScaleDistancePanRect.height() - textRect.height());
glColor3f(0.94f, 0.22f, 0.43f);
//glRasterPos3f(textRect.left(), textRect.center().y(), 0.0);
//glRasterPos3f(textRect.right() + right, textRect.center().y(), 0.0);
glRasterPos3f(textRect.right() + m_dBmScaleDistancePanRect.left(), textRect.center().y(), 0.0);
//writeBitmapString(GLUT_BITMAP_HELVETICA_10, s);
//glPushMatrix();
// glTranslatef(0.0, 0.0, 0.0);
// //glRotatef(45.0, 0.0, 0.0, 1.0);
// glScalef(0.25, 0.25, 0.25);
// writeStrokeString(GLUT_STROKE_ROMAN, s);
//glPopMatrix();
}
//**********************************************************************************************
// The algorithms of the scale functions renderPanVerticalScale() and renderPanHorizontalScale()
// are taken from SDRMAXIII (c) Catherine Moss, with permission.
void QGLDistancePanel::renderPanVerticalScale() {
QString str;
//QFontMetrics d_fm(m_smallFont);
//QFontMetrics d_fm(m_normalFont);
int spacing = 7;
int fontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0dBm").height() + spacing;
int fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("-000.0").width();
GLint width = m_dBmScalePanRect.width();
GLint height = m_dBmScalePanRect.height();
qreal unit = (qreal)(m_dBmScalePanRect.height() / qAbs(m_dBmPanMax - m_dBmPanMin));
m_dBmScale = getYRuler2(m_dBmScalePanRect, fontHeight, unit, m_dBmPanMin, m_dBmPanMax);
glClear(GL_COLOR_BUFFER_BIT);
QRect textRect(0, 0, fontMaxWidth, fontHeight);
textRect.moveLeft(3);
int yOld = -textRect.height();
int len = m_dBmScale.mainPointPositions.length();
int sublen = m_dBmScale.subPointPositions.length();
glViewport(0, 0, width, height);
setProjectionOrthographic(width, height);
// draw the scale background
drawGLScaleBackground(QRect(0, 0, width, height), QColor(30, 30, 30, 180));
if (len > 0) {
glColor3f(0.65f, 0.76f, 0.81f);
glLineWidth(1);
glBegin(GL_LINES);
for (int i = 0; i < len; i++) {
glVertex3f(width, m_dBmScale.mainPointPositions.at(i), 0.0f); // origin of the line
glVertex3f(width - 4, m_dBmScale.mainPointPositions.at(i), 0.0f); // ending point of the line
}
glEnd();
glColor3f(0.45f, 0.56f, 0.61f);
if (sublen > 0) {
glBegin(GL_LINES);
for (int i = 0; i < sublen; i++) {
glVertex3f(width, m_dBmScale.subPointPositions.at(i), 0.0f); // origin of the line
glVertex3f(width - 2, m_dBmScale.subPointPositions.at(i), 0.0f); // ending point of the line
}
glEnd();
}
glColor3f(0.75f, 0.86f, 0.91f);
for (int i = 0; i < len; i++) {
textRect.moveBottom(m_dBmScale.mainPointPositions.at(i) + textRect.height()/2);
if (textRect.y() >= yOld && textRect.bottom() <= (m_dBmScalePanRect.height() - textRect.height())) {
str = QString::number(m_dBmScale.mainPoints.at(i), 'f', 1);
m_oglTextSmall->renderText(textRect.x() + fontMaxWidth - m_fonts.smallFontMetrics->tightBoundingRect(str).width(), textRect.y(), str);
yOld = textRect.bottom();
}
}
}
textRect.moveTop(m_dBmScalePanRect.height() - textRect.height());
glColor3f(0.94f, 0.22f, 0.43f);
str = QString("dBm");
m_oglTextSmall->renderText(textRect.x(), textRect.y(), str);
glViewport(0, 0, size().width(), size().height());
setProjectionOrthographic(size().width(), size().height());
}
void QGLDistancePanel::renderPanHorizontalScale() {
//GRAPHICS_DEBUG << "render frequency scale";
//QFontMetrics d_fm(m_smallFont);
int fontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0kMGHz").height();
int fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("000.000.0").width();
qreal freqSpan = (qreal)(m_sampleRate * m_freqScaleZoomFactor);
qreal lowerFreq = (qreal)m_frequency - freqSpan / 2;
qreal upperFreq = (qreal)m_frequency + freqSpan / 2;
qreal unit = (qreal)(m_freqScalePanRect.width() / freqSpan);
m_frequencyScale = getXRuler(m_freqScalePanRect, fontMaxWidth, unit, lowerFreq, upperFreq);
// draw the frequency scale
int offset_X = -1;
int textOffset_y = 5;
double freqScale = 1;
QString fstr = QString(" Hz ");
if (upperFreq >= 1e6) { freqScale = 1e6; fstr = QString(" MHz "); }
else
if (upperFreq >= 1e3) { freqScale = 1e3; fstr = QString(" kHz "); }
// draw the scale background
drawGLScaleBackground(QRect(0, 0, m_freqScalePanRect.width(), m_freqScalePanRect.height()), QColor(0, 0, 0, 255));
QRect scaledTextRect(0, textOffset_y, 1, m_freqScalePanRect.height());
scaledTextRect.setWidth(m_fonts.smallFontMetrics->width(fstr));
scaledTextRect.moveLeft(m_freqScalePanRect.width() - scaledTextRect.width());
glColor3f(0.65f, 0.76f, 0.81f);
int len = m_frequencyScale.mainPointPositions.length();
if (len > 0) {
glLineWidth(3);
glBegin(GL_LINES);
for (int i = 0; i < len; i++) {
glVertex3f(m_frequencyScale.mainPointPositions.at(i), 1.0f, 0.0f);
glVertex3f(m_frequencyScale.mainPointPositions.at(i), 4.0f, 0.0f);
}
glEnd();
for (int i = 0; i < len; i++) {
QString str = QString::number(m_frequencyScale.mainPoints.at(i) / freqScale, 'f', 3);
if (i > 0) {
double delta = m_frequencyScale.mainPoints.at(i) - m_frequencyScale.mainPoints.at(i-1);
if (delta < 1000.0)
str = QString::number(m_frequencyScale.mainPoints.at(i) / freqScale, 'f', 4);
else
if (freqScale == 1e3)
while (str.endsWith('0')) str.remove(str.size() - 1, 1);
}
if (str.endsWith('.')) str.remove(str.size() - 1, 1);
int text_width = m_fonts.smallFontMetrics->width(str);
QRect textRect(m_frequencyScale.mainPointPositions.at(i) + offset_X - (text_width / 2), textOffset_y, text_width, fontHeight);
if (textRect.left() < 0 || textRect.right() >= scaledTextRect.left()) continue;
m_oglTextSmall->renderText(textRect.x(), textRect.y(), str);
}
}
if (m_frequencyScale.subPointPositions.length() > 0) {
glLineWidth(1);
glBegin(GL_LINES);
for (int i = 0; i < m_frequencyScale.subPointPositions.length(); i++) {
glVertex3f(m_frequencyScale.subPointPositions.at(i), 1.0f, 0.0f);
glVertex3f(m_frequencyScale.subPointPositions.at(i), 3.0f, 0.0f);
}
glEnd();
}
glColor3f(0.94f, 0.22f, 0.43f);
m_oglTextSmall->renderText(m_freqScalePanRect.width() - 30, textOffset_y, fstr);
}
void QGLDistancePanel::renderPanadapterGrid() {
//GRAPHICS_DEBUG << "render panadapter grid";
//glLineStipple(1, 0xCCCC);
glClear(GL_COLOR_BUFFER_BIT);
glLineStipple(1, 0x9999);
glEnable(GL_LINE_STIPPLE);
glLineWidth(1.0f);
// vertical lines
int len = m_frequencyScale.mainPointPositions.length();
if (len > 0) {
GLint x1 = m_panRect.left();
GLint x2 = 1;
if (m_dBmScalePanRect.isValid()) x2 += m_dBmScalePanRect.width();
//GLint y1 = rect.top() + 1;
GLint y1 = 1;
GLint y2 = m_panRect.bottom() - 1;
TGL2int *vertexArray = new TGL2int[len * 2];
int vertexArrayLen = 0;
TGL2int point1, point2;
point1.y = y1;
point2.y = y2;
for (int i = 0; i < len; i++) {
GLint x = m_frequencyScale.mainPointPositions.at(i);
if (x < x2) continue;
x += x1;
point1.x = x;
point2.x = x;
vertexArray[vertexArrayLen++] = point1;
vertexArray[vertexArrayLen++] = point2;
}
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_INT, 0, vertexArray);
glDrawArrays(GL_LINES, 0, vertexArrayLen);
glDisableClientState(GL_VERTEX_ARRAY);
delete[] vertexArray;
}
// horizontal lines
len = m_dBmScale.mainPointPositions.length();
if (len > 0) {
TGL2float *vertexArray = new TGL2float[len * 2];
int vertexArrayLen = 0;
TGL2float point1, point2;
point1.x = m_panRect.left() + m_dBmScalePanRect.width();
point2.x = m_panRect.right();
for (int i = 0; i < len; i++) {
GLfloat y = m_dBmScale.mainPointPositions.at(i);
point1.y = y;
point2.y = y;
vertexArray[vertexArrayLen++] = point1;
vertexArray[vertexArrayLen++] = point2;
}
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, vertexArray);
glDrawArrays(GL_LINES, 0, vertexArrayLen);
glDisableClientState(GL_VERTEX_ARRAY);
delete[] vertexArray;
}
glDisable(GL_LINE_STIPPLE);
}
//********************************************************************
void QGLDistancePanel::getRegion(QPoint p) {
QRect mouse_rect(0, 0, 100, 100);
mouse_rect.moveCenter(p);
if (m_freqScalePanRect.contains(p)) {
m_mouseRegion = freqScalePanadapterRegion;
if (m_displayTime.elapsed() >= 50) {
m_displayTime.restart();
update();
}
}
else if (m_dBmScalePanRect.contains(p)) {
m_mouseRegion = dBmScalePanadapterRegion;
if (m_displayTime.elapsed() >= 50) {
m_displayTime.restart();
update();
}
}
else if (abs(p.x() - m_filterRect.left()) < m_snapMouse &&
m_panRect.contains(p)
) {
m_mouseRegion = filterRegionLow;
m_mouseDownFilterFrequencyLo = m_filterLowerFrequency;
}
else if (abs(p.x() - m_filterRect.right()) < m_snapMouse &&
m_panRect.contains(p)
) {
m_mouseRegion = filterRegionHigh;
m_mouseDownFilterFrequencyHi = m_filterUpperFrequency;
}
else if (m_panRect.contains(p)) {
m_mouseRegion = panadapterRegion;
if (m_displayTime.elapsed() >= 50) {
m_displayTime.restart();
update();
}
}
else if (m_freqScaleDistancePanRect.contains(p)) {
m_mouseRegion = freqScaleDistancePanRegion;
m_distRulerUpdate = true;
if (m_displayTime.elapsed() >= 50) {
m_displayTime.restart();
update();
}
}
else if (m_dBmScaleDistancePanRect.contains(p)) {
m_mouseRegion = dBmScaleDistancePanRegion;
if (m_displayTime.elapsed() >= 50) {
m_displayTime.restart();
update();
}
}
else if (m_distanceSpectrumRect.contains(p)) {
m_mouseRegion = distancePanRegion;
if (m_displayTime.elapsed() >= 50) {
m_displayTime.restart();
update();
}
}
else
m_mouseRegion = elsewhere;
/*if (m_displayTime.elapsed() >= 50) {
m_displayTime.restart();
updateGL();
update();
}*/
//GRAPHICS_DEBUG << "region" << m_mouseRegion;
}
void QGLDistancePanel::resizeGL(int iWidth, int iHeight) {
int width = (int)(iWidth/2) * 2;
int height = iHeight;
if (width != m_oldWidth) {
m_freqScalePanadapterRenew = true;
m_panGridRenew = true;
m_oldWidth = width;
}
m_spectrumVertexColorUpdate = true;
//m_displayData.size = QSize(width, height);
glFinish();
m_resizeTime.restart();
setupDisplayRegions(QSize(width, height));
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
setProjectionOrthographic(width, height);
}
void QGLDistancePanel::setupDisplayRegions(QSize size) {
m_displayTop = 0;
int freqScaleRectHeight = 20;
int dBmScaleWidth = 45;
int distScaleRectHeight = 20;
m_freqScalePanRect = QRect(
0,
m_displayTop + qRound((size.height() - m_displayTop - freqScaleRectHeight) * m_freqRulerPosition),
size.width(),
freqScaleRectHeight);
m_panRect = QRect(
0,
m_displayTop,
size.width(),
m_freqScalePanRect.top() - m_displayTop);
if (m_panRect.height() != m_oldPanRectHeight) {
m_dBmScalePanadapterRenew = true;
m_panGridRenew = true;
}
m_oldPanRectHeight = m_panRect.height();
m_panRectWidth = (GLint)m_panRect.width();
m_freqScaleDistancePanRect = QRect(
0,
size.height() - m_displayTop - distScaleRectHeight + 1,
size.width(),
distScaleRectHeight);
m_distanceSpectrumRect = QRect(
m_freqScalePanRect.left(),
m_freqScalePanRect.bottom(),
m_freqScalePanRect.width(),
size.height() - m_displayTop - m_freqScalePanRect.bottom() - distScaleRectHeight + 1);
m_distancePanRect = QRect(
m_freqScalePanRect.left(),
m_freqScalePanRect.bottom(),
m_freqScalePanRect.width(),
size.height() - m_displayTop - m_freqScalePanRect.bottom() - distScaleRectHeight + 1);
m_dBmScaleDistancePanRect = QRect(
m_distanceSpectrumRect.right() - dBmScaleWidth,
m_freqScalePanRect.bottom(),
dBmScaleWidth,
size.height() - m_displayTop - m_freqScalePanRect.bottom() - distScaleRectHeight + 1);
m_dBmScalePanRect = QRect(
m_panRect.left(),
m_displayTop,
45,
m_panRect.height());
m_freqScalePanadapterUpdate = true;
m_dBmScalePanadapterUpdate = true;
m_panGridUpdate = true;
//***************************************************************************
/*GRAPHICS_DEBUG << "***************************************************************************";
GRAPHICS_DEBUG << "total size" << size.height();
GRAPHICS_DEBUG << "sizes (top, bottom, height):";
GRAPHICS_DEBUG << "panRect: " << m_panRect.top() << " " << m_panRect.bottom() << " " << m_panRect.height();
GRAPHICS_DEBUG << "freqScalePanRect: " << m_freqScalePanRect.top() << " " << m_freqScalePanRect.bottom() << " " << m_freqScalePanRect.height();
GRAPHICS_DEBUG << "dBmScalePanRect: " << m_dBmScalePanRect.top() << " " << m_dBmScalePanRect.bottom() << " " << m_dBmScalePanRect.height();
GRAPHICS_DEBUG << "m_distanceSpectrumRect: " << m_distanceSpectrumRect.top() << " " << m_distanceSpectrumRect.bottom() << " " << m_distanceSpectrumRect.height();
GRAPHICS_DEBUG << "m_freqScaleDistancePanRect: " << m_freqScaleDistancePanRect.top() << " " << m_freqScaleDistancePanRect.bottom() << " " << m_freqScaleDistancePanRect.height();
GRAPHICS_DEBUG << "m_dBmScaleDistancePanRect: " << m_dBmScaleDistancePanRect.top() << " " << m_dBmScaleDistancePanRect.bottom() << " " << m_dBmScaleDistancePanRect.height();
GRAPHICS_DEBUG << "";*/
}
void QGLDistancePanel::saveGLState() {
glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
}
void QGLDistancePanel::restoreGLState() {
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPopAttrib();
}
//********************************************************************
// HMI control
void QGLDistancePanel::enterEvent(QEvent *event) {
setFocus(Qt::MouseFocusReason);
m_mousePos = QPoint(-1, -1);
m_mouseRegion = elsewhere;
update();
QGLWidget::enterEvent(event);
}
void QGLDistancePanel::leaveEvent(QEvent *event) {
m_mousePos = QPoint(-1, -1);
m_mouseRegion = elsewhere;
update();
QGLWidget::leaveEvent(event);
}
void QGLDistancePanel::wheelEvent(QWheelEvent* event) {
//GRAPHICS_DEBUG << "wheelEvent";
QPoint pos = event->pos();
if (event->buttons() == Qt::NoButton) getRegion(pos);
double freqStep = set->getMouseWheelFreqStep(0);
switch (m_mouseRegion) {
case panadapterRegion:
double delta = 0;
if (event->delta() < 0) delta = -freqStep;
else
if (event->delta() > 0) delta = freqStep;
if (m_frequency + delta > MAXFREQUENCY)
m_frequency = MAXFREQUENCY;
else
if (m_frequency + delta < 0)
m_frequency = 0;
else
// snap to the frequency step
m_frequency = (long)(qRound((m_frequency + delta) / qAbs(freqStep)) * qAbs(freqStep));
//set->setFrequency(this, true, 0, m_frequency);
set->setVFOFrequency(this, 0, 0, m_frequency);
/*if (m_spectrumAveragingOld) {
m_spectrumAveragingOld = true;
m_spectrumAveraging = false;
freqChangeTimer.restart();
}*/
break;
}
//updateGL();
update();
}
void QGLDistancePanel::mousePressEvent(QMouseEvent* event) {
//GRAPHICS_DEBUG << "mousePressEvent";
m_mousePos = event->pos();
m_mouseDownPos = m_mousePos;
getRegion(m_mousePos);
if (m_mouseRegion == panadapterRegion) {
if (event->buttons() == Qt::RightButton) {
if (m_crossHairCursor) {
m_crossHairCursor = false;
setCursor(Qt::ArrowCursor);
}
else {
m_crossHairCursor = true;
setCursor(Qt::BlankCursor);
}
}
else if (event->buttons() == Qt::LeftButton && m_crossHairCursor) {
double freqStep = set->getMouseWheelFreqStep(0);
int dx = m_panRect.width()/2 - m_mousePos.x();
qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width());
m_frequency -= unit * dx;
m_frequency = (long)(qRound(m_frequency / qAbs(freqStep)) * qAbs(freqStep));
//set->setFrequency(this, true, 0, m_frequency);
set->setVFOFrequency(this, 0, 0, m_frequency);
update();
}
}
else if (m_mouseRegion == freqScalePanadapterRegion) {
m_rulerMouseDownPos = m_freqScalePanRect.topLeft();
if (event->buttons() == Qt::RightButton) setCursor(Qt::SplitHCursor);
update();
return;
}
else if (m_mouseRegion == freqScaleDistancePanRegion) {
m_rulerMouseDownPos = m_freqScaleDistancePanRect.topLeft();
if (event->buttons() == Qt::RightButton) setCursor(Qt::SplitHCursor);
update();
return;
}
else if (m_mouseRegion == dBmScalePanadapterRegion) {
m_rulerMouseDownPos = m_dBmScaleDistancePanRect.topLeft();
if (event->buttons() == Qt::RightButton) setCursor(Qt::SplitVCursor);
update();
return;
}
else if (m_mouseRegion == dBmScaleDistancePanRegion) {
m_rulerMouseDownPos = m_dBmScaleDistancePanRect.topLeft();
if (event->buttons() == Qt::RightButton) setCursor(Qt::SplitVCursor);
update();
return;
}
update();
}
void QGLDistancePanel::mouseReleaseEvent(QMouseEvent *event) {
//GRAPHICS_DEBUG << "mouseReleaseEvent";
m_mousePos = event->pos();
m_mouseDownPos = m_mousePos;
getRegion(m_mousePos);
if (m_mouseRegion == freqScalePanadapterRegion) {
return;
}
else if (m_mouseRegion == freqScaleDistancePanRegion) {
return;
}
else if (m_mouseRegion == dBmScaleDistancePanRegion) {
if (event->button() == Qt::LeftButton && m_showZerodBmLine) {
m_showZerodBmLine = false;
}
else if (event->button() == Qt::RightButton) {
}
update();
return;
}
update();
}
void QGLDistancePanel::mouseMoveEvent(QMouseEvent* event) {
//GRAPHICS_DEBUG << "mouseMoveEvent";
QPoint pos = event->pos();
m_mousePos = event->pos();
if (event->buttons() == Qt::NoButton) getRegion(pos);
switch (m_mouseRegion) {
case distancePanRegion:
//GRAPHICS_DEBUG << "distancePanRegion";
setCursor(Qt::ArrowCursor);
//update();
break;
case panadapterRegion:
//GRAPHICS_DEBUG << "panadapterRegion Rx:" << m_receiver;
if (m_crossHairCursor)
setCursor(Qt::BlankCursor);
else
setCursor(Qt::ArrowCursor);
if (event->buttons() == Qt::LeftButton) {
QPoint dPos = m_mouseDownPos - pos;
qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_freqScalePanRect.width());
qreal deltaFreq = unit * dPos.x();
long newFrequency = m_frequency + deltaFreq;
if (newFrequency > MAXFREQUENCY)
newFrequency = MAXFREQUENCY;
else
if (newFrequency + deltaFreq < 0)
newFrequency = 0;
else
m_frequency += deltaFreq;
//set->setFrequency(this, true, 0, m_frequency);
set->setVFOFrequency(this, 0, 0, m_frequency);
m_mouseDownPos = pos;
}
//update();
break;
case dBmScalePanadapterRegion:
//GRAPHICS_DEBUG << "dBmScalePanadapterRegion";
if (event->buttons() == Qt::LeftButton) {
QPoint dPos = m_mouseDownPos - pos;
qreal unit = (qreal)(qAbs(m_dBmPanMax - m_dBmPanMin) / m_panRect.height());
qreal newMin = m_dBmPanMin - unit * dPos.y();
qreal newMax = m_dBmPanMax - unit * dPos.y();
if (newMin > MINDBM && newMax < MAXDBM) {
m_dBmPanMin = newMin;
m_dBmPanMax = newMax;
set->setdBmPanScaleMin(0, m_dBmPanMin);
set->setdBmPanScaleMax(0, m_dBmPanMax);
}
m_mouseDownPos = pos;
m_dBmScalePanadapterUpdate = true;
m_panGridUpdate = true;
}
else
if (event->buttons() == Qt::RightButton) {
QPoint dPos = m_mouseDownPos - pos;
if (dPos.y() > 0)
m_dBmPanDelta = 1.0;
else if (dPos.y() < 0)
m_dBmPanDelta = -1.0f;
m_dBmPanMin += m_dBmPanDelta;
m_dBmPanMax -= m_dBmPanDelta;
if (qAbs(m_dBmPanMax - m_dBmPanMin) < 10) {
m_dBmPanMin -= m_dBmPanDelta;
m_dBmPanMax += m_dBmPanDelta;
}
if (m_dBmPanMin < MINDBM) m_dBmPanMin = MINDBM;
if (m_dBmPanMax > MAXDBM) m_dBmPanMax = MAXDBM;
set->setdBmPanScaleMin(0, m_dBmPanMin);
set->setdBmPanScaleMax(0, m_dBmPanMax);
m_mouseDownPos = pos;
m_dBmScalePanadapterUpdate = true;
m_panGridUpdate = true;
}
else
setCursor(Qt::ArrowCursor);
//update();
break;
case dBmScaleDistancePanRegion:
//GRAPHICS_DEBUG << "dBmScaleDistancePanRegion";
if (event->buttons() == Qt::LeftButton &&
event->modifiers() == Qt::ControlModifier) {
m_showZerodBmLine = true;
QPoint dPos = m_mouseDownPos - pos;
qreal unit = (qreal)(qAbs(m_dBmDistScaleMax - m_dBmDistScaleMin) / m_distanceSpectrumRect.height());
qreal newMin = m_dBmDistScaleMin - unit * dPos.y();
qreal newMax = m_dBmDistScaleMax - unit * dPos.y();
if (newMin > MINDISTDBM && newMax < MAXDISTDBM) {
m_dBmDistScaleMin = newMin;
m_dBmDistScaleMax = newMax;
}
m_mouseDownPos = pos;
}
else
if (event->buttons() == Qt::LeftButton) {
QPoint dPos = m_mouseDownPos - pos;
qreal unit = (qreal)(qAbs(m_dBmDistMax - m_dBmDistMin) / m_distanceSpectrumRect.height());
qreal newMin = m_dBmDistMin - unit * dPos.y();
qreal newMax = m_dBmDistMax - unit * dPos.y();
if (newMin > MINDISTDBM && newMax < MAXDISTDBM) {
m_dBmDistMin = newMin;
m_dBmDistMax = newMax;
}
m_mouseDownPos = pos;
m_dBmDistScaleMin = m_dBmDistMin;
m_dBmDistScaleMax = m_dBmDistMax;
}
else
if (event->buttons() == Qt::RightButton) {
QPoint dPos = m_mouseDownPos - pos;
if (dPos.y() > 0)
m_dBmDistDelta = 1.0;
else if (dPos.y() < 0)
m_dBmDistDelta = -1.0f;
m_dBmDistMin += m_dBmDistDelta;
m_dBmDistMax -= m_dBmDistDelta;
if (qAbs(m_dBmDistMax - m_dBmDistMin) < 10) {
m_dBmDistMin -= m_dBmDistDelta;
m_dBmDistMax += m_dBmDistDelta;
}
if (m_dBmDistMin < MINDISTDBM) m_dBmDistMin = MINDISTDBM;
if (m_dBmDistMax > MAXDISTDBM) m_dBmDistMax = MAXDISTDBM;
m_dBmDistScaleMin = m_dBmDistMin;
m_dBmDistScaleMax = m_dBmDistMax;
m_mouseDownPos = pos;
}
else
setCursor(Qt::ArrowCursor);
//update();
break;
case freqScalePanadapterRegion:
//GRAPHICS_DEBUG << "freqScalePanadapterRegion Rx" << m_receiver;
if (event->buttons() == Qt::LeftButton) {
QPoint dPos = m_mouseDownPos - pos;
int bottom_y = height() - m_freqScalePanRect.height();
int new_y = m_rulerMouseDownPos.y() - dPos.y();
if (new_y < m_panRect.top() + m_panSpectrumMinimumHeight)
new_y = m_panRect.top() + m_panSpectrumMinimumHeight;
if (new_y > bottom_y)
new_y = bottom_y;
m_freqRulerPosition = (float)(new_y - m_panRect.top()) / (bottom_y - m_panRect.top());
set->setFreqRulerPosition(this, 0, m_freqRulerPosition);
}
else
if (event->buttons() == Qt::RightButton) {
QPoint dPos = m_mouseDownPos - pos;
if (dPos.x() > 0)
m_freqScaleZoomFactor += 0.01;
else if (dPos.x() < 0)
m_freqScaleZoomFactor -= 0.01;
if (m_freqScaleZoomFactor > 1.0) m_freqScaleZoomFactor = 1.0;
//if (m_freqScaleZoomFactor < 0.05) m_freqScaleZoomFactor = 0.05;
if (m_freqScaleZoomFactor < 0.15) m_freqScaleZoomFactor = 0.15;
m_mouseDownPos = pos;
m_freqScalePanadapterUpdate = true;
m_panGridUpdate = true;
}
else
setCursor(Qt::ArrowCursor);
//update();
break;
case freqScaleDistancePanRegion:
//GRAPHICS_DEBUG << "freqScaleDistancePanRegion";
if (event->buttons() == Qt::LeftButton) {
if (m_distScaleZoomFactor < 1.0) {
QPoint dPos = m_mouseDownPos - pos;
if (dPos.x() > 0)
m_distRulerDisplayDelta += m_distRulerDisplayDeltaStep;
else if (dPos.x() < 0)
m_distRulerDisplayDelta -= m_distRulerDisplayDeltaStep;
if (m_distRulerDisplayDelta < 0)
m_distRulerDisplayDelta = 0.0;
if (m_distRulerDisplayDelta > m_chirpBufferLength * m_kilometersPerGate)
m_distRulerDisplayDelta -= m_distRulerDisplayDeltaStep;
m_mouseDownPos = pos;
}
else
m_distRulerDisplayDelta = 0.0;
}
else if (event->buttons() == Qt::RightButton) {
QPoint dPos = m_mouseDownPos - pos;
if (dPos.x() > 0)
m_distScaleZoomFactor += 0.005;
else if (dPos.x() < 0)
m_distScaleZoomFactor -= 0.005;
if (m_distScaleZoomFactor > 1.0) m_distScaleZoomFactor = 1.0;
if (m_distScaleZoomFactor < 0.1) m_distScaleZoomFactor = 0.1;
m_mouseDownPos = pos;
}
else
setCursor(Qt::ArrowCursor);
//update();
break;
case filterRegionLow:
setCursor(Qt::SizeHorCursor);
if (event->buttons() == Qt::LeftButton) {
QPoint dPos = m_mouseDownPos - pos;
qreal dFreq = (qreal)(dPos.x() * m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width();
m_filterLowerFrequency = qRound(m_mouseDownFilterFrequencyLo - dFreq);
set->setRXFilter(this, 0, m_filterLowerFrequency, m_filterUpperFrequency);
}
break;
case filterRegionHigh:
setCursor(Qt::SizeHorCursor);
if (event->buttons() == Qt::LeftButton) {
QPoint dPos = m_mouseDownPos - pos;
qreal dFreq = (qreal)(dPos.x() * m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width();
m_filterUpperFrequency = qRound(m_mouseDownFilterFrequencyHi - dFreq);
set->setRXFilter(this, 0, m_filterLowerFrequency, m_filterUpperFrequency);
}
break;
case elsewhere:
//GRAPHICS_DEBUG << "elsewhere";
//update();
break;
}
if (m_displayTime.elapsed() >= 50) {
m_displayTime.restart();
update();
}
//setupDisplayRegions(size());
//update();
//locker.unlock();
}
void QGLDistancePanel::keyPressEvent(QKeyEvent* event) {
//GRAPHICS_DEBUG << "keyPressEvent";
if (event->key() == Qt::Key_Control) {
//m_keyCTRLpressed = true;
//GRAPHICS_DEBUG << "m_keyCTRLpressed =" << m_keyCTRLpressed;
//printf("Ry %f\n",ry);
//ry+=10.0f;
}
else if (event->key() == Qt::Key_T) {
//printf("Ry %f\n",ry);
//ry-=10.0f;
}
else if (event->key() == Qt::Key_P) {
//drawTeapot = !drawTeapot;
}
else if (event->key() == Qt::Key_W) {
//approach -= 0.1f;
}
else if (event->key() == Qt::Key_S) {
//approach += 0.1f;
}
else {
//m_keyCTRLpressed = false;
//GRAPHICS_DEBUG << "m_keyCTRLpressed =" << m_keyCTRLpressed;
//event->ignore();
}
QWidget::keyPressEvent(event);
//updateGL();
update();
}
void QGLDistancePanel::timerEvent(QTimerEvent *) {
update();
}
//********************************************************************
void QGLDistancePanel::setFrequency(QObject *sender, bool value, long freq) {
Q_UNUSED(sender)
Q_UNUSED(value)
m_frequency = freq;
//m_displayData.frequency = freq;
m_freqScalePanadapterUpdate = true;
m_panGridUpdate = true;
//updateGL();
update();
}
void QGLDistancePanel::setFilterFrequencies(QObject *sender, int rx, qreal lo, qreal hi) {
Q_UNUSED(sender)
if (rx == 0) {
m_filterLowerFrequency = lo;
m_filterUpperFrequency = hi;
}
update();
}
void QGLDistancePanel::freqRulerPositionChanged(float pos, int rx) {
if (rx == 0) {
m_freqRulerPosition = pos;
setupDisplayRegions(size());
update();
}
}
void QGLDistancePanel::setSpectrumBuffer(const float *buffer) {
if (m_spectrumAveraging) {
QVector<float> m_specBuf(SAMPLE_BUFFER_SIZE);
//spectrumBufferMutex.lock();
memcpy(
(float *) m_specBuf.data(),
(float *) &buffer[0],
SAMPLE_BUFFER_SIZE * sizeof(float));
specAv_queue.enqueue(m_specBuf);
if (specAv_queue.size() <= m_specAveragingCnt) {
for (int i = 0; i < SAMPLE_BUFFER_SIZE; i++)
m_tmpBuf[i] += specAv_queue.last().data()[i];
//spectrumBufferMutex.unlock();
return;
}
for (int i = 0; i < SAMPLE_BUFFER_SIZE; i++) {
m_tmpBuf[i] -= specAv_queue.first().at(i);
m_tmpBuf[i] += specAv_queue.last().at(i);
m_avgBuf[i] = m_tmpBuf[i] * m_scale;
}
computeDisplayBins(m_avgBuf);
specAv_queue.dequeue();
//spectrumBufferMutex.unlock();
}
else
computeDisplayBins(buffer);
}
void QGLDistancePanel::computeDisplayBins(const float *panBuffer) {
int newSampleSize = 0;
int deltaSampleSize = 0;
int idx = 0;
int lIdx = 0;
int rIdx = 0;
qreal localMax;
if (m_serverMode == QSDR::ChirpWSPRFile) {
newSampleSize = (int)floor(2 * BUFFER_SIZE * m_freqScaleZoomFactor);
deltaSampleSize = 2 * BUFFER_SIZE - newSampleSize;
}
else {
newSampleSize = (int)floor(4 * BUFFER_SIZE * m_freqScaleZoomFactor);
deltaSampleSize = 4 * BUFFER_SIZE - newSampleSize;
}
/*if (deltaSampleSize%2 != 0) {
deltaSampleSize += 1;
newSampleSize -= 1;
}*/
m_panScale = (qreal)(1.0 * newSampleSize / m_panRectWidth);
m_scaleMultOld = m_scaleMult;
if (m_panScale < 0.125) {
m_scaleMult = 0.0625;
}
else if (m_panScale < 0.25) {
m_scaleMult = 0.125;
}
else if (m_panScale < 0.5) {
m_scaleMult = 0.25;
}
else if (m_panScale < 1.0) {
m_scaleMult = 0.5;
}
else {
m_scaleMult = 1.0;
}
m_panSpectrumBinsLength = (GLint)(m_scaleMult * m_panRectWidth);
/*if (bins != binsOld) {
GRAPHICS_DEBUG << "newSampleSize" << newSampleSize;
GRAPHICS_DEBUG << "m_panScale" << m_panScale;
GRAPHICS_DEBUG << "bins:" << bins;
}*/
m_panadapterBins.clear();
for (int i = 0; i < m_panSpectrumBinsLength; i++) {
idx = 0;
lIdx = (int)floor((qreal)(i * m_panScale / m_scaleMult));
rIdx = (int)floor((qreal)(i * m_panScale / m_scaleMult) + m_panScale / m_scaleMult);
// max value; later we try mean value also!
localMax = -10000.0F;
for (int j = lIdx; j < rIdx; j++) {
if (panBuffer[j] > localMax) {
localMax = panBuffer[j];
idx = j;
}
}
idx += deltaSampleSize/2;
m_panadapterBins << panBuffer[idx] - m_dBmPanMin - m_dBmPanLogGain;
}
update();
}
void QGLDistancePanel::setDistanceSpectrumBuffer(int sampleRate, qint64 length, const float *buffer) {
Q_UNUSED(sampleRate)
Q_UNUSED(length)
Q_UNUSED(buffer)
}
void QGLDistancePanel::distanceSpectrumBufferChanged(int sampleRate, qint64 length, const float *buffer) {
Q_UNUSED(sampleRate)
distanceSpectrumBufferMutex.lock();
m_kilometersPerGate = 1.0f * 3E5 / sampleRate;
//m_kilometersPerGate = 0.5f * 3E5 / 12000;
m_chirpBufferLength = length;
memcpy(m_distanceSpectrumBuffer, buffer, m_chirpBufferLength * sizeof(float));
distanceSpectrumBufferMutex.unlock();
update();
}
// get waterfall colors - taken from PowerSDR/KISS Konsole
//QColor QGLDistancePanel::getWaterfallColorAtPixel(qreal value) {
//
// QColor color;
// //int r = 0; int g = 0; int b = 0;
// int r, g, b;
// int lowerThreshold = (int)m_dBmPanMin - m_waterfallOffsetLo;
// int upperThreshold = (int)m_dBmPanMax + m_waterfallOffsetHi;
//
// float offset;
// float globalRange;
// float localRange;
// float percent;
//
// switch (m_waterColorScheme) {
//
// case QSDRGraphics::simple:
//
// if (value <= lowerThreshold)
// color = m_waterfallLoColor;
// else
// if (value >= upperThreshold)
// color = QColor(255, 255, 255);//m_waterfallHiColor;
// else {
//
// percent = (value - lowerThreshold) / (upperThreshold - lowerThreshold);
// if (percent <= 0.5) { // use a gradient between low and mid colors
//
// percent *= 2;
//
// r = (int)((1 - percent) * m_waterfallLoColor.red() + percent * m_waterfallMidColor.red());
// g = (int)((1 - percent) * m_waterfallLoColor.green() + percent * m_waterfallMidColor.green());
// b = (int)((1 - percent) * m_waterfallLoColor.blue() + percent * m_waterfallMidColor.blue());
// }
// else { // use a gradient between mid and high colors
//
// percent = (float)(percent - 0.5) * 2;
//
// r = (int)((1 - percent) * m_waterfallMidColor.red() + percent * 255);//m_waterfallHiColor.red());
// g = (int)((1 - percent) * m_waterfallMidColor.green() + percent * 255);//m_waterfallHiColor.green());
// b = (int)((1 - percent) * m_waterfallMidColor.blue() + percent * 255);//m_waterfallHiColor.blue());
// }
//
// if (r > 255) r = 255;
// if (g > 255) g = 255;
// if (b > 255) b = 255;
// color = QColor(r, g, b, m_waterfallAlpha);
// }
//
// break;
//
// case QSDRGraphics::enhanced:
//
// if (value <= lowerThreshold)
// color = m_waterfallLoColor;
// else
// if (value >= upperThreshold)
// color = m_waterfallHiColor;
// else {
//
// offset = value - lowerThreshold;
// globalRange = offset / m_waterfallColorRange; // value from 0.0 to 1.0 where 1.0 is high and 0.0 is low.
//
// if (globalRange < (float)2/9) { // background to blue
//
// localRange = globalRange / ((float)2/9);
// r = (int)((1.0 - localRange) * m_waterfallLoColor.red());
// g = (int)((1.0 - localRange) * m_waterfallLoColor.green());
// b = (int)(m_waterfallLoColor.blue() + localRange * (255 - m_waterfallLoColor.blue()));
// }
// else
// if (globalRange < (float)3/9) { // blue to blue-green
//
// localRange = (globalRange - (float)2/9) / ((float)1/9);
// r = 0;
// g = (int)(localRange * 255);
// b = 255;
// }
// else
// if (globalRange < (float)4/9) { // blue-green to green
//
// localRange = (globalRange - (float)3/9) / ((float)1/9);
// r = 0;
// g = 255;
// b = (int)((1.0 - localRange) * 255);
// }
// else
// if (globalRange < (float)5/9) { // green to red-green
//
// localRange = (globalRange - (float)4/9) / ((float)1/9);
// r = (int)(localRange * 255);
// g = 255;
// b = 0;
// }
// else
// if (globalRange < (float)7/9) { // red-green to red
//
// localRange = (globalRange - (float)5/9) / ((float)2/9);
// r = 255;
// g = (int)((1.0 - localRange) * 255);
// b = 0;
// }
// else
// if (globalRange < (float)8/9) { // red to red-blue
//
// localRange = (globalRange - (float)7/9) / ((float)1/9);
// r = 255;
// g = 0;
// b = (int)(localRange * 255);
// }
// else { // red-blue to purple end
//
// localRange = (globalRange - (float)8/9) / ((float)1/9);
// r = (int)((0.75 + 0.25 * (1.0 - localRange)) * 255);
// g = (int)(localRange * 255 * 0.5);
// b = 255;
// }
// if (r > 255) r = 255;
// if (g > 255) g = 255;
// if (b > 255) b = 255;
// if (r < 0) r = 0;
// if (g < 0) g = 0;
// if (b < 0) b = 0;
// color = QColor(r, g, b, m_waterfallAlpha);
// }
//
// break;
//
// case QSDRGraphics::spectran:
//
// break;
// }
//
// return color;
//}
void QGLDistancePanel::setChirpFFTShow(bool value) {
distanceSpectrumBufferMutex.lock();
m_showChirpFFT = value;
distanceSpectrumBufferMutex.unlock();
update();
}
void QGLDistancePanel::systemStateChanged(
QObject *sender,
QSDR::_Error err,
QSDR::_HWInterfaceMode hwmode,
QSDR::_ServerMode mode,
QSDR::_DataEngineState state)
{
Q_UNUSED (sender)
Q_UNUSED (err)
Q_UNUSED (hwmode)
Q_UNUSED (state)
if (m_dataEngineState != state)
m_dataEngineState = state;
if (m_serverMode != mode) {
//memset(m_wbSpectrumBuffer, -10000, 4 * BUFFER_SIZE * sizeof(float));
memset(m_spectrumBuffer, -10000, 4 * BUFFER_SIZE * sizeof(float));
memset(m_distanceSpectrumBuffer, -10000, 16 * BUFFER_SIZE * sizeof(float));
m_serverMode = mode;
}
//resizeGL(width(), height());
m_displayTime.restart();
update();
}
void QGLDistancePanel::graphicModeChanged(
QObject *sender,
int rx,
PanGraphicsMode panMode,
WaterfallColorMode colorScheme)
{
Q_UNUSED (sender)
Q_UNUSED (colorScheme)
Q_UNUSED (rx)
if (m_panMode != panMode)
m_panMode = panMode;
/*if (m_waterColorScheme != colorScheme) {
m_waterColorScheme = colorScheme;
change = true;
}*/
//if (!change) return;
update();
}
void QGLDistancePanel::setSpectrumAveraging(bool value) {
spectrumBufferMutex.lock();
if (m_spectrumAveraging == value)
return;
else
m_spectrumAveraging = value;
spectrumBufferMutex.unlock();
}
void QGLDistancePanel::setSpectrumAveragingCnt(int value) {
spectrumBufferMutex.lock();
memset(m_tmpBuf, 0, SAMPLE_BUFFER_SIZE * sizeof(float));
while (!specAv_queue.isEmpty())
specAv_queue.dequeue();
m_specAveragingCnt = value;
if (m_specAveragingCnt > 0)
m_scale = 1.0f / m_specAveragingCnt;
else
m_scale = 1.0f;
spectrumBufferMutex.unlock();
}
void QGLDistancePanel::setPanGridStatus(bool value) {
spectrumBufferMutex.lock();
if (m_panGrid == value)
return;
else
m_panGrid = value;
spectrumBufferMutex.unlock();
update();
}
void QGLDistancePanel::sampleRateChanged(QObject *sender, int value) {
Q_UNUSED(sender)
m_sampleRate = value;
update();
}
void QGLDistancePanel::setPanadapterColors() {
m_spectrumColorsChanged = true;
mutex.lock();
/*m_bkgRed = (GLfloat)(set->getPanadapterColors().panBackgroundColor.red() / 256.0);
m_bkgGreen = (GLfloat)(set->getPanadapterColors().panBackgroundColor.green() / 256.0);
m_bkgBlue = (GLfloat)(set->getPanadapterColors().panBackgroundColor.blue() / 256.0);*/
/*if (m_bkgRed * 1.2 > 1.0) m_bkgRed = 1.0f;
if (m_bkgGreen * 1.2 > 1.0) m_bkgGreen = 1.0f;
if (m_bkgBlue * 1.2 > 1.0) m_bkgBlue = 1.0f;
if (m_bkgRed * 1.6 > 1.0) m_bkgRed = 1.0f;
if (m_bkgGreen * 1.6 > 1.0) m_bkgGreen = 1.0f;
if (m_bkgBlue * 1.6 > 1.0) m_bkgBlue = 1.0f;*/
m_red = (GLfloat)(set->getPanadapterColors().panLineColor.red() / 256.0);
m_green = (GLfloat)(set->getPanadapterColors().panLineColor.green() / 256.0);
m_blue = (GLfloat)(set->getPanadapterColors().panLineColor.blue() / 256.0);
m_redF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.red() / 256.0);
m_greenF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.green() / 256.0);
m_blueF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.blue() / 256.0);
m_redST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.red() / 256.0);
m_greenST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.green() / 256.0);
m_blueST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.blue() / 256.0);
m_redSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.red() / 256.0);
m_greenSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.green() / 256.0);
m_blueSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.blue() / 256.0);
mutex.unlock();
update();
}
//void QGLDistancePanel::setWaterfallTime(int rx, int value) {
//
// if (rx == 0)
// m_waterfallTime = value;
//}
//void QGLDistancePanel::setWaterfallOffesetLo(int rx, int value) {
//
// if (rx == 0)
// m_waterfallOffsetLo = value;
//
// update();
//}
//
//void QGLDistancePanel::setWaterfallOffesetHi(int rx, int value) {
//
// if (rx = 0)
// m_waterfallOffsetHi = value;
//
// update();
//}
void QGLDistancePanel::closeEvent(QCloseEvent *event) {
emit closeEvent(this);
QWidget::closeEvent(event);
}
void QGLDistancePanel::showEvent(QShowEvent *event) {
emit showEvent(this);
QWidget::showEvent(event);
}