Add user defined waterfall palette.

The  new  class WFPalette  encapsulates  waterfall palettes  including
exporting and importing to disk files and interpolation for use in the
waterfall plotter.

A special  entry in the palette  list "User Defined"  is now available
along with  a button  to invoke a  colour palette designer.   The user
defined palette definition is persistent across runs as it is saved in
the application settings file.

Palettes can now have any number of colours up to 256.

The export function may be used  to save user designed palettes; to be
added  to the built  in resource  palettes that  are shipped  with the
application.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@3964 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2014-03-31 00:03:44 +00:00
parent a893d42288
commit 31ebdc9618
10 changed files with 1020 additions and 487 deletions

View File

@ -49,6 +49,7 @@ set (PROJECT_MANUAL "http://www.physics.princeton.edu/pulsar/K1JT/wsjtx-doc/wsjt
#
set (wsjt_qt_CXXSRCS
NetworkServerLookup.cpp
WFPalette.cpp
Radio.cpp
Bands.cpp
FrequencyList.cpp
@ -241,6 +242,10 @@ set (ConfigTest_UISRCS
Configuration.ui
)
set (wsjt_qt_UISRCS
wf_palette_design_dialog.ui
)
set (wsjtx_UISRCS
mainwindow.ui
about.ui
@ -455,12 +460,12 @@ if (NOT hamlib_FOUND)
endif (NOT hamlib_FOUND)
include_directories (${hamlib_INCLUDE_DIRS})
if (WIN32)
find_library (hamlib_RUNTIME NAMES hamlib hamlib-2 PATH_SUFFIXES bin)
get_filename_component (_hamlib_runtime_path "${hamlib_RUNTIME}" PATH)
file (GLOB hamlib_BACKENDS ${_hamlib_runtime_path}/hamlib*.dll)
find_library (usb_RUNTIME NAMES usb0 PATH_SUFFIXES bin)
endif (WIN32)
# if (WIN32)
# find_library (hamlib_RUNTIME NAMES hamlib hamlib-2 PATH_SUFFIXES bin)
# get_filename_component (_hamlib_runtime_path "${hamlib_RUNTIME}" PATH)
# file (GLOB hamlib_BACKENDS ${_hamlib_runtime_path}/hamlib*.dll)
# find_library (usb_RUNTIME NAMES usb0 PATH_SUFFIXES bin)
# endif (WIN32)
#
@ -535,7 +540,9 @@ add_custom_target (kvasd DEPENDS contrib/kvasd${CMAKE_EXECUTABLE_SUFFIX})
# UI generation
qt5_wrap_ui (GENUISRCS ${ConfigTest_UISRCS} ${wsjtx_UISRCS})
qt5_wrap_ui (wsjt_qt_GENUISRCS ${wsjt_qt_UISRCS})
qt5_wrap_ui (ConfigTest_GENUISRCS ${ConfigTest_UISRCS})
qt5_wrap_ui (wsjtx_GENUISRCS ${wsjtx_UISRCS})
# Resource generation
qt5_add_resources (wsjtx_RESOURCES_RCC wsjtx.qrc)
@ -555,7 +562,7 @@ endif (WIN32)
add_library (wsjt STATIC ${wsjt_CSRCS} ${wsjt_CXXSRCS} ${wsjt_FSRCS})
# build a library of package Qt functionality
add_library (wsjt_qt STATIC ${wsjt_qt_CXXSRCS} ${GENAXSRCS})
add_library (wsjt_qt STATIC ${wsjt_qt_CXXSRCS} ${wsjt_qt_GENUISRCS} ${GENAXSRCS})
qt5_use_modules (wsjt_qt Widgets OpenGL Network)
if (WIN32)
qt5_use_modules (wsjt_qt AxContainer AxBase)
@ -572,12 +579,12 @@ target_link_libraries (jt9 wsjt ${FFTW3F_LIBRARY})
qt5_use_modules (jt9 Core)
# build configuration dialog and transceiver interface test application
#add_executable (ConfigTest ${ConfigTest_CXXSRCS} ${ConfigTest_UISRCS} wsjtx.rc)
#add_executable (ConfigTest ${ConfigTest_CXXSRCS} ${ConfigTest_GENUISRCS} wsjtx.rc)
#target_link_libraries (ConfigTest wsjt wsjt_qt ${hamlib_LIBRARIES})
#qt5_use_modules (ConfigTest Widgets OpenGL Network Multimedia)
# build the main application
add_executable (wsjtx WIN32 MACOSX_BUNDLE ${wsjtx_CXXSRCS} ${wsjtx_UISRCS} wsjtx.rc ${WSJTX_ICON_FILE} ${wsjtx_RESOURCES_RCC})
add_executable (wsjtx WIN32 MACOSX_BUNDLE ${wsjtx_CXXSRCS} ${wsjtx_GENUISRCS} wsjtx.rc ${WSJTX_ICON_FILE} ${wsjtx_RESOURCES_RCC})
qt5_use_modules (wsjtx Widgets OpenGL Network Multimedia)
set_target_properties (wsjtx PROPERTIES

307
WFPalette.cpp Normal file
View File

@ -0,0 +1,307 @@
#include "WFPalette.hpp"
#include <stdexcept>
#include <memory>
#include <QMetaType>
#include <QObject>
#include <QFile>
#include <QTextStream>
#include <QString>
#include <QDialog>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <QColorDialog>
#include <QColor>
#include <QBrush>
#include <QPoint>
#include <QMenu>
#include <QAction>
#include <QPushButton>
#include <QStandardPaths>
#include <QFileDialog>
#include <QFile>
#include <QTextStream>
#include "qt_helpers.hpp"
#include "ui_wf_palette_design_dialog.h"
namespace
{
int constexpr points {256};
struct init
{
init ()
{
qRegisterMetaTypeStreamOperators<WFPalette::Colours> ("Colours");
}
} static_initaializer;
using Colours = WFPalette::Colours;
// ensure that palette colours are useable for interpolation
Colours make_valid (Colours colours)
{
if (colours.size () < 2)
{
// allow single element by starting at black
colours.prepend (QColor {0, 0, 0});
}
if (1 == colours.size ())
{
// allow empty list by using black to white
colours.append (QColor {255,255,255});
}
if (colours.size () > points)
{
throw_qstring (tr ("Too many colours in palette."));
}
return colours;
}
// load palette colours from a file
Colours load_palette (QString const& file_name)
{
Colours colours;
QFile file {file_name};
if (file.open (QIODevice::ReadOnly))
{
unsigned count {0};
QTextStream in (&file);
int line_counter {0};
while (!in.atEnd ())
{
auto line = in.readLine();
++line_counter;
if (++count >= points)
{
throw_qstring (QObject::tr ("Error reading waterfall palette file \"%1:%2\" too many colors.")
.arg (file.fileName ().arg (line_counter));
}
auto items = line.split (';');
if (items.size () != 3)
{
throw_qstring (QObject::tr ("Error reading waterfall palette file \"%1:%2\" invalid triplet.")
.arg (file.fileName ()).arg (line_counter));
}
bool r_ok, g_ok, b_ok;
auto r = items[0].toInt (&r_ok);
auto g = items[1].toInt (&g_ok);
auto b = items[2].toInt (&b_ok);
if (!r_ok || !g_ok || !b_ok
|| r < 0 || r > 255
|| g < 0 || g > 255
|| b < 0 || b > 255)
{
throw_qstring (QObject::tr ("Error reading waterfall palette file \"%1:%2\" invalid color.")
.arg (file.fileName ()).arg (line_counter));
}
colours.append (QColor {r, g, b});
}
}
else
{
throw_qstring (QObject::tr ("Error opening waterfall palette file \"%1\".").arg (file.fileName ()));
}
return colours;
}
// GUI to design and manage waterfall palettes
class Designer
: public QDialog
{
Q_OBJECT;
public:
explicit Designer (Colours const& current, QWidget * parent = nullptr)
: QDialog {parent}
, colours_ {current}
{
ui_.setupUi (this);
// context menu actions
auto import_button = ui_.button_box->addButton ("&Import...", QDialogButtonBox::ActionRole);
connect (import_button, &QPushButton::clicked, this, &Designer::import_palette);
auto export_button = ui_.button_box->addButton ("&Export...", QDialogButtonBox::ActionRole);
connect (export_button, &QPushButton::clicked, this, &Designer::export_palette);
// load the table items
ui_.colour_table_widget->setRowCount (colours_.size ());
for (int i {0}; i < colours_.size (); ++i)
{
insert_item (i);
}
// hookup the context menu handler
connect (ui_.colour_table_widget, &QWidget::customContextMenuRequested, this, &Designer::context_menu);
}
Colours colours () const
{
return colours_;
}
// invoke the colour editor
Q_SLOT void on_colour_table_widget_itemDoubleClicked (QTableWidgetItem * item)
{
auto new_colour = QColorDialog::getColor (item->background ().color (), this);
if (new_colour.isValid ())
{
item->setBackground (QBrush {new_colour});
colours_[item->row ()] = new_colour;
}
}
private:
void insert_item (int row)
{
std::unique_ptr<QTableWidgetItem> item {new QTableWidgetItem {""}};
item->setBackground (QBrush {colours_[row]});
item->setFlags (Qt::ItemIsEnabled);
ui_.colour_table_widget->setItem (row, 0, item.release ());
}
void context_menu (QPoint const& p)
{
context_menu_.clear ();
if (ui_.colour_table_widget->itemAt (p))
{
auto delete_action = context_menu_.addAction (tr ("&Delete"));
connect (delete_action, &QAction::triggered, [this] ()
{
auto row = ui_.colour_table_widget->currentRow ();
ui_.colour_table_widget->removeRow (row);
colours_.removeAt (row);
});
}
auto insert_action = context_menu_.addAction (tr ("&Insert ..."));
connect (insert_action, &QAction::triggered, [this] ()
{
auto item = ui_.colour_table_widget->itemAt (menu_pos_);
int row = item ? item->row () : colours_.size ();
auto default_colour = QColor {0, 0, 0};
if (row > 0)
{
// use the prior row colour
default_colour = colours_[row - 1];
}
auto new_colour = QColorDialog::getColor (default_colour, this);
if (new_colour.isValid ())
{
ui_.colour_table_widget->insertRow (row);
colours_.insert (row, new_colour);
insert_item (row);
}
});
menu_pos_ = p; // save for context menu action handlers
context_menu_.popup (ui_.colour_table_widget->mapToGlobal (p));
}
void import_palette ()
{
auto docs = QStandardPaths::writableLocation (QStandardPaths::DocumentsLocation);
auto file_name = QFileDialog::getOpenFileName (this, tr ("Import Palette"), docs, tr ("Palettes (*.pal)"));
if (!file_name.isEmpty ())
{
colours_ = load_palette (file_name);
}
}
void export_palette ()
{
auto docs = QStandardPaths::writableLocation (QStandardPaths::DocumentsLocation);
auto file_name = QFileDialog::getSaveFileName (this, tr ("Export Palette"), docs, tr ("Palettes (*.pal)"));
if (!file_name.isEmpty ())
{
if (!QFile::exists (file_name) && !file_name.contains ('.'))
{
file_name += ".pal";
}
QFile file {file_name};
if (file.open (QFile::WriteOnly | QFile::Truncate | QFile::Text))
{
QTextStream stream {&file};
Q_FOREACH (auto colour, colours_)
{
stream << colour.red () << ';' << colour.green () << ';' << colour.blue () << endl;
}
}
else
{
throw_qstring (QObject::tr ("Error writing waterfall palette file \"%1\".").arg (file.fileName ()));
}
}
}
Ui::wf_palette_design_dialog ui_;
Colours colours_;
QMenu context_menu_;
QPoint menu_pos_;
};
}
#include "WFPalette.moc"
WFPalette::WFPalette (QString const& file_path)
: colours_ {load_palette (file_path)}
{
}
WFPalette::WFPalette (QList<QColor> const& colour_list)
: colours_ {colour_list}
{
}
// generate an array of colours suitable for the waterfall plotter
QVector<QColor> WFPalette::interpolate () const
{
Colours colours {make_valid (colours_)};
QVector<QColor> result;
result.reserve (points);
// do a linear gradient between each supplied colour point
int interval = points / (colours.size () - 1);
for (int i {0}; i < points; ++i)
{
int prior {i / interval};
int next {prior + 1};
if (next >= colours.size ())
{
--next;
--prior;
}
int increment {i - interval * prior};
int r {colours[prior].red () + int((increment * (colours[next].red () - colours[prior].red ()))/interval)};
int g {colours[prior].green () + int((increment * (colours[next].green () - colours[prior].green ()))/interval)};
int b {colours[prior].blue () + int((increment * (colours[next].blue () - colours[prior].blue ()))/interval)};
result.append (QColor {r, g, b});
}
return result;
}
// invoke the palette designer
bool WFPalette::design ()
{
Designer designer {colours_};
if (QDialog::Accepted == designer.exec ())
{
colours_ = designer.colours ();
return true;
}
return false;
}

55
WFPalette.hpp Normal file
View File

@ -0,0 +1,55 @@
#ifndef W_F_PALETTE_HPP__
#define W_F_PALETTE_HPP__
#include <QList>
#include <QVector>
#include <QColor>
class QString;
//
// Class WFPalette
//
// Encapulates a waterfall palette description. A colour gradient
// over 256 intervals is described by a list of RGB colour triplets.
// The list of colours are use to interpolate the full 256 interval
// waterfall colour gradient.
//
// Responsibilities
//
// Construction from a string which is a path to a file containing
// colour descriptions in the form rrr;ggg;bbb on up to 256
// consecutive lines, where rrr, ggg and, bbb are integral numbers in
// the range 0<=n<256.
//
// Construction from a list of QColor instances. Up to the first 256
// list elements are used.
//
// Includes a design GUI to create or adjust a WFPalette.
//
class WFPalette
{
public:
using Colours = QList<QColor>;
WFPalette () = default;
explicit WFPalette (Colours const&);
explicit WFPalette (QString const& file_path);
WFPalette (WFPalette const&) = default;
WFPalette& operator = (WFPalette const&) = default;
Colours colours () const {return colours_;}
// interpolate a gradient over 256 steps
QVector<QColor> interpolate () const;
// returns true if colours have been modified
bool design ();
private:
Colours colours_;
};
Q_DECLARE_METATYPE (WFPalette::Colours);
#endif

View File

@ -14,6 +14,7 @@
#endif
#include <QFrame>
#include <QImage>
#include <QVector>
#include <cstring>
#include "commons.h"
@ -22,28 +23,14 @@
class CPlotter : public QFrame
{
Q_OBJECT
Q_OBJECT;
public:
explicit CPlotter(QWidget *parent = 0);
~CPlotter();
QSize minimumSizeHint() const;
QSize sizeHint() const;
QColor m_ColorTbl[256];
bool m_bCurrent;
bool m_bCumulative;
bool m_bLinearAvg;
bool m_lockTxFreq;
float m_fSpan;
qint32 m_plotZero;
qint32 m_plotGain;
qint32 m_nSpan;
qint32 m_binsPerPixel;
qint32 m_w;
void draw(float sw[]); //Update the waterfall
void SetRunningState(bool running);
void setPlotZero(int plotZero);
@ -54,6 +41,7 @@ public:
int startFreq();
int plotWidth();
void setNSpan(int n);
int nSpan() const {return m_nSpan;}
void UpdateOverlay();
void setDataFromDisk(bool b);
void setRxRange(int fMin);
@ -72,6 +60,24 @@ public:
int getFmax();
void setDialFreq(double d);
void setCurrent(bool b) {m_bCurrent = b;}
bool current() const {return m_bCurrent;}
void setCumulative(bool b) {m_bCumulative = b;}
bool cumulative() const {return m_bCumulative;}
void setLinearAvg(bool b) {m_bLinearAvg = b;}
bool linearAvg() const {return m_bLinearAvg;}
void setBreadth(qint32 w) {m_w = w;}
qint32 breadth() const {return m_w;}
float fSpan() const {return m_fSpan;}
void setLockTxFreq(bool b) {m_lockTxFreq = b;}
void setColours(QVector<QColor> const& cl) {m_ColorTbl = cl;}
signals:
void freezeDecode1(int n);
void setFreq1(int rxFreq, int txFreq);
@ -88,6 +94,21 @@ private:
int XfromFreq(float f);
float FreqfromX(int x);
QVector<QColor> m_ColorTbl;
bool m_bCurrent;
bool m_bCumulative;
bool m_bLinearAvg;
bool m_lockTxFreq;
float m_fSpan;
qint32 m_plotZero;
qint32 m_plotGain;
qint32 m_nSpan;
qint32 m_binsPerPixel;
qint32 m_w;
QPixmap m_WaterfallPixmap;
QPixmap m_2DPixmap;
QPixmap m_ScalePixmap;

View File

@ -1,9 +1,13 @@
#ifndef QT_HELPERS_HPP_
#define QT_HELPERS_HPP_
#include <stdexcept>
#include <QDataStream>
#include <QMetaObject>
#include <QMetaEnum>
#include <QString>
#include <QByteArray>
#include <QDebug>
#define ENUM_QDATASTREAM_OPS_DECL(CLASS, ENUM) \
@ -56,4 +60,10 @@
return QString {mo.enumerator (mo.indexOfEnumerator (#ENUM)).valueToKey (m)}; \
}
inline
void throw_qstring (QString const& qs)
{
throw std::runtime_error (qs.toLocal8Bit ().data ());
}
#endif

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>wf_palette_design_dialog</class>
<widget class="QDialog" name="wf_palette_design_dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>181</width>
<height>209</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QTableWidget" name="colour_table_widget">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="toolTip">
<string>Right click to insert or delete colors.
Colors at the top represent weak signals
and colors at the bottom represent strong
signals. You can have up to 256 colors.</string>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="columnCount">
<number>1</number>
</property>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<column/>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="button_box">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>button_box</sender>
<signal>accepted()</signal>
<receiver>wf_palette_design_dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>button_box</sender>
<signal>rejected()</signal>
<receiver>wf_palette_design_dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -11,6 +11,11 @@
#define MAX_SCREENSIZE 2048
namespace
{
auto user_defined = QObject::tr ("User Defined");
}
WideGraph::WideGraph(QSettings * settings, QWidget *parent) :
QDialog(parent),
ui(new Ui::WideGraph),
@ -26,7 +31,7 @@ WideGraph::WideGraph(QSettings * settings, QWidget *parent) :
ui->widePlot->setCursor(Qt::CrossCursor);
ui->widePlot->setMaximumHeight(800);
ui->widePlot->m_bCurrent=false;
ui->widePlot->setCurrent(false);
connect(ui->widePlot, SIGNAL(freezeDecode1(int)),this,
SLOT(wideFreezeDecode(int)));
@ -42,25 +47,25 @@ WideGraph::WideGraph(QSettings * settings, QWidget *parent) :
ui->zeroSpinBox->setValue(ui->widePlot->getPlotZero());
ui->gainSpinBox->setValue(ui->widePlot->getPlotGain());
int n = m_settings->value("FreqSpan",2).toInt();
int w = m_settings->value("PlotWidth",1000).toInt();
m_bFlatten=m_settings->value("Flatten",true).toBool();
ui->cbFlatten->setChecked(m_bFlatten);
ui->widePlot->m_w=w;
ui->widePlot->setBreadth(m_settings->value("PlotWidth",1000).toInt());
ui->freqSpanSpinBox->setValue(n);
ui->widePlot->setNSpan(n);
m_waterfallAvg = m_settings->value("WaterfallAvg",5).toInt();
ui->waterfallAvgSpinBox->setValue(m_waterfallAvg);
ui->widePlot->m_bCurrent=m_settings->value("Current",false).toBool();
ui->widePlot->m_bCumulative=m_settings->value("Cumulative",true).toBool();
ui->widePlot->m_bLinearAvg=m_settings->value("LinearAvg",false).toBool();
if(ui->widePlot->m_bCurrent) ui->spec2dComboBox->setCurrentIndex(0);
if(ui->widePlot->m_bCumulative) ui->spec2dComboBox->setCurrentIndex(1);
if(ui->widePlot->m_bLinearAvg) ui->spec2dComboBox->setCurrentIndex(2);
ui->widePlot->setCurrent(m_settings->value("Current",false).toBool());
ui->widePlot->setCumulative(m_settings->value("Cumulative",true).toBool());
ui->widePlot->setLinearAvg(m_settings->value("LinearAvg",false).toBool());
if(ui->widePlot->current()) ui->spec2dComboBox->setCurrentIndex(0);
if(ui->widePlot->cumulative()) ui->spec2dComboBox->setCurrentIndex(1);
if(ui->widePlot->linearAvg()) ui->spec2dComboBox->setCurrentIndex(2);
int nbpp=m_settings->value("BinsPerPixel",2).toInt();
ui->widePlot->setBinsPerPixel(nbpp);
ui->widePlot->setStartFreq(m_settings->value("StartFreq",0).toInt());
ui->fStartSpinBox->setValue(ui->widePlot->startFreq());
m_waterfallPalette=m_settings->value("WaterfallPalette","Default").toString();
m_userPalette = WFPalette {m_settings->value("UserPalette").value<WFPalette::Colours> ()};
int m_fMin = m_settings->value ("fMin", 2500).toInt ();
ui->fMinSpinBox->setValue (m_fMin);
setRxRange (m_fMin);
@ -68,10 +73,6 @@ WideGraph::WideGraph(QSettings * settings, QWidget *parent) :
saveSettings (); // update config with defaults
//m_palettes_path = configuration->resources_path ();
//QString palettes_dir {":/Palettes"};
//m_palettes_path.cd (palettes_dir);
QStringList allFiles = m_palettes_path.entryList(QDir::NoDotAndDotDot |
QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files,
QDir::DirsFirst);
@ -84,8 +85,14 @@ WideGraph::WideGraph(QSettings * settings, QWidget *parent) :
}
index++;
}
// ui->paletteComboBox->lineEdit()->setAlignment(Qt::AlignHCenter);
readPalette(m_palettes_path.absoluteFilePath (m_waterfallPalette + ".pal"));
ui->paletteComboBox->addItem (user_defined);
if (user_defined == m_waterfallPalette)
{
ui->paletteComboBox->setCurrentIndex(index);
}
readPalette ();
// ui->paletteComboBox->lineEdit()->setAlignment(Qt::AlignHCenter);
}
WideGraph::~WideGraph ()
@ -102,17 +109,18 @@ void WideGraph::saveSettings()
{
m_settings->beginGroup ("WideGraph");
m_settings->setValue ("geometry", saveGeometry ());
m_settings->setValue ("PlotZero", ui->widePlot->m_plotZero);
m_settings->setValue ("PlotGain", ui->widePlot->m_plotGain);
m_settings->setValue ("PlotZero", ui->widePlot->getPlotZero());
m_settings->setValue ("PlotGain", ui->widePlot->getPlotGain());
m_settings->setValue ("PlotWidth", ui->widePlot->plotWidth ());
m_settings->setValue ("FreqSpan", ui->freqSpanSpinBox->value ());
m_settings->setValue ("WaterfallAvg", ui->waterfallAvgSpinBox->value ());
m_settings->setValue ("Current", ui->widePlot->m_bCurrent);
m_settings->setValue ("Cumulative", ui->widePlot->m_bCumulative);
m_settings->setValue ("LinearAvg", ui->widePlot->m_bLinearAvg);
m_settings->setValue ("Current", ui->widePlot->current());
m_settings->setValue ("Cumulative", ui->widePlot->cumulative());
m_settings->setValue ("LinearAvg", ui->widePlot->linearAvg());
m_settings->setValue ("BinsPerPixel", ui->widePlot->binsPerPixel ());
m_settings->setValue ("StartFreq", ui->widePlot->startFreq ());
m_settings->setValue ("WaterfallPalette", m_waterfallPalette);
m_settings->setValue ("UserPalette", QVariant::fromValue (m_userPalette.colours ()));
m_settings->setValue ("Fmin", m_fMin);
m_settings->setValue("Flatten",m_bFlatten);
m_settings->endGroup ();
@ -218,12 +226,12 @@ int WideGraph::rxFreq()
int WideGraph::nSpan()
{
return ui->widePlot->m_nSpan;
return ui->widePlot->nSpan();
}
float WideGraph::fSpan()
{
return ui->widePlot->m_fSpan;
return ui->widePlot->fSpan();
}
int WideGraph::nStartFreq()
@ -292,12 +300,12 @@ void WideGraph::setModeTx(QString modeTx)
void WideGraph::on_spec2dComboBox_currentIndexChanged(const QString &arg1)
{
ui->widePlot->m_bCurrent=false;
ui->widePlot->m_bCumulative=false;
ui->widePlot->m_bLinearAvg=false;
if(arg1=="Current") ui->widePlot->m_bCurrent=true;
if(arg1=="Cumulative") ui->widePlot->m_bCumulative=true;
if(arg1=="Linear Avg") ui->widePlot->m_bLinearAvg=true;
ui->widePlot->setCurrent(false);
ui->widePlot->setCumulative(false);
ui->widePlot->setLinearAvg(false);
if(arg1=="Current") ui->widePlot->setCurrent(true);
if(arg1=="Cumulative") ui->widePlot->setCumulative(true);
if(arg1=="Linear Avg") ui->widePlot->setLinearAvg(true);
}
void WideGraph::on_fMinSpinBox_valueChanged(int n)
@ -309,7 +317,7 @@ void WideGraph::on_fMinSpinBox_valueChanged(int n)
void WideGraph::setLockTxFreq(bool b)
{
m_lockTxFreq=b;
ui->widePlot->m_lockTxFreq=b;
ui->widePlot->setLockTxFreq(b);
}
void WideGraph::setFreq2(int rxFreq, int txFreq)
@ -330,42 +338,31 @@ void WideGraph::on_fStartSpinBox_valueChanged(int n)
ui->widePlot->setStartFreq(n);
}
void WideGraph::readPalette(QString fileName)
void WideGraph::readPalette ()
{
QFile f;
f.setFileName(fileName);
if(f.open(QIODevice::ReadOnly)) {
QTextStream in(&f);
int r[9],g[9],b[9];
QString t;
for(int i=0; i<9; i++) {
t=in.readLine();
r[i]=t.mid(0,3).toInt();
g[i]=t.mid(4,3).toInt();
b[i]=t.mid(8,3).toInt();
try
{
if (user_defined == m_waterfallPalette)
{
ui->widePlot->setColours (WFPalette {m_userPalette}.interpolate ());
}
f.close();
for(int i=0; i<256; i++) {
int j0=i/32;
int j1=j0+1;
int k=i-32*j0;
int rr=r[j0] + int((k*(r[j1]-r[j0]))/31 + 0.5);
int gg=g[j0] + int((k*(g[j1]-g[j0]))/31 + 0.5);
int bb=b[j0] + int((k*(b[j1]-b[j0]))/31 + 0.5);
ui->widePlot->m_ColorTbl[i].setRgb(rr,gg,bb);
else
{
ui->widePlot->setColours (WFPalette {m_palettes_path.absoluteFilePath (m_waterfallPalette + ".pal")}.interpolate());
}
} else {
}
catch (std::exception const& e)
{
QMessageBox msgBox0;
QString t="Error: Cannot find requested palette file " + fileName;
msgBox0.setText(t);
msgBox0.setText(e.what());
msgBox0.exec();
}
}
void WideGraph::on_paletteComboBox_activated(const QString &palette)
void WideGraph::on_paletteComboBox_activated (QString const& palette)
{
m_waterfallPalette=palette;
readPalette(m_palettes_path.absoluteFilePath(palette + ".pal"));
m_waterfallPalette = palette;
readPalette();
}
void WideGraph::on_cbFlatten_toggled(bool b)
@ -373,6 +370,25 @@ void WideGraph::on_cbFlatten_toggled(bool b)
m_bFlatten=b;
}
void WideGraph::on_adjust_palette_push_button_clicked (bool)
{
try
{
if (m_userPalette.design ())
{
m_waterfallPalette = user_defined;
ui->paletteComboBox->setCurrentText (m_waterfallPalette);
readPalette ();
}
}
catch (std::exception const& e)
{
QMessageBox msgBox0;
msgBox0.setText(e.what());
msgBox0.exec();
}
}
bool WideGraph::flatten()
{
return m_bFlatten;

View File

@ -5,6 +5,8 @@
#include <QScopedPointer>
#include <QDir>
#include "WFPalette.hpp"
namespace Ui {
class WideGraph;
}
@ -37,7 +39,6 @@ public:
void setModeTx(QString modeTx);
void setLockTxFreq(bool b);
double fGreen();
void readPalette(QString fileName);
bool flatten();
signals:
@ -65,11 +66,15 @@ private slots:
void on_fStartSpinBox_valueChanged(int n);
void on_paletteComboBox_activated(const QString &palette);
void on_cbFlatten_toggled(bool b);
void on_adjust_palette_push_button_clicked (bool);
private:
void readPalette();
QScopedPointer<Ui::WideGraph> ui;
QSettings * m_settings;
QDir m_palettes_path;
WFPalette m_userPalette;
qint32 m_rxFreq;
qint32 m_txFreq;

View File

@ -52,7 +52,7 @@
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="6">
<item row="1" column="7">
<widget class="QComboBox" name="spec2dComboBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select data for spectral display&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@ -111,7 +111,7 @@
</property>
</widget>
</item>
<item row="1" column="4">
<item row="1" column="5">
<widget class="QComboBox" name="paletteComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@ -130,16 +130,6 @@
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="labPalette">
<property name="text">
<string> Palette</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="fMinSpinBox">
<property name="sizePolicy">
@ -251,7 +241,7 @@
</property>
</widget>
</item>
<item row="0" column="7">
<item row="0" column="8">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -305,6 +295,13 @@
</property>
</widget>
</item>
<item row="0" column="7">
<widget class="QCheckBox" name="cbFlatten">
<property name="text">
<string>Flatten</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QSpinBox" name="zeroSpinBox">
<property name="minimumSize">
@ -336,10 +333,38 @@
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QCheckBox" name="cbFlatten">
<item row="0" column="5">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="labPalette">
<property name="text">
<string>Flatten</string>
<string> Palette</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="adjust_palette_push_button">
<property name="text">
<string>Adjust...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="4" rowspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="0" column="6" rowspan="2">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>