Files
Radio/module/radio/BackEnd/IntermediateFrequencyWidget.cpp
T
2026-08-02 03:43:40 +08:00

302 lines
15 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "IntermediateFrequencyWidget.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPainter>
#include <QDebug>
#include "../component/FrequentShower.h"
#include "../component/ProgressBar.h"
#include "../component/ConsoleWidget.h"
#include "../component/ShowTime.h"
#include "../Global.h"
#include "../BaseWidget.h"
#include "../menu/BaseWidgetMenu.h"
#include "../BackEnd/MainWidget.h"
#include "../Tool.h"
static renderive::Range frequent_range = {-12000, 12000};
static double max = 160;
QWidget* Intermediate_Frequency_Widget::create_spectrogram_power_plot() {
class Spectrum_Plot : public renderive::Latency_Eager_Plot {
public:
std::shared_ptr<renderive::Frequency_Axis> x_axis{};
std::shared_ptr<renderive::Axis> y_axis{};
std::shared_ptr<renderive::Selection_Rectangle_Overlay> msr{};
std::shared_ptr<renderive::Spectrum> sp{};
QMenu* menu{};
void init() override {
Latency_Eager_Plot::init();
object_name = "Spectrum_Plot";
auto data = create_renderable_node(root_renderable(), "Data_Renderable");
auto frequency_axis_cache = create_renderable_node(root_renderable(), "Frequency_Axis_Cache");
auto power_axis_cache = create_renderable_node(root_renderable(), "Power_Axis_Cache");
auto overlay = create_renderable_node(root_renderable(), "Overlay_Renderable");
frequency_axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel);
power_axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel);
x_axis = renderive::Frequency_Axis::Builder(frequency_axis_cache, renderive::Orientation::Horizontal)
.set_tick_length(-10)
.set_coord_range(frequent_range)
.set_tick_length(-10)
.set_sub_tick_length(-5)
.build();
y_axis = renderive::Axis::Builder(power_axis_cache, renderive::Orientation::Vertical)
.set_coord_range({160, 0})
.set_unit_text("功率")
.build();
sp = renderive::Spectrum::Builder(data, x_axis, y_axis)
.set_frequency_range(frequent_range)
.set_sweep_region_visible(true)
.set_frequency_point_size(1024)
.build();
msr = renderive::Selection_Rectangle_Overlay::Builder(overlay, x_axis, y_axis).build();
}
protected:
void resizeEvent(QResizeEvent* event) override {
x_axis->set_x(0);
x_axis->set_y(height() - 1);
x_axis->set_pixel_length(width());
y_axis->set_x(0);
y_axis->set_y(0);
y_axis->set_pixel_length(height());
}
void contextMenuEvent(QContextMenuEvent* event) override {
if (!menu) {
auto ws = concat_widgets(
bw(cw(sp.get(), -1), "频谱图"),
bw(cw(x_axis.get()), "频率x轴"),
bw(cw(y_axis.get()), "功率y轴"),
bw(cw(msr.get()), "多选框"));
menu = create_menu(this, ws);
}
menu->exec(event->globalPos());
}
};
auto w = new Spectrum_Plot;
w->init();
spectrogram_line = w->sp;
progress_bar1->set_value = [this]() {
double middle_frequent = this->spectrogram_line->frequency_range().center();
bool ok = false;
double power = spectrogram_line->power_at(middle_frequent, ok);
if (ok)
this->progress_bar1->value = power;
};
return w;
}
QWidget* Intermediate_Frequency_Widget::create_Afterglow_Plot() {
class Afterglow_Plot : public renderive::Latency_Eager_Plot {
public:
std::shared_ptr<renderive::Frequency_Axis> x_axis{};
std::shared_ptr<renderive::Axis> y_axis{};
std::shared_ptr<renderive::Afterglow> ag{};
std::shared_ptr<renderive::Selection_Rectangle_Overlay> msr{};
QMenu* menu{};
void init() override {
Latency_Eager_Plot::init();
object_name = "Afterglow_Plot";
auto data = create_renderable_node(root_renderable(), "Data_Renderable");
auto frequency_axis_cache = create_renderable_node(root_renderable(), "Frequency_Axis_Cache");
auto power_axis_cache = create_renderable_node(root_renderable(), "Power_Axis_Cache");
auto overlay = create_renderable_node(root_renderable(), "Overlay_Renderable");
frequency_axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel);
power_axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel);
x_axis = renderive::Frequency_Axis::Builder(frequency_axis_cache, renderive::Orientation::Horizontal)
.set_coord_range(frequent_range)
.set_tick_length(-10)
.set_sub_tick_length(-5)
.set_use_drag(true)
.build();
y_axis = renderive::Axis::Builder(power_axis_cache, renderive::Orientation::Vertical)
.set_coord_range({160, 0})
.set_use_drag(true)
.build();
ag = renderive::Afterglow::Builder(data, x_axis, y_axis)
.set_frequency_range(frequent_range)
.set_power_range({0, 160})
.set_frequency_bin_count(1024)
.build();
msr = renderive::Selection_Rectangle_Overlay::Builder(overlay, x_axis, y_axis).build();
}
protected:
void resizeEvent(QResizeEvent* event) override {
x_axis->set_x(0);
x_axis->set_y(height() - 1);
x_axis->set_pixel_length(width());
y_axis->set_x(0);
y_axis->set_y(0);
y_axis->set_pixel_length(height());
ag->set_power_point_size(ag->power_axis()->pixel_sample_count());
}
void contextMenuEvent(QContextMenuEvent* event) override {
if (!menu) {
auto ws = concat_widgets(
bw(cw(ag.get(), -1), "余辉图"),
bw(cw(x_axis.get()), "频率轴"),
bw(cw(y_axis.get()), "功率概率轴"),
bw(cw(msr.get()), "多选框"));
menu = create_menu(this, ws);
}
menu->exec(event->globalPos());
}
};
auto w = new Afterglow_Plot;
w->init();
afterglow = w->ag;
return w;
}
//am, atu, vsql, nb, nr, dnf, pre, att, spl, fil1, agc_a
Intermediate_Frequency_Widget::Intermediate_Frequency_Widget(QWidget* parent) : Base_Widget(parent) {
setObjectName("发射界面");
int font_size = 20;
m1 = create_normal("RF Gain\n62", font_size);
m2 = create_normal("FFT SPAN\n100K", font_size);
m3 = create_normal("频率表\n1289.6MHZ", font_size);
m4 = create_normal("MODEM\nRTTY", font_size);
m5 = create_normal("FIL1\n20K", font_size);
m6 = create_normal("MSG1\n", font_size);
frequent_shower = new Frequent_Shower(this);
QColor orange(255, 165, 0);
progress_bar1 = new Progress_Bar({
Tick("S", Qt::black),
{"3", Qt::black},
{"6", Qt::black},
{"9", Qt::black},
{"20", Qt::black},
{"+40", orange},
{"+60", orange},
{"+80", orange},
{"+100", Qt::red},
}, this);
progress_bar2 = new Progress_Bar({
{"1", Qt::black},
{"2", Qt::yellow},
{"3", Qt::red},
{">5", Qt::red},
}, this);
auto main = create_vbox_layout({}, this);
main->addStretch(1);
{
auto center = create_hbox_layout();
main->addLayout(center, 7);
auto front = create_vbox_layout();
center->addLayout(front, 1);
front->addWidget(m1, 3);
front->addStretch(1);
front->addWidget(m2, 3);
center->addSpacing(4);
auto middle = create_vbox_layout();
center->addLayout(middle, 9);
middle->addStretch(1);
middle->addWidget(frequent_shower, 4);
auto middle_h = create_hbox_layout();
middle->addLayout(middle_h, 2);
middle_h->addWidget(progress_bar1, 5);
middle_h->addStretch(1);
middle_h->addWidget(progress_bar2, 3);
center->addStretch(4);
auto back1 = create_vbox_layout();
center->addLayout(back1, 1);
back1->addWidget(m3, 3);
back1->addStretch(1);
back1->addWidget(m4, 3);
center->addSpacing(4);
auto back2 = create_vbox_layout();
center->addLayout(back2, 1);
back2->addWidget(m5, 3);
back2->addStretch(1);
back2->addWidget(m6, 3);
}
main->addStretch(1);
main->addSpacing(8);
auto a_h = create_hbox_layout();
main->addLayout(a_h, 12);
a_h->addWidget(create_spectrogram_power_plot(), 12);
a_h->addSpacing(8);
main->addWidget(create_Afterglow_Plot(), 12);
init_menu();
}
Intermediate_Frequency_Widget::~Intermediate_Frequency_Widget() {}
void Intermediate_Frequency_Widget::focusInEvent(QFocusEvent* event) {
QWidget::focusInEvent(event);
frequent_shower->setFocus();
}
void Intermediate_Frequency_Widget::init_menu() {
int font_size = 30;
auto btn1 = new Double_Text_Menu_Button("设置最大值标记", "取消最大值标记", font_size, [&](bool is_first) {
spectrogram_line->set_max_marker_visible(is_first);
base_widget_menu->hide();
Main_Widget::instance()->get_current_base_widget()->setFocus();
});
auto btn2 = new Double_Text_Menu_Button("设置最小值标记", "取消最小值标记", font_size, [&](bool is_first) {
spectrogram_line->set_use_min_marker(is_first);
base_widget_menu->hide();
Main_Widget::instance()->get_current_base_widget()->setFocus();
});
auto btn3 = new Menu_Button("设置自定义标记", font_size, [&]() {
base_widget_menu->hide();
Main_Widget::instance()->get_current_base_widget()->setFocus();
});
auto frequent_step2 = new Value_Menu_Button("频率步进:%1", font_size, [this](Value_Menu_Button* that, bool add) {
int new_frequent = (int)that->value + (add ? 1 : -1);
that->setValue(new_frequent);
spectrogram_line->set_current_marker_frequency(new_frequent);
}, qMax(0.0, spectrogram_line->frequency_range().length() / 50.0));
auto btn_middle_frequent = new Value_Menu_Button("中频:%1 Hz", font_size, nullptr, spectrogram_line->center_frequency());
auto btn_frequent_width = new Value_Menu_Button("频宽:%1 Hz", font_size, [this, frequent_step2](Value_Menu_Button* that, bool add) {
that->setValue(that->value + (double)(add ? frequent_step2->value : -frequent_step2->value));
double middle_sweep_frequent = spectrogram_line->center_frequency();
spectrogram_line->set_sweep_frequency_range({middle_sweep_frequent - that->value, middle_sweep_frequent + that->value});
}, qAbs(spectrogram_line->sweep_frequency_range().length() / 2));
btn_middle_frequent->value_changed = [this, btn_frequent_width, frequent_step2](Value_Menu_Button* that, bool add) {
that->setValue(that->value + (double)(add ? frequent_step2->value : -frequent_step2->value));
spectrogram_line->set_center_frequency(that->value);
spectrogram_line->set_sweep_frequency_range({that->value - btn_frequent_width->value, that->value + btn_frequent_width->value});
};
auto btn2_2 = new Value_Menu_Button("参考增益:%1", font_size, [&](Value_Menu_Button* that, bool add) {
that->setValue(that->value + (double)(add ? 1 : -1));
}, 0);
base_widget_menu->add_menu_button_on_layout1({btn1, btn2, btn3, btn2_2,});
base_widget_menu->add_menu_button_on_layout2({frequent_step2, btn_middle_frequent, btn_frequent_width,});
Base_Widget_Menu* sub1 = base_widget_menu->create_sub_widget_menu(btn3);
auto frequent_step = new Value_Menu_Button("频率步进:%1", font_size, [this](Value_Menu_Button* that, bool add) {
int new_frequent = (int)that->value + (add ? 1 : -1);
that->setValue(new_frequent);
spectrogram_line->set_current_marker_frequency(new_frequent);
}, qMax(0.0, spectrogram_line->frequency_range().length() / 50.0));
auto mark_frequent = new Value_Menu_Button("更改标记频率:%1", font_size, [frequent_step, this](Value_Menu_Button* that, bool add) {
int new_frequent = (int)that->value + (add ? frequent_step->value : -frequent_step->value);
that->setValue(new_frequent);
spectrogram_line->set_current_marker_frequency(new_frequent);
}, -1);
auto add_init_frequent = new Value_Menu_Button("添加初始频率:%1", font_size, [frequent_step,this](Value_Menu_Button* that, bool add) {
int new_frequent = (int)that->value + (add ? frequent_step->value : -frequent_step->value);
that->setValue(new_frequent);
}, spectrogram_line->frequency_range().origin);
auto btn1_1 = new Value_Menu_Button("当前标记:%1", font_size, [&, mark_frequent](Value_Menu_Button* that, bool add) {
int index = ((int)that->value + (add ? 1 : -1)) % spectrogram_line->selectable_line_marker_count();
that->setValue(index);
spectrogram_line->set_selected_marker_index(index);
mark_frequent->setValue(spectrogram_line->marker_frequency(index));
}, -1);
auto btn1_2 = new Menu_Button("添加标记", font_size, [&, add_init_frequent]() {
spectrogram_line->add_custom_line_marker(add_init_frequent->value);
});
auto btn1_3 = new Menu_Button("删除标记", font_size, [&]() {
spectrogram_line->remove_selected_marker();
int size = spectrogram_line->selectable_line_marker_count();
if (size == 0) {
spectrogram_line->set_selected_marker_index(-1);
}
else {
spectrogram_line->set_selected_marker_index(0);
}
});
connect(sub1, &Base_Widget_Menu::show_that, [&, mark_frequent]() {
spectrogram_line->set_selected_marker_index(0);
mark_frequent->setValue(spectrogram_line->marker_frequency(0));
});
connect(sub1, &Base_Widget_Menu::hide_that, [&]() {
spectrogram_line->clear_marker_selection();
});
sub1->add_menu_button_on_layout1({btn1_1, btn1_2, btn1_3}, 2);
sub1->add_menu_button_on_layout2({frequent_step, mark_frequent, add_init_frequent}, 2);
}