mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-22 04:11:16 -05:00
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:
parent
a893d42288
commit
31ebdc9618
@ -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
307
WFPalette.cpp
Normal 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
55
WFPalette.hpp
Normal 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
|
53
plotter.h
53
plotter.h
@ -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;
|
||||
|
@ -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
|
||||
|
87
wf_palette_design_dialog.ui
Normal file
87
wf_palette_design_dialog.ui
Normal 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>
|
134
widegraph.cpp
134
widegraph.cpp
@ -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 ());
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->widePlot->setColours (WFPalette {m_palettes_path.absoluteFilePath (m_waterfallPalette + ".pal")}.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);
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
QMessageBox msgBox0;
|
||||
msgBox0.setText(e.what());
|
||||
msgBox0.exec();
|
||||
}
|
||||
} else {
|
||||
QMessageBox msgBox0;
|
||||
QString t="Error: Cannot find requested palette file " + fileName;
|
||||
msgBox0.setText(t);
|
||||
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;
|
||||
|
@ -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;
|
||||
|
59
widegraph.ui
59
widegraph.ui
@ -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><html><head/><body><p>Select data for spectral display</p></body></html></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">
|
||||
<property name="text">
|
||||
<string>Flatten</string>
|
||||
<item row="0" column="5">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<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>
|
||||
<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>
|
||||
|
Loading…
Reference in New Issue
Block a user