mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-29 23:58:39 -05:00
b8e4517718
This include inverting the order of table view rows so the newest is at the top, without that the Qt MVC interactions when using a database table based model is too slow and complex to manage. The table views now have sort by column capability in the normal way (click column header to reverse sort order) for timely logging and non-disruption of Tx starts the log view should be sorted in descending time order and scrolled to the last row added. Without that Fox and contest logging will work but serious delays may be invoked that disrupt operation.
327 lines
8.3 KiB
C++
327 lines
8.3 KiB
C++
#include "echoplot.h"
|
|
#include "commons.h"
|
|
#include <math.h>
|
|
#include <QPainter>
|
|
#include <QPen>
|
|
#include <QDebug>
|
|
#include "moc_echoplot.cpp"
|
|
|
|
#define MAX_SCREENSIZE 2048
|
|
|
|
|
|
EPlotter::EPlotter(QWidget *parent) : //EPlotter Constructor
|
|
QFrame(parent)
|
|
{
|
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
setFocusPolicy(Qt::StrongFocus);
|
|
setAttribute(Qt::WA_PaintOnScreen,false);
|
|
setAutoFillBackground(false);
|
|
setAttribute(Qt::WA_OpaquePaintEvent, false);
|
|
setAttribute(Qt::WA_NoSystemBackground, true);
|
|
|
|
m_StartFreq = -200;
|
|
m_fftBinWidth=12000.0/32768.0;
|
|
m_binsPerPixel=1;
|
|
m_fSpan=1000.0;
|
|
m_hdivs = HORZ_DIVS;
|
|
m_Running = false;
|
|
m_paintEventBusy=false;
|
|
m_2DPixmap = QPixmap(0,0);
|
|
m_ScalePixmap = QPixmap(0,0);
|
|
m_OverlayPixmap = QPixmap(0,0);
|
|
m_Size = QSize(0,0);
|
|
m_TxFreq = 1500;
|
|
m_line = 0;
|
|
m_dBStepSize=10;
|
|
}
|
|
|
|
EPlotter::~EPlotter() { } // Destructor
|
|
|
|
QSize EPlotter::minimumSizeHint() const
|
|
{
|
|
return QSize(50, 50);
|
|
}
|
|
|
|
QSize EPlotter::sizeHint() const
|
|
{
|
|
return QSize(180, 180);
|
|
}
|
|
|
|
void EPlotter::resizeEvent(QResizeEvent* ) //resizeEvent()
|
|
{
|
|
if(!size().isValid()) return;
|
|
if( m_Size != size() ) { //if changed, resize pixmaps to new screensize
|
|
m_Size = size();
|
|
m_w = m_Size.width();
|
|
m_h = m_Size.height();
|
|
m_h1=30;
|
|
m_h2=m_h-m_h1;
|
|
m_2DPixmap = QPixmap(m_Size.width(), m_h2);
|
|
m_2DPixmap.fill(Qt::black);
|
|
m_OverlayPixmap = QPixmap(m_Size.width(), m_h2);
|
|
m_ScalePixmap = QPixmap(m_w,30);
|
|
m_ScalePixmap.fill(Qt::white);
|
|
m_fSpan=m_w*m_fftBinWidth*m_binsPerPixel;
|
|
m_StartFreq=50 * int((-0.5*m_fSpan)/50.0 - 0.5);
|
|
}
|
|
DrawOverlay();
|
|
draw();
|
|
}
|
|
|
|
void EPlotter::paintEvent(QPaintEvent *) // paintEvent()
|
|
{
|
|
if(m_paintEventBusy) return;
|
|
m_paintEventBusy=true;
|
|
QPainter painter(this);
|
|
painter.drawPixmap(0,0,m_ScalePixmap);
|
|
painter.drawPixmap(0,m_h1,m_2DPixmap);
|
|
m_paintEventBusy=false;
|
|
}
|
|
|
|
void EPlotter::draw() //draw()
|
|
{
|
|
int i,j,y;
|
|
float blue[4096],red[4096];
|
|
float gain = pow(10.0,(m_plotGain/20.0));
|
|
QPen penBlue(QColor(0,255,255),1);
|
|
QPen penRed(Qt::red,1);
|
|
QPen penRed2(Qt::red,2);
|
|
QPen penBlack(Qt::black,1);
|
|
QPen penBlack2(Qt::black,2);
|
|
|
|
if(m_2DPixmap.size().width()==0) return;
|
|
QPainter painter2D(&m_2DPixmap);
|
|
QRect tmp(0,0,m_w,m_h2);
|
|
if(m_nColor < 2) {
|
|
painter2D.fillRect(tmp,Qt::black);
|
|
} else {
|
|
painter2D.fillRect(tmp,Qt::white);
|
|
painter2D.setPen(penBlack);
|
|
painter2D.drawLine(0,0,m_w,0);
|
|
}
|
|
|
|
QPoint LineBuf[MAX_SCREENSIZE];
|
|
|
|
if(m_binsPerPixel==0) m_binsPerPixel=1;
|
|
j=0;
|
|
for(i=0; i<4096/m_binsPerPixel; i++) {
|
|
blue[i]=0.0;
|
|
red[i]=0.0;
|
|
for(int k=0; k<m_binsPerPixel; k++) {
|
|
blue[i]+=echocom_.blue[j];
|
|
red[i]+=echocom_.red[j];
|
|
j++;
|
|
}
|
|
}
|
|
if(m_smooth>0) {
|
|
for(i=0; i<m_smooth; i++) {
|
|
int n4096=4096;
|
|
smo121_(blue,&n4096);
|
|
smo121_(red,&n4096);
|
|
}
|
|
}
|
|
|
|
// check i0 value! ...
|
|
int i0=2048/m_binsPerPixel + int(m_StartFreq/(m_fftBinWidth*m_binsPerPixel));
|
|
if(m_blue) {
|
|
painter2D.setPen(penBlue);
|
|
j=0;
|
|
for(i=0; i<m_w; i++) {
|
|
y = 0.9*m_h2 - gain*(m_h/10.0)*(blue[i0+i]-1.0) - 0.01*m_h2*m_plotZero;
|
|
LineBuf[j].setX(i);
|
|
LineBuf[j].setY(y);
|
|
j++;
|
|
}
|
|
painter2D.drawPolyline(LineBuf,j);
|
|
}
|
|
switch (m_nColor) {
|
|
case 0: painter2D.setPen(penRed); break;
|
|
case 1: painter2D.setPen(penRed2); break;
|
|
case 2: painter2D.setPen(penRed); break;
|
|
case 3: painter2D.setPen(penRed2); break;
|
|
case 4: painter2D.setPen(penBlack); break;
|
|
case 5: painter2D.setPen(penBlack2); break;
|
|
}
|
|
|
|
j=0;
|
|
for(int i=0; i<m_w; i++) {
|
|
y = 0.9*m_h2 - gain*(m_h/10.0)*(red[i0+i]-1.0) - 0.01*m_h2*m_plotZero;
|
|
LineBuf[j].setX(i);
|
|
LineBuf[j].setY(y);
|
|
j++;
|
|
}
|
|
painter2D.drawPolyline(LineBuf,j);
|
|
update(); //trigger a new paintEvent
|
|
}
|
|
|
|
void EPlotter::DrawOverlay() //DrawOverlay()
|
|
{
|
|
if(m_OverlayPixmap.isNull() or m_2DPixmap.isNull()) return;
|
|
// int w = m_WaterfallPixmap.width();
|
|
int x,y;
|
|
|
|
QRect rect;
|
|
QPainter painter(&m_OverlayPixmap);
|
|
painter.initFrom(this);
|
|
QLinearGradient gradient(0, 0, 0 ,m_h2); //fill background with gradient
|
|
gradient.setColorAt(1, Qt::black);
|
|
gradient.setColorAt(0, Qt::darkBlue);
|
|
painter.setBrush(gradient);
|
|
painter.drawRect(0, 0, m_w, m_h2);
|
|
painter.setBrush(Qt::SolidPattern);
|
|
|
|
m_fSpan = m_w*m_fftBinWidth*m_binsPerPixel;
|
|
m_freqPerDiv=20;
|
|
if(m_fSpan>250) m_freqPerDiv=50;
|
|
if(m_fSpan>500) m_freqPerDiv=100;
|
|
if(m_fSpan>1000) m_freqPerDiv=200;
|
|
if(m_fSpan>2000) m_freqPerDiv=500;
|
|
|
|
// m_StartFreq=50 * int((-0.5*m_fSpan)/50.0 - 0.5);
|
|
m_StartFreq=m_freqPerDiv * int((-0.5*m_fSpan)/m_freqPerDiv - 0.5);
|
|
|
|
float pixPerHdiv = m_freqPerDiv/(m_fftBinWidth*m_binsPerPixel);
|
|
float pixPerVdiv = float(m_h2)/float(VERT_DIVS);
|
|
|
|
m_hdivs = m_w*m_fftBinWidth*m_binsPerPixel/m_freqPerDiv + 0.9999;
|
|
|
|
painter.setPen(QPen(Qt::white, 1,Qt::DotLine));
|
|
for( int i=1; i<m_hdivs; i++) //draw vertical grids
|
|
{
|
|
x=int(i*pixPerHdiv);
|
|
painter.drawLine(x,0,x,m_h2);
|
|
}
|
|
|
|
for( int i=1; i<VERT_DIVS; i++) //draw horizontal grids
|
|
{
|
|
y = (int)( (float)i*pixPerVdiv );
|
|
painter.drawLine(0,y,m_w,y);
|
|
}
|
|
|
|
QRect rect0;
|
|
QPainter painter0(&m_ScalePixmap);
|
|
painter0.initFrom(this);
|
|
|
|
//create Font to use for scales
|
|
QFont Font("Arial");
|
|
Font.setPointSize(12);
|
|
QFontMetrics metrics(Font);
|
|
Font.setWeight(QFont::Normal);
|
|
painter0.setFont(Font);
|
|
painter0.setPen(Qt::black);
|
|
|
|
m_ScalePixmap.fill(Qt::white);
|
|
painter0.drawRect(0, 0, m_w, 30);
|
|
|
|
//draw tick marks on upper scale
|
|
for( int i=1; i<m_hdivs; i++) { //major ticks
|
|
x = (int)( (float)i*pixPerHdiv );
|
|
painter0.drawLine(x,18,x,30);
|
|
}
|
|
int minor=5;
|
|
if(m_freqPerDiv==200) minor=4;
|
|
for( int i=1; i<minor*m_hdivs; i++) { //minor ticks
|
|
x = i*pixPerHdiv/minor;
|
|
painter0.drawLine(x,24,x,30);
|
|
}
|
|
|
|
//draw frequency values
|
|
MakeFrequencyStrs();
|
|
for( int i=0; i<=m_hdivs; i++) {
|
|
if(0==i) {
|
|
//left justify the leftmost text
|
|
x = (int)( (float)i*pixPerHdiv);
|
|
rect0.setRect(x,0, (int)pixPerHdiv, 20);
|
|
painter0.drawText(rect0, Qt::AlignLeft|Qt::AlignVCenter,
|
|
m_HDivText[i]);
|
|
}
|
|
else if(m_hdivs == i) {
|
|
//right justify the rightmost text
|
|
x = (int)( (float)i*pixPerHdiv - pixPerHdiv);
|
|
rect0.setRect(x,0, (int)pixPerHdiv, 20);
|
|
painter0.drawText(rect0, Qt::AlignRight|Qt::AlignVCenter,
|
|
m_HDivText[i]);
|
|
} else {
|
|
//center justify the rest of the text
|
|
x = (int)( (float)i*pixPerHdiv - pixPerHdiv/2);
|
|
rect0.setRect(x,0, (int)pixPerHdiv, 20);
|
|
painter0.drawText(rect0, Qt::AlignHCenter|Qt::AlignVCenter,
|
|
m_HDivText[i]);
|
|
}
|
|
}
|
|
|
|
/*
|
|
QPen pen1(Qt::red, 3); //Mark Tx Freq with red tick
|
|
painter0.setPen(pen1);
|
|
x = XfromFreq(m_TxFreq);
|
|
painter0.drawLine(x,17,x,30);
|
|
*/
|
|
}
|
|
|
|
void EPlotter::MakeFrequencyStrs() //MakeFrequencyStrs
|
|
{
|
|
float freq;
|
|
for(int i=0; i<=m_hdivs; i++) {
|
|
freq=m_StartFreq + i*m_freqPerDiv;
|
|
m_HDivText[i].setNum((int)freq);
|
|
}
|
|
}
|
|
|
|
int EPlotter::XfromFreq(float f) //XfromFreq()
|
|
{
|
|
int x = (int) m_w * (f - m_StartFreq)/m_fSpan;
|
|
if(x<0 ) return 0;
|
|
if(x>m_w) return m_w;
|
|
return x;
|
|
}
|
|
|
|
float EPlotter::FreqfromX(int x) //FreqfromX()
|
|
{
|
|
return float(m_StartFreq + x*m_fftBinWidth*m_binsPerPixel);
|
|
}
|
|
|
|
void EPlotter::SetRunningState(bool running) //SetRunningState()
|
|
{
|
|
m_Running = running;
|
|
}
|
|
|
|
void EPlotter::setPlotZero(int plotZero) //setPlotZero()
|
|
{
|
|
m_plotZero=plotZero;
|
|
}
|
|
|
|
int EPlotter::getPlotZero() //getPlotZero()
|
|
{
|
|
return m_plotZero;
|
|
}
|
|
|
|
void EPlotter::setPlotGain(int plotGain) //setPlotGain()
|
|
{
|
|
m_plotGain=plotGain;
|
|
}
|
|
|
|
int EPlotter::getPlotGain() //getPlotGain()
|
|
{
|
|
return m_plotGain;
|
|
}
|
|
|
|
void EPlotter::setSmooth(int n) //setSmooth()
|
|
{
|
|
m_smooth=n;
|
|
}
|
|
|
|
int EPlotter::getSmooth() //getSmooth()
|
|
{
|
|
return m_smooth;
|
|
}
|
|
|
|
void EPlotter::setColors(qint32 n) //setSmooth()
|
|
{
|
|
m_nColor=n;
|
|
draw();
|
|
}
|
|
|
|
int EPlotter::plotWidth(){return m_2DPixmap.width();}
|
|
|
|
void EPlotter::UpdateOverlay() {DrawOverlay();}
|