diff --git a/module/radio/BackEnd/BackEnd_Mock.cpp b/module/radio/BackEnd/BackEnd_Mock.cpp index c93666a..81964be 100644 --- a/module/radio/BackEnd/BackEnd_Mock.cpp +++ b/module/radio/BackEnd/BackEnd_Mock.cpp @@ -52,24 +52,24 @@ void push_radio_data(Radio_Widget* rw) { return; { auto r = rw->spectrogram_line->power_axis()->coord_range(); - renderive::Range nr = {r.middle() - r.length() / 4, r.middle() + r.length() / 4}; + renderive::Range nr = {r.center() - r.length() / 4, r.center() + r.length() / 4}; auto data = make_random_data(nr, rw->spectrogram_line->frequency_point_size(), renderive::Memory_Domain::Spectrum); - double middle_power = data.empty() ? nr.middle() : data[data.size() / 2]; - rw->spectrogram_line->give_data(std::move(data)); + double middle_power = data.empty() ? nr.center() : data[data.size() / 2]; + rw->spectrogram_line->update_samples(std::move(data)); rw->progress_bar1->setValue(middle_power); } { - rw->water_fall->give_data(current_render_time(), make_random_data(rw->water_fall->power_range(), rw->water_fall->frequency_point_size(), renderive::Memory_Domain::Waterfall)); + rw->water_fall->append_row(current_render_time(), make_random_data(rw->water_fall->power_range(), rw->water_fall->frequency_bin_count(), renderive::Memory_Domain::Waterfall)); } { renderive::Range r = rw->time_power->value_axis()->coord_range(); - renderive::Range nr = {r.middle() - r.length() / 4, r.middle() + r.length() / 4}; - rw->time_power->give_data(current_render_time(), make_random_value(nr)); + renderive::Range nr = {r.center() - r.length() / 4, r.center() + r.length() / 4}; + rw->time_power->append_sample(current_render_time(), make_random_value(nr)); } { auto r = rw->audio_spectrogram_plot->power_axis()->coord_range(); - renderive::Range nr = {r.middle() - r.length() / 4, r.middle() + r.length() / 4}; - rw->audio_spectrogram_plot->give_data(make_random_data(nr, rw->audio_spectrogram_plot->frequency_point_size(), renderive::Memory_Domain::Spectrum)); + renderive::Range nr = {r.center() - r.length() / 4, r.center() + r.length() / 4}; + rw->audio_spectrogram_plot->update_samples(make_random_data(nr, rw->audio_spectrogram_plot->frequency_point_size(), renderive::Memory_Domain::Spectrum)); } rw->progress_bar2->setValue(make_random_value({1, 5})); } @@ -79,18 +79,18 @@ void push_radio_data_perf(Radio_Widget* rw) { { renderive::Range nr = {40, 120}; auto data = make_random_data(nr, 1024, renderive::Memory_Domain::Spectrum); - double middle_power = data.empty() ? nr.middle() : data[data.size() / 2]; - rw->spectrogram_line->give_data(std::move(data)); + double middle_power = data.empty() ? nr.center() : data[data.size() / 2]; + rw->spectrogram_line->update_samples(std::move(data)); rw->progress_bar1->setValue(middle_power); } { - rw->water_fall->give_data(current_render_time(), make_random_data({0, 160}, 1024, renderive::Memory_Domain::Waterfall)); + rw->water_fall->append_row(current_render_time(), make_random_data({0, 160}, 1024, renderive::Memory_Domain::Waterfall)); } { - rw->time_power->give_data(current_render_time(), make_random_value({-6000, 6000})); + rw->time_power->append_sample(current_render_time(), make_random_value({-6000, 6000})); } { - rw->audio_spectrogram_plot->give_data(make_random_data({-6000, 6000}, 512, renderive::Memory_Domain::Spectrum)); + rw->audio_spectrogram_plot->update_samples(make_random_data({-6000, 6000}, 512, renderive::Memory_Domain::Spectrum)); } rw->progress_bar2->setValue(make_random_value({1, 5})); } diff --git a/module/radio/BackEnd/IntermediateFrequencyWidget.cpp b/module/radio/BackEnd/IntermediateFrequencyWidget.cpp index 9a0764e..5510b08 100644 --- a/module/radio/BackEnd/IntermediateFrequencyWidget.cpp +++ b/module/radio/BackEnd/IntermediateFrequencyWidget.cpp @@ -11,7 +11,7 @@ #include "../BaseWidget.h" #include "../menu/BaseWidgetMenu.h" #include "../BackEnd/MainWidget.h" -#include "Demo_Gallery/base/export.h" +#include "../Tool.h" static renderive::Range frequent_range = {-12000, 12000}; static double max = 160; QWidget* Intermediate_Frequency_Widget::create_spectrogram_power_plot() { @@ -19,51 +19,51 @@ QWidget* Intermediate_Frequency_Widget::create_spectrogram_power_plot() { public: std::shared_ptr x_axis{}; std::shared_ptr y_axis{}; - std::shared_ptr msr{}; + std::shared_ptr msr{}; std::shared_ptr sp{}; QMenu* menu{}; void init() override { Latency_Eager_Plot::init(); object_name = "Spectrum_Plot"; - auto data = create_renderable_node(get_root_renderable(), "Data_Renderable"); - auto frequency_axis_cache = create_renderable_node(get_root_renderable(), "Frequency_Axis_Cache"); - auto power_axis_cache = create_renderable_node(get_root_renderable(), "Power_Axis_Cache"); - auto overlay = create_renderable_node(get_root_renderable(), "Overlay_Renderable"); + 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(); + .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(); + .set_coord_range({160, 0}) + .set_unit_text("功率") + .build(); sp = renderive::Spectrum::Builder(data, x_axis, y_axis) .set_frequency_range(frequent_range) - .set_use_sweep_frequency_rect(true) + .set_sweep_region_visible(true) .set_frequency_point_size(1024) .build(); - msr = renderive::Multi_Select_Rect::Builder(overlay, x_axis, y_axis).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_size(width()); + x_axis->set_pixel_length(width()); y_axis->set_x(0); y_axis->set_y(0); - y_axis->set_pixel_size(height()); + 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()), "多选框")); + 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()); @@ -73,9 +73,9 @@ QWidget* Intermediate_Frequency_Widget::create_spectrogram_power_plot() { w->init(); spectrogram_line = w->sp; progress_bar1->set_value = [this]() { - double middle_frequent = this->spectrogram_line->frequency_range().middle(); + double middle_frequent = this->spectrogram_line->frequency_range().center(); bool ok = false; - double power = spectrogram_line->get_power(middle_frequent, ok); + double power = spectrogram_line->power_at(middle_frequent, ok); if (ok) this->progress_bar1->value = power; }; @@ -87,51 +87,51 @@ QWidget* Intermediate_Frequency_Widget::create_Afterglow_Plot() { std::shared_ptr x_axis{}; std::shared_ptr y_axis{}; std::shared_ptr ag{}; - std::shared_ptr msr{}; + std::shared_ptr msr{}; QMenu* menu{}; void init() override { Latency_Eager_Plot::init(); object_name = "Afterglow_Plot"; - auto data = create_renderable_node(get_root_renderable(), "Data_Renderable"); - auto frequency_axis_cache = create_renderable_node(get_root_renderable(), "Frequency_Axis_Cache"); - auto power_axis_cache = create_renderable_node(get_root_renderable(), "Power_Axis_Cache"); - auto overlay = create_renderable_node(get_root_renderable(), "Overlay_Renderable"); + 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(); + .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(); + .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_point_size(1024) + .set_frequency_bin_count(1024) .build(); - msr = renderive::Multi_Select_Rect::Builder(overlay, x_axis, y_axis).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_size(width()); + x_axis->set_pixel_length(width()); y_axis->set_x(0); y_axis->set_y(0); - y_axis->set_pixel_size(height()); - ag->set_power_point_size(ag->power_axis()->get_pixel_point_size()); + 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()), "多选框")); + 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()); @@ -155,22 +155,22 @@ Intermediate_Frequency_Widget::Intermediate_Frequency_Widget(QWidget* parent) : 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); + 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); + {"1", Qt::black}, + {"2", Qt::yellow}, + {"3", Qt::red}, + {">5", Qt::red}, + }, this); auto main = create_vbox_layout({}, this); main->addStretch(1); { @@ -221,7 +221,7 @@ void Intermediate_Frequency_Widget::focusInEvent(QFocusEvent* event) { 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_use_max_marker(is_first); + spectrogram_line->set_max_marker_visible(is_first); base_widget_menu->hide(); Main_Widget::instance()->get_current_base_widget()->setFocus(); }); @@ -239,15 +239,15 @@ void Intermediate_Frequency_Widget::init_menu() { 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->middle_sweep_frequency()); + 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->middle_sweep_frequency(); + 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_middle_sweep_frequency(that->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) { @@ -271,30 +271,30 @@ void Intermediate_Frequency_Widget::init_menu() { 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->select_line_marker_size(); + int index = ((int)that->value + (add ? 1 : -1)) % spectrogram_line->selectable_line_marker_count(); that->setValue(index); - spectrogram_line->set_selected_line_marker(index); - mark_frequent->setValue(spectrogram_line->get_mark_frequency(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_current_marker(); - int size = spectrogram_line->select_line_marker_size(); + spectrogram_line->remove_selected_marker(); + int size = spectrogram_line->selectable_line_marker_count(); if (size == 0) { - spectrogram_line->set_selected_line_marker(-1); + spectrogram_line->set_selected_marker_index(-1); } else { - spectrogram_line->set_selected_line_marker(0); + spectrogram_line->set_selected_marker_index(0); } }); connect(sub1, &Base_Widget_Menu::show_that, [&, mark_frequent]() { - spectrogram_line->set_selected_line_marker(0); - mark_frequent->setValue(spectrogram_line->get_mark_frequency(0)); + spectrogram_line->set_selected_marker_index(0); + mark_frequent->setValue(spectrogram_line->marker_frequency(0)); }); connect(sub1, &Base_Widget_Menu::hide_that, [&]() { - spectrogram_line->un_select_marker(); + 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); diff --git a/module/radio/BackEnd/RadioWidget.cpp b/module/radio/BackEnd/RadioWidget.cpp index 20dbf0d..187df0a 100644 --- a/module/radio/BackEnd/RadioWidget.cpp +++ b/module/radio/BackEnd/RadioWidget.cpp @@ -10,8 +10,8 @@ #include "../menu/BaseWidgetMenu.h" #include "BackEnd.h" #include "../BackEnd/MainWidget.h" -#include "Demo_Gallery/base/export.h" #include "Core/plottable/export.h" +#include "module/radio/Tool.h" static double max = 160; static renderive::Range frequent_range = {-12000, 12000}; static bool radio_mock_perf_mode() { @@ -29,8 +29,8 @@ static void configure_radio_plot_perf(renderive::Latency_Eager_Plot* plot) { return; plot->set_max_render_fps(1000); } -static renderive::Performance_Shower_Options radio_performance_options() { - renderive::Performance_Shower_Options options; +static renderive::Performance_Overlay_Options radio_performance_options() { + renderive::Performance_Overlay_Options options; options.font.size = 11.0; options.background = renderive::Color{20, 20, 20, 255}; options.foreground = renderive::Color::white(); @@ -47,12 +47,12 @@ static void apply_radio_performance_overlay(renderive::Latency_Eager_Plot* plot) } if (!plot || !plot->core()) return; - auto shower = renderive::attach_performance_shower(*plot->core(), radio_performance_options()); + auto shower = renderive::attach_performance_overlay(*plot->core(), radio_performance_options()); if (!shower) return; - shower->setEnabled(enabled); + shower->set_enabled(enabled); if (enabled) - renderive::notify_performance_shower_viewport_changed(*plot->core()); + renderive::notify_performance_overlay_viewport_changed(*plot->core()); } struct Radio_Plot_Layout { int left_axis_width{}; @@ -77,12 +77,12 @@ static void apply_radio_plot_layout(renderive::Abs_Axis* x_axis, renderive::Abs_ if (x_axis) { x_axis->set_x(layout.content_x); x_axis->set_y(layout.content_y + layout.content_height); - x_axis->set_pixel_size(static_cast(layout.content_width)); + x_axis->set_pixel_length(static_cast(layout.content_width)); } if (y_axis) { y_axis->set_x(layout.content_x); y_axis->set_y(layout.content_y); - y_axis->set_pixel_size(static_cast(layout.content_height)); + y_axis->set_pixel_length(static_cast(layout.content_height)); } } QWidget* Radio_Widget::create_spectrogram_power_plot() { @@ -90,21 +90,21 @@ QWidget* Radio_Widget::create_spectrogram_power_plot() { public: std::shared_ptr x_axis{}; std::shared_ptr y_axis{}; - std::shared_ptr msr{}; + std::shared_ptr msr{}; std::shared_ptr sp{}; QMenu* menu{}; void init() override { Latency_Eager_Plot::init(); configure_radio_plot_perf(this); object_name = "Spectrum_Plot"; - auto data = create_renderable_node(get_root_renderable(), "Data_Renderable"); + auto data = create_renderable_node(root_renderable(), "Data_Renderable"); // auto frequency_axis_cache = create_renderable_node(get_root_renderable(), "Frequency_Axis_Cache"); // auto power_axis_cache = create_renderable_node(get_root_renderable(), "Power_Axis_Cache"); // frequency_axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel); // power_axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel); - auto axis_cache = create_renderable_node(get_root_renderable(), "Power_Axis_Cache"); + auto axis_cache = create_renderable_node(root_renderable(), "Power_Axis_Cache"); axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel); - auto overlay = create_renderable_node(get_root_renderable(), "Overlay_Renderable"); + auto overlay = create_renderable_node(root_renderable(), "Overlay_Renderable"); x_axis = renderive::Frequency_Axis::Builder(axis_cache, renderive::Orientation::Horizontal) .set_coord_range(frequent_range) .set_tick_length(10) @@ -119,7 +119,7 @@ QWidget* Radio_Widget::create_spectrogram_power_plot() { .set_frequency_range(frequent_range) .set_frequency_point_size(1024) .build(); - msr = renderive::Multi_Select_Rect::Builder(overlay, x_axis, y_axis).build(); + msr = renderive::Selection_Rectangle_Overlay::Builder(overlay, x_axis, y_axis).build(); } protected: void resizeEvent(QResizeEvent* event) override { @@ -143,9 +143,9 @@ QWidget* Radio_Widget::create_spectrogram_power_plot() { spectrogram_line = w->sp; if (!radio_mock_perf_mode()) { progress_bar1->set_value = [this]() { - double middle_frequent = this->spectrogram_line->frequency_range().middle(); + double middle_frequent = this->spectrogram_line->frequency_range().center(); bool ok = false; - double power = spectrogram_line->get_power(middle_frequent, ok); + double power = spectrogram_line->power_at(middle_frequent, ok); if (ok) this->progress_bar1->setValue(power); }; @@ -157,18 +157,18 @@ QWidget* Radio_Widget::create_water_fall_plot() { public: std::shared_ptr x_axis{}; std::shared_ptr y_axis{}; - std::shared_ptr msr{}; + std::shared_ptr msr{}; std::shared_ptr wf{}; QMenu* menu{}; void init() override { Latency_Eager_Plot::init(); configure_radio_plot_perf(this); object_name = "Water_Fall_Plot"; - auto stream_cache = create_renderable_node(get_root_renderable(), "Waterfall_Stream_Cache"); + auto stream_cache = create_renderable_node(root_renderable(), "Waterfall_Stream_Cache"); auto data = create_renderable_node(stream_cache, "Data_Renderable"); auto time_axis = create_renderable_node(stream_cache, "Time_Axis_Renderable"); - auto frequency_axis_cache = create_renderable_node(get_root_renderable(), "Frequency_Axis_Cache"); - auto overlay = create_renderable_node(get_root_renderable(), "Overlay_Renderable"); + auto frequency_axis_cache = create_renderable_node(root_renderable(), "Frequency_Axis_Cache"); + auto overlay = create_renderable_node(root_renderable(), "Overlay_Renderable"); stream_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel); frequency_axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel); x_axis = renderive::Frequency_Axis::Builder(frequency_axis_cache, renderive::Orientation::Horizontal) @@ -179,14 +179,14 @@ QWidget* Radio_Widget::create_water_fall_plot() { y_axis = renderive::Time_Axis::Builder(time_axis, renderive::Orientation::Vertical) .set_tick_length(-10) .set_sub_tick_length(-5) - .set_time_point_size(100) + .set_visible_time_point_count(100) .build(); wf = renderive::Waterfall::Builder(data, x_axis, y_axis) .set_frequency_range(frequent_range) - .set_frequency_point_size(1024) + .set_frequency_bin_count(1024) .set_power_range({0, max}) .build(); - msr = renderive::Multi_Select_Rect::Builder(overlay, x_axis, y_axis).build(); + msr = renderive::Selection_Rectangle_Overlay::Builder(overlay, x_axis, y_axis).build(); } protected: void resizeEvent(QResizeEvent* event) override { @@ -215,17 +215,17 @@ QWidget* Radio_Widget::create_audio_spectrogram_plot() { public: std::shared_ptr x_axis{}; std::shared_ptr y_axis{}; - std::shared_ptr msr{}; + std::shared_ptr msr{}; std::shared_ptr sp{}; QMenu* menu{}; void init() override { Latency_Eager_Plot::init(); configure_radio_plot_perf(this); object_name = "Spectrum_Plot"; - auto data = create_renderable_node(get_root_renderable(), "Data_Renderable"); - auto frequency_axis_cache = create_renderable_node(get_root_renderable(), "Frequency_Axis_Cache"); - auto power_axis_cache = create_renderable_node(get_root_renderable(), "Power_Axis_Cache"); - auto overlay = create_renderable_node(get_root_renderable(), "Overlay_Renderable"); + 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) @@ -242,7 +242,7 @@ QWidget* Radio_Widget::create_audio_spectrogram_plot() { .set_frequency_range({-12000, 12000}) .set_frequency_point_size(512) .build(); - msr = renderive::Multi_Select_Rect::Builder(overlay, x_axis, y_axis).build(); + msr = renderive::Selection_Rectangle_Overlay::Builder(overlay, x_axis, y_axis).build(); } protected: void resizeEvent(QResizeEvent* event) override { @@ -271,18 +271,18 @@ QWidget* Radio_Widget::create_time_power_plot() { public: std::shared_ptr x_axis{}; std::shared_ptr y_axis{}; - std::shared_ptr audio{}; - std::shared_ptr msr{}; + std::shared_ptr audio{}; + std::shared_ptr msr{}; QMenu* menu{}; void init() override { Latency_Eager_Plot::init(); configure_radio_plot_perf(this); object_name = "Audio_Plot"; - auto stream_cache = create_renderable_node(get_root_renderable(), "Audio_Stream_Cache"); + auto stream_cache = create_renderable_node(root_renderable(), "Audio_Stream_Cache"); auto data = create_renderable_node(stream_cache, "Data_Renderable"); auto time_axis = create_renderable_node(stream_cache, "Time_Axis_Renderable"); - auto power_axis_cache = create_renderable_node(get_root_renderable(), "Power_Axis_Cache"); - auto overlay = create_renderable_node(get_root_renderable(), "Overlay_Renderable"); + auto power_axis_cache = create_renderable_node(root_renderable(), "Power_Axis_Cache"); + auto overlay = create_renderable_node(root_renderable(), "Overlay_Renderable"); stream_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::Time_Axis::Builder(time_axis, renderive::Orientation::Horizontal) @@ -294,14 +294,14 @@ QWidget* Radio_Widget::create_time_power_plot() { .set_tick_length(-10) .set_sub_tick_length(-5) .build(); - audio = renderive::Audio_Frequency::Builder(data, x_axis, y_axis) + audio = renderive::Frequency_Trace::Builder(data, x_axis, y_axis) .build(); - msr = renderive::Multi_Select_Rect::Builder(overlay, x_axis, y_axis).build(); + msr = renderive::Selection_Rectangle_Overlay::Builder(overlay, x_axis, y_axis).build(); } protected: void resizeEvent(QResizeEvent* event) override { apply_radio_plot_layout(x_axis.get(), y_axis.get(), width(), height()); - x_axis->set_time_point_size(x_axis->get_pixel_point_size()); + x_axis->set_time_point_size(x_axis->pixel_sample_count()); } void contextMenuEvent(QContextMenuEvent* event) override { if (!menu) { diff --git a/module/radio/BackEnd/RadioWidget.h b/module/radio/BackEnd/RadioWidget.h index 8a0fd8e..211b112 100644 --- a/module/radio/BackEnd/RadioWidget.h +++ b/module/radio/BackEnd/RadioWidget.h @@ -28,7 +28,7 @@ public: QWidget* create_water_fall_plot(); std::shared_ptr spectrogram_line{}; std::shared_ptr audio_spectrogram_plot{}; - std::shared_ptr time_power{}; + std::shared_ptr time_power{}; std::shared_ptr water_fall{}; protected: void focusInEvent(QFocusEvent *event) override; diff --git a/module/radio/BackEnd/SweepFrequencyWidget.cpp b/module/radio/BackEnd/SweepFrequencyWidget.cpp index 940eaf5..665853f 100644 --- a/module/radio/BackEnd/SweepFrequencyWidget.cpp +++ b/module/radio/BackEnd/SweepFrequencyWidget.cpp @@ -9,59 +9,59 @@ #include "../component/ShowTime.h" #include "../Global.h" #include "../menu/BaseWidgetMenu.h" -#include "Demo_Gallery/base/export.h" +#include "module/radio/Tool.h" QWidget* Sweep_Frequency_Widget::create_spectrogram_power_plot() { - class Sweep_Frequent_Plot : public renderive::Latency_Eager_Plot { + class Sweep_Frequency_Plot : public renderive::Latency_Eager_Plot { public: std::shared_ptr x_axis{}; std::shared_ptr y_axis{}; - std::shared_ptr msr{}; - std::shared_ptr sf{}; + std::shared_ptr msr{}; + std::shared_ptr sf{}; QMenu* menu{}; void init() override { Latency_Eager_Plot::init(); object_name = "Axis_Test_Plot"; - auto data = create_renderable_node(get_root_renderable(), "Data_Renderable"); - auto x_axis_cache = create_renderable_node(get_root_renderable(), "X_Axis_Cache"); - auto y_axis_cache = create_renderable_node(get_root_renderable(), "Y_Axis_Cache"); - auto overlay = create_renderable_node(get_root_renderable(), "Overlay_Renderable"); + auto data = create_renderable_node(root_renderable(), "Data_Renderable"); + auto x_axis_cache = create_renderable_node(root_renderable(), "X_Axis_Cache"); + auto y_axis_cache = create_renderable_node(root_renderable(), "Y_Axis_Cache"); + auto overlay = create_renderable_node(root_renderable(), "Overlay_Renderable"); x_axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel); y_axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel); x_axis = renderive::Axis::Builder(x_axis_cache, renderive::Orientation::Horizontal) - .set_coord_range({0, 100}) - .set_tick_length(-10).build(); + .set_coord_range({0, 100}) + .set_tick_length(-10).build(); y_axis = renderive::Axis::Builder(y_axis_cache, renderive::Orientation::Vertical) - .set_coord_range({100, 0}) - .set_tick_length(-10).build(); - sf = renderive::Sweep_Frequency::Builder(data, x_axis, y_axis) + .set_coord_range({100, 0}) + .set_tick_length(-10).build(); + sf = renderive::Sweep_Spectrum::Builder(data, x_axis, y_axis) .set_block_num(200) - .set_block_frequency_point_size(20) + .set_bins_per_block(20) .set_frequency_range({0, 100}) .build(); - msr = renderive::Multi_Select_Rect::Builder(overlay, x_axis, y_axis).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_size(width()); + x_axis->set_pixel_length(width()); y_axis->set_x(0); y_axis->set_y(0); - y_axis->set_pixel_size(height()); + y_axis->set_pixel_length(height()); } void contextMenuEvent(QContextMenuEvent* event) override { if (!menu) { auto ws = concat_widgets( - bw(cw(sf.get(), -1), "扫频图"), - bw(cw(x_axis.get()), "x轴"), - bw(cw(y_axis.get()), "y轴"), - bw(cw(msr.get()), "多选框")); + bw(cw(sf.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 Sweep_Frequent_Plot; + auto w = new Sweep_Frequency_Plot; w->init(); sweep_frequency_line = w->sf; return w; @@ -76,21 +76,21 @@ Sweep_Frequency_Widget::Sweep_Frequency_Widget(QWidget* parent) : Base_Widget(pa m4 = create_normal("MODEM\nRTTY", font_size); select_value_widget = new Frequent_Shower(this); progress_bar1 = new Progress_Bar({ - {"S", Qt::black}, - {"3", Qt::black}, - {"5", Qt::black}, - {"7", Qt::black}, - {"9", Qt::black}, - {"+20", Qt::yellow}, - {"+40", Qt::yellow}, - {"+60", Qt::red}, - }, this); + {"S", Qt::black}, + {"3", Qt::black}, + {"5", Qt::black}, + {"7", Qt::black}, + {"9", Qt::black}, + {"+20", Qt::yellow}, + {"+40", Qt::yellow}, + {"+60", Qt::red}, + }, this); progress_bar2 = new Progress_Bar({ - {"1", Qt::black}, - {"2", Qt::yellow}, - {"3", Qt::red}, - {">5", Qt::red}, - }, this); + {"1", Qt::black}, + {"2", Qt::yellow}, + {"3", Qt::red}, + {">5", Qt::red}, + }, this); auto main = create_vbox_layout({}, this); main->addStretch(1); { diff --git a/module/radio/BackEnd/SweepFrequencyWidget.h b/module/radio/BackEnd/SweepFrequencyWidget.h index 5962bfa..831c6b9 100644 --- a/module/radio/BackEnd/SweepFrequencyWidget.h +++ b/module/radio/BackEnd/SweepFrequencyWidget.h @@ -23,7 +23,7 @@ public: Frequent_Shower *select_value_widget; Progress_Bar *progress_bar1, *progress_bar2; void init_menu(); - std::shared_ptr sweep_frequency_line{}; + std::shared_ptr sweep_frequency_line{}; QWidget* create_spectrogram_power_plot(); protected: void focusInEvent(QFocusEvent *event) override; diff --git a/module/radio/Tool.h b/module/radio/Tool.h new file mode 100644 index 0000000..13e3bd6 --- /dev/null +++ b/module/radio/Tool.h @@ -0,0 +1,761 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace renderive { +static Time_Of_Day current_time_of_day() { + return renderive::qt_to_time_of_day(QTime::currentTime()); +} +static QColor get_color(int lowest, int highest) { + int r = QRandomGenerator::global()->bounded(lowest, highest); + int g = QRandomGenerator::global()->bounded(lowest, highest); + int b = QRandomGenerator::global()->bounded(lowest, highest); + return {r, g, b}; +} +static QString get_background_style_sheet() { + QString color = QString("background-color: %1;").arg(get_color(176, 256).name()); + return color; +} +static QString get_button_style_sheet() { + QString color = QString("background-color: %1; color: #000000;").arg(get_color(200, 256).name()); + return color; +} +template +QString get_init_value(const T& value) { + return QString::number(value); +} +template <> +inline QString get_init_value(const QString& value) { + return value; +} +template +T get_value_from_string(const QString& value) { + return value.toDouble(); +} +template <> +inline QString get_value_from_string(const QString& value) { + return value; +} +template +static QWidget* create_edit_widget_list(const QString& button_text, + const std::function&)>& click, const std::vector& init_values) { + auto container = new QWidget; + auto layout = new QHBoxLayout(container); + layout->setAlignment(Qt::AlignLeft); + layout->setContentsMargins(0, 0, 0, 0); + auto confirm = new QPushButton(button_text); + // QApplication* app = (QApplication*)QApplication::instance(); + // qDebug() << "Global StyleSheet:" << app->styleSheet(); + confirm->setStyleSheet(get_button_style_sheet()); + // 清除 QSS + QFont font; + font.setFamily("Segoe UI"); + confirm->setFont(font); + confirm->setMinimumWidth(QFontMetrics(confirm->font()).horizontalAdvance(button_text) + 8); + confirm->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + layout->addWidget(confirm); + std::vector lineEditList; + for (const T& init_value : init_values) { + QString init_value_str = get_init_value(init_value); + auto cur_edit = new QLineEdit(init_value_str); + cur_edit->setStyleSheet(get_button_style_sheet()); + // cur_edit->setMaximumWidth(50); + auto fm = QFontMetrics(QFont()); + int width = fm.horizontalAdvance(init_value_str); + // cur_edit->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + cur_edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + int w = qMax((int)((double)width * 1.4) + 16, 50); + cur_edit->setMinimumWidth(w); + lineEditList.push_back(cur_edit); + layout->addWidget(cur_edit); + } + QObject::connect(confirm, &QPushButton::clicked, [lineEditList, click]() { + std::vector values; + for (QLineEdit* line_edit : lineEditList) { + values.push_back(get_value_from_string(line_edit->text())); + } + click(values); + }); + return container; +} +template +static QWidget* create_edit_widget(const QString& button_text, + const std::function& click, const T& init_values) { + return create_edit_widget_list(button_text, [click](const std::vector& data) { + click(data.front()); + }, std::vector{init_values}); +} +static QWidget* create_range(Axis* axis, const QString& text = "更改轴范围") { + return create_edit_widget_list(text, [axis](const std::vector& values) { + axis->set_coord_range(Range{values[0], values[1]}); + }, + {axis->coord_range().origin, axis->coord_range().target}); +} +static QMenu* find_parent_menu(QWidget* widget) { + // 从当前窗口开始,逐步检查父窗口 + QWidget* parent = widget->parentWidget(); + while (parent) { + if (QMenu* menu = qobject_cast(parent)) { + return menu; // 找到第一个 QMenu 类型的父窗口 + } + parent = parent->parentWidget(); + } + return nullptr; // 如果没有找到 QMenu 类型的父窗口 +} +static QWidget* create_select_color(const QString& text, const std::function& click, const QColor& color = QColor()) { + auto ret = new QWidget; + auto l = new QHBoxLayout(ret); + l->setContentsMargins(0, 0, 0, 0); + // l->setSpacing(0); + QString bs = get_button_style_sheet(); + auto show_color = new QWidget; + show_color->setStyleSheet(QString("background-color: %1; border: 2px solid #000000;").arg(color.name(QColor::HexArgb))); + show_color->setFixedWidth(30); + static QPushButton* btn = nullptr; + // static auto dialog = new CustomColorDialog(Qt::white, QApplication::activeWindow()); + static auto dialog = new Select_Color_Dialog; + dialog->resize(800, 600); + // dialog->adjustSize(); + auto label = new QLineEdit(color.isValid() ? color.name(QColor::HexArgb) : "无效"); + label->setAlignment(Qt::AlignCenter); + label->setStyleSheet("background-color: #ffffff; color: #000000;"); + // label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + auto button = new QPushButton(text); + button->setStyleSheet(bs); + QObject::connect(button, &QPushButton::clicked, [button, label]() { + btn = button; + dialog->set_current_color(QColor(label->text())); + dialog->show(); + }); + QObject::connect(dialog, &QDialog::finished, [ret, button, click, label, show_color](int result) { + if (btn != button) + return; + if (result == QDialog::Accepted) { + QColor select_color = dialog->current_color(); + click(select_color); + label->setText(select_color.name(QColor::HexArgb)); + show_color->setStyleSheet(QString("background-color: %1; border: 2px solid #000000;") + .arg(select_color.name(QColor::HexArgb))); + } + else if (result == -1) { + click(QColor()); + label->setText("无颜色"); + show_color->setStyleSheet(QString("background-color: rgba(255, 255, 255, 0); border: 2px solid #000000;")); + } + QMenu* menu = find_parent_menu(ret); + if (menu) { + menu->show(); + } + }); + l->addWidget(button); + l->addWidget(label); + l->addWidget(show_color); + return ret; +} +static QPushButton* create_button(const QString& text, const std::function& click) { + auto button = new QPushButton(text); + button->setStyleSheet(get_button_style_sheet()); + QObject::connect(button, &QPushButton::clicked, [click]() { + click(); + }); + return button; +} +static QPushButton* create_toggle_button(const QString& text, const QString& text2, const std::function& click, bool first_state) { + auto button = new QPushButton(first_state ? text : text2); + button->setStyleSheet(get_button_style_sheet()); + QObject::connect(button, &QPushButton::clicked, [button, click, text, text2]() { + click(); + if (button->text() == text2) { + button->setText(text); + } + else { + button->setText(text2); + } + }); + return button; +} +static QLabel* create_label(const QString& text, int h = 50, const QColor& color = Qt::black) { + auto l = new QLabel(text); + QFont font; + font.setFamily("Segoe UI"); + font.setBold(true); + l->setFont(font); + l->setFixedHeight(h); + l->setAlignment(Qt::AlignHCenter | Qt::AlignBottom); + l->setStyleSheet(QString("color: %1;").arg(color.name(QColor::HexArgb))); + return l; +} +} // namespace renderive +template +static std::vector concat_widgets(const Vectors&... vectors) { + std::vector result; + result.reserve((vectors.size() + ... + 0)); + (result.insert(result.end(), vectors.begin(), vectors.end()), ...); + return result; +} +static std::vector bw(const std::vector& widgets, const QString& name) { + if (widgets.empty()) + return {}; + auto ret = new QWidget; + ret->setStyleSheet(renderive::get_background_style_sheet()); + auto l = new QVBoxLayout(ret); + auto label = new QLabel(name); + label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + QFontMetrics fm(label->font()); + label->setFixedSize(fm.horizontalAdvance(name) + 16, fm.height() + 8); + label->setStyleSheet(QString("color: %1; background-color: %2; padding: 0px; margin: 0px;") + .arg( + QColor(Qt::white).name(QColor::HexArgb), + QColor(Qt::black).name(QColor::HexArgb))); + l->addWidget(label, 0, Qt::AlignHCenter | Qt::AlignBottom); + for (QWidget* w : widgets) { + l->addWidget(w); + } + return {ret}; +} +template +static QWidget* create_line_interpolation_combo(T* renderable) { + auto container = new QWidget; + auto layout = new QHBoxLayout(container); + layout->setContentsMargins(0, 0, 0, 0); + auto label = new QLabel("线图插值"); + auto combo = new QComboBox; + label->setStyleSheet(renderive::get_button_style_sheet()); + combo->setStyleSheet(renderive::get_button_style_sheet()); + combo->addItem("Nearest_Bin", static_cast(renderive::Line_Interpolation_Mode::Nearest_Sample)); + combo->addItem("Linear_Display", static_cast(renderive::Line_Interpolation_Mode::Linear_Value)); + combo->addItem("Linear_Power", static_cast(renderive::Line_Interpolation_Mode::Linear_Power_Domain)); + combo->addItem("Step_Left", static_cast(renderive::Line_Interpolation_Mode::Step_Left)); + combo->addItem("Step_Right", static_cast(renderive::Line_Interpolation_Mode::Step_Right)); + combo->addItem("Cubic_Display", static_cast(renderive::Line_Interpolation_Mode::Cubic_Value)); + combo->setCurrentIndex(combo->findData(static_cast(renderable->interpolation_mode()))); + QObject::connect(combo, QOverload::of(&QComboBox::currentIndexChanged), [renderable, combo](int index) { + renderable->set_interpolation_mode(static_cast(combo->itemData(index).toInt())); + }); + layout->addWidget(label); + layout->addWidget(combo); + return container; +} +static QWidget* create_image_interpolation_combo(renderive::Waterfall* waterfall) { + auto container = new QWidget; + auto layout = new QHBoxLayout(container); + layout->setContentsMargins(0, 0, 0, 0); + auto label = new QLabel("二维插值"); + auto combo = new QComboBox; + label->setStyleSheet(renderive::get_button_style_sheet()); + combo->setStyleSheet(renderive::get_button_style_sheet()); + combo->addItem("Nearest", static_cast(renderive::Image_Interpolation_Mode::Nearest)); + combo->addItem("Bilinear", static_cast(renderive::Image_Interpolation_Mode::Bilinear)); + combo->addItem("Bicubic", static_cast(renderive::Image_Interpolation_Mode::Bicubic)); + combo->setCurrentIndex(combo->findData(static_cast(waterfall->interpolation_mode()))); + QObject::connect(combo, QOverload::of(&QComboBox::currentIndexChanged), [waterfall, combo](int index) { + waterfall->set_interpolation_mode(static_cast(combo->itemData(index).toInt())); + }); + layout->addWidget(label); + layout->addWidget(combo); + return container; +} +static QWidget* create_control(renderive::Abs_Plot* plot, const std::vector& widgets = {}) { + auto control = new QWidget; + auto l = new QVBoxLayout(control); + l->setAlignment(Qt::AlignTop); + l->setContentsMargins({0, 0, 0, 0}); + l->setSpacing(0); + auto* core = renderive::plot_core(plot); + std::vector ws = { + renderive::create_toggle_button("暂停渲染", "开始渲染", [plot]() { + plot->is_rendering() ? plot->pause_render() : plot->start_render(); + }, plot->is_rendering()), + renderive::create_toggle_button("停止性能测试", "启动性能测试", [plot]() { + if (auto* current_core = renderive::plot_core(plot)) + renderive::set_performance_overlay_enabled(*current_core, !renderive::performance_overlay_enabled(*current_core)); + }, core ? renderive::performance_overlay_enabled(*core) : false), + renderive::create_select_color("更改背景色", [plot](const QColor& color) { + plot->set_background_color(color); + }, plot->background_color()), + }; + if (auto latency_plot = dynamic_cast(plot)) { + ws.push_back(renderive::create_edit_widget_list("最大渲染FPS", [latency_plot](std::vector data) { + latency_plot->set_max_render_fps(data[0]); + }, {latency_plot->max_render_fps()})); + } + for (QWidget* cur : concat_widgets(bw(ws, "plot基础"), widgets)) { + l->addWidget(cur); + } + return control; +} +static std::vector cw(renderive::Abs_Axis* it) { + if (it == nullptr) + return {}; + auto t = std::vector{ + renderive::create_button("反转轴整体方向", [it]() { + it->set_orientation(it->orientation() == renderive::Orientation::Horizontal ? renderive::Orientation::Vertical : renderive::Orientation::Horizontal); + }), + renderive::create_edit_widget_list("主刻度值", [it](const std::vector& values) { + it->set_tick_length(values[0]); + }, + {it->tick_length()}), + renderive::create_edit_widget_list("子刻度值", [it](const std::vector& values) { + it->set_sub_tick_length(values[0]); + }, + {it->sub_tick_length()}), + renderive::create_select_color("更改轴颜色", [it](const QColor& color) { + it->set_color(renderive::qt_to_color(color)); + }, renderive::to_qcolor(it->color())), + renderive::create_edit_widget_list("设置单位", [it](const std::vector& values) { + it->set_unit_text(renderive::qt_to_string(values[0])); + }, {renderive::to_qstring(it->unit_text())}), + renderive::create_select_color("更改UnitText颜色", [it](const QColor& color) { + it->set_unit_text_pen(renderive::qt_to_pen(color)); + }, renderive::to_qcolor(it->unit_text_pen().color)), + renderive::create_select_color("更改UnitText背景色", [it](const QColor& color) { + it->set_unit_text_background_brush(renderive::qt_to_brush(color)); + }, renderive::to_qcolor(it->unit_text_background_brush().color)), + renderive::create_edit_widget_list("更改刻度斜度", [it](const std::vector& values) { + it->set_label_rotation_degrees(values[0]); + }, {it->label_rotation_degrees()}), + }; + return t; +} +static std::vector cw(renderive::Axis* it) { + if (it == nullptr) + return {}; + auto t = std::vector{ + renderive::create_range(it), + }; + return concat_widgets(cw(dynamic_cast(it)), t); +} +static std::vector cw(renderive::Frequency_Axis* it) { + if (it == nullptr) + return {}; + auto t = std::vector{}; + return concat_widgets(cw(dynamic_cast(it)), t); +} +static std::vector cw(renderive::Time_Axis* it, int num_pre_second = -1) { + if (it == nullptr) + return {}; + auto t = std::vector{ + renderive::create_edit_widget_list("时间格式", [it](std::vector data) { + it->set_time_format(renderive::qt_to_string(data[0])); + }, + {renderive::to_qstring(it->time_format())}), + renderive::create_edit_widget_list("单位间隔pixel", [it](std::vector data) { + it->set_tick_label_spacing_px(data[0]); + }, + {it->tick_label_spacing_px()}), + }; + auto timer = new QTimer(QApplication::instance()); + if (num_pre_second > 0) + timer->start(static_cast(1000.0 / static_cast(num_pre_second))); + QObject::connect(timer, &QTimer::timeout, [it]() { + it->append_time(renderive::current_time_of_day()); + }); + t.push_back(renderive::create_edit_widget_list("推数据Timer(次/s)", [timer](std::vector data) { + if (data[0] < 0) { + timer->stop(); + } + else { + timer->start((int)(1000.0 / data[0])); + } + }, + {timer->interval() > 0 ? 1000.0 / timer->interval() : -1})); + std::vector axis_widgets = cw(dynamic_cast(it)); + t.insert(t.end(), axis_widgets.begin(), axis_widgets.end()); + return t; +} +static std::vector cw(renderive::Selection_Rectangle_Overlay* it) { + if (it == nullptr) + return {}; + auto t = std::vector{ + renderive::create_select_color("更改填充色", [it](const QColor& color) { + it->set_selection_brush(renderive::qt_to_brush(color)); + }, renderive::to_qcolor(it->selection_brush().color)), + renderive::create_select_color("更改边框色", [it](const QColor& color) { + qDebug() << " color.isValid() == " << color.isValid(); + auto pen = renderive::qt_to_pen(color); + pen.style = renderive::Line_Style::Dash; + it->set_selection_border_pen(pen); + qDebug() << " color.isValid() == " << renderive::to_qcolor(pen.color).isValid(); + }, renderive::to_qcolor(it->selection_border_pen().color)), + renderive::create_select_color("更改字色", [it](const QColor& color) { + it->set_label_pen(renderive::qt_to_pen(color)); + }, renderive::to_qcolor(it->label_pen().color)) + }; + return t; +} +template +static std::vector cw(renderive::Hover_Info_Renderable* it) { + if (it == nullptr) + return {}; + auto t = std::vector{ + renderive::create_label("悬浮信息"), + renderive::create_toggle_button("启动悬浮信息", "停止悬浮信息", [it]() { + it->set_use_hover_info(!it->hover_tooltip_enabled()); + }, !it->hover_tooltip_enabled()), + renderive::create_select_color("设置文字颜色", [it](const QColor& c) { + it->set_tooltip_text_pen(renderive::qt_to_pen(c)); + }, renderive::to_qcolor(it->tooltip_text_pen().color)), + renderive::create_select_color("设置背景颜色", [it](const QColor& c) { + it->set_hover_tooltip_background_brush(renderive::qt_to_brush(c)); + }, renderive::to_qcolor(it->hover_info_background_brush().color)) + }; + return t; +} +static std::vector cw(renderive::Waterfall* it, int num_pre_second = -1) { + if (it == nullptr) + return {}; + auto timer = new QTimer(QApplication::instance()); + if (num_pre_second > 0) + timer->start(static_cast(1000.0 / static_cast(num_pre_second))); + QObject::connect(timer, &QTimer::timeout, [it]() { + std::vector d = renderive::get_data(it->power_range(), it->frequency_bin_count()); + it->append_row(renderive::current_time_of_day(), d); + }); + auto t = std::vector{ + renderive::create_toggle_button("关闭可见区裁剪", "开启可见区裁剪", [it]() { + it->set_visible_range_only(!it->visible_range_only()); + }, it->visible_range_only()), + create_image_interpolation_combo(it), + renderive::create_edit_widget_list("推数据Timer(次/s)", [timer](std::vector data) { + if (data[0] < 0) { + timer->stop(); + } + else { + timer->start((int)(1000.0 / data[0])); + } + }, {timer->interval() > 0 ? 1000.0 / timer->interval() : -1}), + }; + std::vector hover_widgets = cw(static_cast*>(it)); + t.insert(t.end(), hover_widgets.begin(), hover_widgets.end()); + return t; +} +static std::vector cw(renderive::Frequency_Trace* it, int num_pre_second = -1) { + if (it == nullptr) + return {}; + auto timer = new QTimer(QApplication::instance()); + if (num_pre_second > 0) + timer->start(static_cast(1000.0 / static_cast(num_pre_second))); + QObject::connect(timer, &QTimer::timeout, [it]() { + it->append_sample(renderive::current_time_of_day(), renderive::get_data({0, 20})); + }); + auto t = std::vector{ + renderive::create_edit_widget_list("推数据Timer(次/s)", [timer](std::vector data) { + if (data[0] < 0) { + timer->stop(); + } + else { + timer->start((int)(1000.0 / data[0])); + } + }, + {timer->interval() > 0 ? 1000.0 / timer->interval() : -1}), + }; + return t; +} +static std::vector cw(renderive::Constellation_Diagram* it, int num_pre_second = -1) { + if (it == nullptr) + return {}; + auto timer = new QTimer(QApplication::instance()); + QObject::connect(timer, &QTimer::timeout, [it]() { + for (int i = 0; i < 10; ++i) { + double x = renderive::get_data(it->i_range()); + double y = renderive::get_data(it->q_range()); + it->append_point({x, y}); + } + }); + if (num_pre_second > 0) + timer->start(static_cast(1000.0 / static_cast(num_pre_second))); + auto t = std::vector{ + renderive::create_edit_widget_list("推数据Timer(次/s)", [timer](std::vector data) { + if (data[0] < 0) { + timer->stop(); + } + else { + timer->start((int)(1000.0 / data[0])); + } + }, + {timer->interval() > 0 ? 1000.0 / timer->interval() : -1}), + renderive::create_edit_widget_list("设置持续时间(ms)", [it](std::vector data) { + it->set_point_lifetime_ms(data[0]); + }, + {it->point_lifetime_ms()}), + renderive::create_select_color("更改IQ点颜色", [it](const QColor& color) { + it->set_point_color(renderive::qt_to_color(color)); + }, renderive::to_qcolor(it->point_color())), + renderive::create_select_color("更改锚点颜色", [it](const QColor& color) { + it->set_anchor_color(renderive::qt_to_color(color)); + }, renderive::to_qcolor(it->anchor_color())), + renderive::create_edit_widget_list("I范围", [it](std::vector data) { + it->set_i_range({data[0], data[1]}); + }, {it->i_range().origin, it->i_range().target}), + renderive::create_edit_widget_list("Q范围", [it](std::vector data) { + it->set_q_range({data[0], data[1]}); + }, {it->q_range().origin, it->q_range().target}), + renderive::create_button("设置到轴中心", [it]() { + it->fit_square_to_axes(); + }), + }; + return t; +} +static std::vector cw(renderive::Afterglow* it, int num_pre_second = -1) { + if (it == nullptr) + return {}; + static auto create_base_data = [it]() { + renderive::Range r = it->power_range(); + std::vector ret(it->frequency_point_size()); + ret[0] = get_data(r); + for (int i = 1; i < it->frequency_point_size(); ++i) { + double rate; + if (i % 20 == 0) { + double that = qAbs(ret[i - 1] - r.origin) / r.size() - 0.5; + rate = (1.0 - that) * renderive::get_data({0.8, 1.2}); + } + else { + rate = renderive::get_data({0.8, 1.2}); + } + ret[i] = std::clamp(ret[i - 1] * rate, r.origin, r.target); + } + return ret; + }; + static std::vector base_data = create_base_data(); + auto timer = new QTimer(QApplication::instance()); + QObject::connect(timer, &QTimer::timeout, [it]() { + renderive::Range r = it->power_range(); + int n = base_data.size(); + std::vector cur_data(n); + for (int i = 0; i < n; ++i) { + double rate = renderive::get_data({0.8, 1.2}); + cur_data[i] = std::clamp(base_data[i] * rate, r.origin, r.target); + } + it->append_spectrum(cur_data); + }); + if (num_pre_second > 0) + timer->start(static_cast(1000.0 / static_cast(num_pre_second))); + auto t = std::vector{ + renderive::create_edit_widget_list("推数据Timer(次/s)", [timer](std::vector data) { + if (data[0] < 0) { + timer->stop(); + } + else { + timer->start((int)(1000.0 / data[0])); + } + }, + {timer->interval() > 0 ? 1000.0 / timer->interval() : -1}), + renderive::create_edit_widget_list("频率范围", [it](std::vector data) { + it->set_frequency_range({data[0], data[1]}); + }, + {it->frequency_range().origin, it->frequency_range().target}), + renderive::create_edit_widget_list("功率概率范围", [it](std::vector data) { + it->set_power_range({data[0], data[1]}); + }, + {it->power_range().origin, it->power_range().target}), + renderive::create_button("更改基础线", []() { + base_data = create_base_data(); + }), + }; + return t; +} +static std::vector cw(renderive::Spectrum* it, int num_pre_second = -1) { + if (it == nullptr) + return {}; + auto timer = new QTimer(QApplication::instance()); + if (num_pre_second > 0) + timer->start(static_cast(1000.0 / static_cast(num_pre_second))); + QObject::connect(timer, &QTimer::timeout, [it]() { + it->update_samples(renderive::get_data(it->power_axis()->coord_range(), it->frequency_point_size())); + }); + auto t = std::vector{ + renderive::create_toggle_button("关闭可见区裁剪", "开启可见区裁剪", [it]() { + it->set_visible_range_only(!it->visible_range_only()); + }, it->visible_range_only()), + create_line_interpolation_combo(it), + renderive::create_edit_widget_list("推数据Timer(次/s)", [timer](std::vector data) { + if (data[0] < 0) { + timer->stop(); + } + else { + timer->start((int)(1000.0 / data[0])); + } + }, {timer->interval() > 0 ? 1000.0 / timer->interval() : -1}), + renderive::create_edit_widget_list("频率范围", [it](std::vector data) { + it->set_frequency_range({data[0], data[1]}); + }, {it->frequency_range().origin, it->frequency_range().target}), + renderive::create_edit_widget_list("设置频率点数", [it](std::vector data) { + it->set_frequency_point_size(data[0]); + }, {it->frequency_point_size()}), + renderive::create_label("sweepRect"), + renderive::create_toggle_button("停止sweepRect", "启动sweepRect", [it]() { + it->set_sweep_region_visible(!it->sweep_region_visible()); + }, it->sweep_region_visible()), + renderive::create_edit_widget_list("sweepRect 范围", [it](std::vector data) { + if (!it->sweep_region_visible()) it->set_sweep_region_visible(true); + it->set_sweep_frequency_range({data[0], data[1]}); + }, {it->sweep_frequency_range().origin, it->sweep_frequency_range().target}), + renderive::create_edit_widget_list("中频", [it](std::vector data) { + if (!it->sweep_region_visible()) it->set_sweep_region_visible(true); + it->set_center_frequency(data[0]); + }, {it->center_frequency()}), + renderive::create_select_color("扫频矩形", [it](const QColor& c) { + it->set_sweep_region_brush(renderive::qt_to_brush(c)); + }), + renderive::create_select_color("中频", [it](const QColor& c) { + if (!c.isValid()) { + it->set_middle_frequency_pen(renderive::Pen{.style = renderive::Line_Style::None}); + return; + } + it->set_middle_frequency_pen(renderive::qt_to_pen(c)); + }, renderive::to_qcolor(it->middle_frequency_pen().color)), + renderive::create_label("marker"), + renderive::create_toggle_button("停止最大值marker", "启动最大值marker", [it]() { + it->set_max_marker_visible(!it->max_marker_visible()); + }, it->max_marker_visible()), + renderive::create_toggle_button("停止最小值marker", "启动最小值marker", [it]() { + it->set_use_min_marker(!it->use_min_marker()); + }, it->use_min_marker()), + renderive::create_edit_widget_list("添加自定义marker", [it](std::vector data) { + it->add_custom_marker(data[0]); + }, {0}), + renderive::create_edit_widget_list("添加自定义Linemarker", [it](std::vector data) { + it->add_custom_line_marker(data[0]); + }, {0}), + renderive::create_edit_widget_list("删除marker", [it](std::vector data) { + it->remove_custom_marker(data[0]); + }, {0}), + renderive::create_edit_widget_list("清楚所有marker", [it](std::vector data) { + it->clear_custom_markers(); + }, {}), + renderive::create_edit_widget_list("选择当前marker", [it](std::vector data) { + it->set_selected_marker_index(data[0]); + }, {0}), + renderive::create_edit_widget_list("选择下一个marker", [it](std::vector data) { + it->select_next_marker(); + }, {}), + renderive::create_edit_widget_list("选择上一个marker", [it](std::vector data) { + it->select_previous_marker(); + }, {}), + renderive::create_label("当前线"), + renderive::create_select_color("当前线色", [it](const QColor& c) { + if (!c.isValid()) { + it->set_current_pen(renderive::Pen{.style = renderive::Line_Style::None}); + return; + } + it->set_current_pen(renderive::qt_to_pen(c)); + }, renderive::to_qcolor(it->current_pen().color)), + renderive::create_select_color("当前线填充色", [it](const QColor& c) { + it->set_current_brush(renderive::qt_to_brush(c)); + }, renderive::to_qcolor(it->current_brush().color)), + renderive::create_label("最大值线"), + renderive::create_toggle_button("停止最大值线", "启动最大值线", [it]() { + it->set_max_hold_visible(!it->max_hold_visible()); + }, it->max_hold_visible()), + renderive::create_select_color("最大值线色", [it](const QColor& c) { + if (!c.isValid()) { + it->set_max_pen(renderive::Pen{.style = renderive::Line_Style::None}); + return; + } + it->set_max_pen(renderive::qt_to_pen(c)); + }, renderive::to_qcolor(it->max_pen().color)), + renderive::create_select_color("最大值线填充色", [it](const QColor& c) { + it->set_max_brush(renderive::qt_to_brush(c)); + }, renderive::to_qcolor(it->max_brush().color)), + renderive::create_label("最小值线"), + renderive::create_toggle_button("停止最小值线", "启动最小值线", [it]() { + it->set_min_hold_visible(!it->min_hold_visible()); + }, it->min_hold_visible()), + renderive::create_select_color("最小值线色", [it](const QColor& c) { + it->set_min_pen(renderive::qt_to_pen(c)); + }, renderive::to_qcolor(it->min_pen().color)), + renderive::create_select_color("最小值线填充色", [it](const QColor& c) { + it->set_min_brush(renderive::qt_to_brush(c)); + }, renderive::to_qcolor(it->min_brush().color)), + }; + return concat_widgets(cw(static_cast*>(it)), t); +} +static std::vector cw(renderive::Sweep_Spectrum* it, int num_pre_second = -1) { + if (it == nullptr) + return {}; + auto timer = new QTimer(QApplication::instance()); + if (num_pre_second > 0) + timer->start(static_cast(1000.0 / static_cast(num_pre_second))); + QObject::connect(timer, &QTimer::timeout, [it]() { + it->append_block(renderive::get_data(it->power_axis()->coord_range(), it->bins_per_block())); + }); + auto t = std::vector{ + renderive::create_toggle_button("关闭可见区裁剪", "开启可见区裁剪", [it]() { + it->set_visible_range_only(!it->visible_range_only()); + }, it->visible_range_only()), + create_line_interpolation_combo(it), renderive::create_edit_widget_list("推数据Timer(次/s)", [timer](std::vector data) { + if (data[0] < 0) { + timer->stop(); + } + else { + timer->start((int)(1000.0 / data[0])); + } + }, {timer->interval() > 0 ? 1000.0 / timer->interval() : -1}), + renderive::create_select_color("线颜色", [it](const QColor& color) { + it->set_pen(renderive::qt_to_pen(color)); + }, renderive::to_qcolor(it->pen().color)), + renderive::create_select_color("扫频线颜色", [it](const QColor& color) { + auto p = it->cur_frequency_pen(); + p.color = renderive::qt_to_color(color); + it->set_cur_frequency_pen(p); + }, renderive::to_qcolor(it->cur_frequency_pen().color)), + renderive::create_edit_widget_list("频率范围", [it](const std::vector& data) { + it->set_frequency_range({data[0], data[1]}); + }, {it->frequency_range().origin, it->frequency_range().target}) + }; + return t; +} +static QMenu* create_menu(renderive::Abs_Plot* plot, const std::vector& widgets) { + auto menu = new QMenu(plot); + menu->setObjectName("memu"); + // menu->setStyle(nullptr); + menu->hide(); + menu->setContentsMargins(0, 0, 0, 0); + auto container = create_control(plot, widgets); + auto scroll_area = new QScrollArea; + scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scroll_area->setContentsMargins(0, 0, 0, 0); + scroll_area->setWidget(container); + scroll_area->setWidgetResizable(true); + scroll_area->setObjectName("scroll_area"); + auto scrollAction = new QWidgetAction(menu); + scrollAction->setDefaultWidget(scroll_area); + menu->addAction(scrollAction); + return menu; +} +static QMenu* create_menu_normal(QWidget* w, const std::vector& widgets) { + auto menu = new QMenu(w); + menu->setObjectName("memu_normal"); + // menu->setStyle(nullptr); + menu->hide(); + menu->setContentsMargins(0, 0, 0, 0); + auto container = new QWidget; + auto l = new QVBoxLayout(container); + l->setAlignment(Qt::AlignTop); + l->setContentsMargins({0, 0, 0, 0}); + l->setSpacing(4); + for (auto widget : widgets) { + l->addWidget(widget); + } + auto scroll_area = new QScrollArea; + scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scroll_area->setContentsMargins(0, 0, 0, 0); + scroll_area->setWidget(container); + scroll_area->setWidgetResizable(true); + scroll_area->setObjectName("scrollArea2"); + auto scrollAction = new QWidgetAction(menu); + scrollAction->setDefaultWidget(scroll_area); + menu->addAction(scrollAction); + return menu; +}