#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 = plot ? plot->core() : nullptr; const auto overlay = core ? core->performance_overlay() : nullptr; std::vector ws = { renderive::create_toggle_button("停止性能测试", "启动性能测试", [plot]() { if (auto* current_core = plot ? plot->core() : nullptr) { const auto current_overlay = current_core->performance_overlay(); renderive::set_performance_overlay_enabled( *current_core, !(current_overlay && current_overlay->enabled())); } }, overlay && overlay->enabled()), renderive::create_select_color("更改背景色", [plot](const QColor& color) { plot->set_background_color(color); }, plot->background_color()), }; if (auto latency_plot = dynamic_cast(plot)) { ws.insert(ws.begin(), renderive::create_toggle_button("暂停渲染", "开始渲染", [latency_plot]() { latency_plot->running() ? latency_plot->pause() : latency_plot->start(); }, latency_plot->running())); 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_Tooltip_Mixin* 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; }