From 84c4082e82988d071176dc56cb07efd8ce699b8d Mon Sep 17 00:00:00 2001 From: wyc <1104749580@qq.com> Date: Wed, 29 Jul 2026 18:08:57 +0800 Subject: [PATCH] =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E5=86=85=E5=AD=98?= =?UTF-8?q?=E5=88=86=E9=85=8D=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + module/radio/Application.h | 1 - module/radio/BackEnd/BackEnd.h | 16 +- module/radio/BackEnd/BackEnd_Mock.cpp | 159 ++++++++++++------ module/radio/BackEnd/BackEnd_True.cpp | 8 +- .../BackEnd/IntermediateFrequencyWidget.cpp | 27 +-- module/radio/BackEnd/RadioWidget.cpp | 84 ++++++--- module/radio/BackEnd/SweepFrequencyWidget.cpp | 11 +- module/radio/Global.cpp | 6 +- module/radio/Global.h | 8 +- .../Toolbox_private/CircularLinkedList.hpp | 12 +- module/radio/Toolbox_private/Node.hpp | 65 +++---- module/radio/Toolbox_private/RollObject.h | 19 ++- .../Toolbox_private/view/FileFolderBar.cpp | 10 +- module/radio/component/ProgressBar.cpp | 54 +++--- module/radio/component/ProgressBar.h | 13 +- module/radio/menu/BaseWidgetMenu.cpp | 8 +- module/radio/menu/BaseWidgetMenu.h | 10 +- 18 files changed, 325 insertions(+), 188 deletions(-) diff --git a/.gitignore b/.gitignore index ad810a2..94a8e3d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /.idea /third_party/Graphic_Core/Renderive.zip +/cmake-build-vs2019_asan/ +/clion_none_git_dir/ diff --git a/module/radio/Application.h b/module/radio/Application.h index 968572b..ac24b68 100644 --- a/module/radio/Application.h +++ b/module/radio/Application.h @@ -1,7 +1,6 @@ #ifndef Application_H #define Application_H #include -#include class Main_Widget; class Application : public QApplication { public: diff --git a/module/radio/BackEnd/BackEnd.h b/module/radio/BackEnd/BackEnd.h index 66aaf0f..e5b5cf9 100644 --- a/module/radio/BackEnd/BackEnd.h +++ b/module/radio/BackEnd/BackEnd.h @@ -4,11 +4,13 @@ #include #include #include +#include +#include class Back_End : public QObject { Q_OBJECT public: - QMap function_map; + std::map function_map; bool match(QKeyEvent* e, const QString& function); static Back_End* instance(); int YsGetAfGain(); @@ -22,12 +24,22 @@ public: QString get_screenshot_save_dir_path(); QString get_screenshot_save_file_name(); QString get_audio_file_location(); + void stop_mock_thread() { + if (mock_thread) { + mock_thread->quit(); + mock_thread->wait(); + mock_thread = nullptr; + } + } Back_End(const Back_End&) = delete; Back_End& operator=(const Back_End&) = delete; void call_back_data_func(int channel, void *pData, int i_length); protected: Back_End(); - ~Back_End() override = default; + ~Back_End() override { + stop_mock_thread(); + } + QThread* mock_thread{}; }; #endif diff --git a/module/radio/BackEnd/BackEnd_Mock.cpp b/module/radio/BackEnd/BackEnd_Mock.cpp index b1c5ed2..478cf76 100644 --- a/module/radio/BackEnd/BackEnd_Mock.cpp +++ b/module/radio/BackEnd/BackEnd_Mock.cpp @@ -6,6 +6,93 @@ #include "IntermediateFrequencyWidget.h" #include "RadioWidget.h" #include "SweepFrequencyWidget.h" +#include +#include +#include +#include +#include "../../../third_party/Renderive/Renderive/Generate_Mock_Data.h" +#include "../../../third_party/Renderive/Renderive/base/Memory.h" +namespace { +struct Mock_Config { + bool performance{}; + int interval_ms = 10; + int batch_count = 1; +}; +int read_env_int(const char* name, int fallback) { + bool ok = false; + int value = qEnvironmentVariableIntValue(name, &ok); + return ok ? value : fallback; +} +Mock_Config read_mock_config() { + Mock_Config config; + config.performance = read_env_int("RADIO_MOCK_PERF_MODE", 1) != 0; + config.interval_ms = std::max(1, read_env_int("RADIO_MOCK_INTERVAL_MS", config.performance ? 1 : 10)); + config.batch_count = std::max(1, read_env_int("RADIO_MOCK_BATCH_COUNT", config.performance ? 4 : 1)); + return config; +} +std::pmr::vector make_random_data(renderive::Range range, int size, renderive::Memory_Domain domain) { + if (range.origin > range.target) + std::swap(range.origin, range.target); + std::pmr::vector data(renderive::memory_resource(domain)); + data.resize(size); + renderive::fill_data(range, data); + return data; +} +double make_random_value(renderive::Range range) { + if (range.origin > range.target) + std::swap(range.origin, range.target); + return renderive::get_data(range); +} +void push_radio_data(Radio_Widget* rw) { + if (!rw || !rw->spectrogram_line || !rw->water_fall || !rw->time_power || !rw->audio_spectrogram_plot || !rw->progress_bar1 || !rw->progress_bar2) + return; + { + auto r = rw->spectrogram_line->power_axis()->coord_range(); + 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.center() : data[data.size() / 2]; + rw->spectrogram_line->give_data(std::move(data)); + rw->progress_bar1->setValue(middle_power); + } + { + rw->water_fall->give_data(QTime::currentTime(), make_random_data(rw->water_fall->power_range(), rw->water_fall->frequency_point_size(), renderive::Memory_Domain::Waterfall)); + } + { + int tick = rw->time_power->time_axis()->give_data(QTime::currentTime()); + renderive::Range r = rw->time_power->value_axis()->coord_range(); + renderive::Range nr = {r.center() - r.length() / 4, r.center() + r.length() / 4}; + rw->time_power->give_data(tick, make_random_value(nr)); + } + { + auto r = rw->audio_spectrogram_plot->power_axis()->coord_range(); + renderive::Range nr = {r.center() - r.length() / 4, r.center() + r.length() / 4}; + rw->audio_spectrogram_plot->give_data(make_random_data(nr, rw->audio_spectrogram_plot->frequency_point_size(), renderive::Memory_Domain::Spectrum)); + } + rw->progress_bar2->setValue(make_random_value({1, 5})); +} +void push_radio_data_perf(Radio_Widget* rw) { + if (!rw || !rw->spectrogram_line || !rw->water_fall || !rw->time_power || !rw->audio_spectrogram_plot || !rw->progress_bar1 || !rw->progress_bar2) + return; + { + renderive::Range nr = {40, 120}; + auto data = make_random_data(nr, 1024, renderive::Memory_Domain::Spectrum); + double middle_power = data.empty() ? nr.center() : data[data.size() / 2]; + rw->spectrogram_line->give_data(std::move(data)); + rw->progress_bar1->setValue(middle_power); + } + { + rw->water_fall->give_data(QTime::currentTime(), make_random_data({0, 160}, 1024, renderive::Memory_Domain::Waterfall)); + } + { + int tick = rw->time_power->time_axis()->give_data(QTime::currentTime()); + rw->time_power->give_data(tick, make_random_value({-6000, 6000})); + } + { + rw->audio_spectrogram_plot->give_data(make_random_data({-6000, 6000}, 512, renderive::Memory_Domain::Spectrum)); + } + rw->progress_bar2->setValue(make_random_value({1, 5})); +} +} void Back_End::play(const QString& fileName) { qDebug() << "播放音频文件:" << fileName; } @@ -67,55 +154,33 @@ Back_End::Back_End() { function_map["切换音量/RF Gain"] = Qt::Key_Return; function_map["特别增加"] = Qt::Key_PageUp; function_map["特别减小"] = Qt::Key_PageDown; - auto timer = new QTimer(this); - QObject::connect(timer, &QTimer::timeout, [&]() { - int size = 1024; + Mock_Config config = read_mock_config(); + QTimer::singleShot(0, this, [this, config]() { Radio_Widget* rw = Main_Widget::instance()->radio_widget; - { - auto r = rw->spectrogram_line->power_axis()->coord_range(); - renderive::Range nr = {r.center() - r.length() / 4, r.center() + r.length() / 4}; - //QVector&& d= renderive::get_data(nr, rw->spectrogram_line->frequent_point_size()); - QVector&& d = renderive::get_data(nr, size); - rw->spectrogram_line->give_data(d); - } - { - QVector&& d = renderive::get_data(rw->water_fall->power_range(), rw->water_fall->frequency_point_size()); - //qDebug() << "D == " << d.size(); - int tick = rw->water_fall->time_axis()->give_data(QTime::currentTime()); - rw->water_fall->give_data(tick, d); - } - { - int tick = rw->time_power->time_axis()->give_data(QTime::currentTime()); - renderive::Range r = rw->time_power->value_axis()->coord_range(); - renderive::Range nr = {r.center() - r.length() / 4, r.center() + r.length() / 4}; - rw->time_power->give_data(tick, renderive::get_data(nr)); - } - { - auto r = rw->audio_spectrogram_plot->power_axis()->coord_range(); - renderive::Range nr = {r.center() - r.length() / 4, r.center() + r.length() / 4}; - //QVector&& d= renderive::get_data(nr, rw->audio_spectrogram_plot->frequent_point_size()); - QVector&& d = renderive::get_data(nr, 512); - rw->audio_spectrogram_plot->give_data(d); - } - auto iw = Main_Widget::instance()->intermediate_frequency_widget; - { - auto r = iw->spectrogram_line->power_axis()->coord_range(); - renderive::Range nr = {r.center() - r.length() / 4, r.center() + r.length() / 4}; - //QVector d = renderive::get_data(nr, iw->spectrogram_line->frequent_point_size()); - QVector d = renderive::get_data(nr, size); - iw->spectrogram_line->give_data(d); - } - { - //QVector d= renderive::get_data(iw->afterglow->power_range(), iw->afterglow->frequent_point_size()); - QVector d = renderive::get_data(iw->afterglow->power_range(), size); - iw->afterglow->give_data(d); - } - auto sw = Main_Widget::instance()->sweep_frequency_widget; - { - QVector&& sweepData = renderive::get_data(sw->sweep_frequency_line->power_axis()->coord_range(), sw->sweep_frequency_line->block_frequency_point_size()); - sw->sweep_frequency_line->give_data(sweepData); + if (config.performance) { + mock_thread = new QThread(this); + auto worker = new QObject; + worker->moveToThread(mock_thread); + QObject::connect(mock_thread, &QThread::finished, worker, &QObject::deleteLater); + QObject::connect(mock_thread, &QThread::started, worker, [worker, config, rw]() { + auto timer = new QTimer(worker); + timer->setTimerType(Qt::PreciseTimer); + QObject::connect(timer, &QTimer::timeout, worker, [config, rw]() { + for (int i = 0; i < config.batch_count; ++i) + push_radio_data_perf(rw); + }); + timer->start(config.interval_ms); + }); + mock_thread->start(); + return; } + auto timer = new QTimer(this); + timer->setTimerType(Qt::PreciseTimer); + QObject::connect(timer, &QTimer::timeout, this, [config, rw]() { + for (int i = 0; i < config.batch_count; ++i) + push_radio_data(rw); + }); + timer->start(config.interval_ms); }); - timer->start(10); } #endif diff --git a/module/radio/BackEnd/BackEnd_True.cpp b/module/radio/BackEnd/BackEnd_True.cpp index a3978be..b400645 100644 --- a/module/radio/BackEnd/BackEnd_True.cpp +++ b/module/radio/BackEnd/BackEnd_True.cpp @@ -12,10 +12,10 @@ #include // 用于音频文件写入 #include // 用于音频播放 -#include // Qt 的 QVector #include #include #include +#include #define BUFFER_SIZE 512 // 缓冲区大小 Device_UHD* ys_radio; @@ -105,7 +105,7 @@ void Back_End::call_back_data_func(int channel, void *pData, int i_length) // qDebug()<<"收到数据包大小"<DataLen; //绘图用 if(pUHDData->DataType == UHD_Enum_DataType::kd_fft ) { - QVector data; + std::vector data; data.clear(); for(int i = 0; i < 1024; i++) { @@ -146,7 +146,7 @@ void Back_End::call_back_data_func(int channel, void *pData, int i_length) //Main_Widget::instance()->radio_widget->giv - QVector data(512); + std::vector data(512); for(int i = 0; i < 512; ++i){ data[i] = rbuf[i]; } @@ -334,4 +334,4 @@ QString Back_End::get_screenshot_save_dir_path() { } -#endif \ No newline at end of file +#endif diff --git a/module/radio/BackEnd/IntermediateFrequencyWidget.cpp b/module/radio/BackEnd/IntermediateFrequencyWidget.cpp index bd9e701..182a82a 100644 --- a/module/radio/BackEnd/IntermediateFrequencyWidget.cpp +++ b/module/radio/BackEnd/IntermediateFrequencyWidget.cpp @@ -1,7 +1,6 @@ #include "IntermediateFrequencyWidget.h" #include #include -#include #include #include #include "../component/FrequentShower.h" @@ -57,11 +56,11 @@ QWidget* Intermediate_Frequency_Widget::create_spectrogram_power_plot() { } void contextMenuEvent(QContextMenuEvent* event) override { if (!menu) { - auto ws = - bw(cw(sp.get(), -1), "频谱图") + - bw(cw(x_axis.get()), "频率x轴") + - bw(cw(y_axis.get()), "功率y轴") + - bw(cw(msr.get()), "多选框"); + 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()); @@ -72,8 +71,10 @@ QWidget* Intermediate_Frequency_Widget::create_spectrogram_power_plot() { spectrogram_line = w->sp; progress_bar1->set_value = [this]() { double middle_frequent = this->spectrogram_line->frequency_range().center(); - bool ok; - this->progress_bar1->value = spectrogram_line->get_power(middle_frequent, ok, renderive::SRC::Edit); + bool ok = false; + double power = spectrogram_line->get_power(middle_frequent, ok, renderive::SRC::Render); + if (ok) + this->progress_bar1->value = power; }; return w; } @@ -120,11 +121,11 @@ QWidget* Intermediate_Frequency_Widget::create_Afterglow_Plot() { } void contextMenuEvent(QContextMenuEvent* event) override { if (!menu) { - auto ws = - bw(cw(ag.get(), -1), "余辉图") + - bw(cw(x_axis.get()), "频率轴") + - bw(cw(y_axis.get()), "功率概率轴") + - bw(cw(msr.get()), "多选框"); + 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()); diff --git a/module/radio/BackEnd/RadioWidget.cpp b/module/radio/BackEnd/RadioWidget.cpp index 8a63d19..ae3e34f 100644 --- a/module/radio/BackEnd/RadioWidget.cpp +++ b/module/radio/BackEnd/RadioWidget.cpp @@ -1,7 +1,7 @@ #include "RadioWidget.h" #include #include -#include +#include #include "../component/FrequentShower.h" #include "../component/ProgressBar.h" #include "../Global.h" @@ -12,6 +12,24 @@ static bool use_Performance_shower = false; static double max = 160; static renderive::Range frequent_range = {-12000, 12000}; +static bool radio_mock_perf_mode() { + bool ok = false; + int value = qEnvironmentVariableIntValue("RADIO_MOCK_PERF_MODE", &ok); + return ok ? value != 0 : true; +} +static bool radio_show_performance_overlay() { + bool ok = false; + int value = qEnvironmentVariableIntValue("RADIO_SHOW_PERFORMANCE_OVERLAY", &ok); + return ok ? value != 0 : false; +} +static void configure_radio_plot_perf(renderive::Plot* plot) { + if (!radio_mock_perf_mode()) + return; + plot->set_render_check_fps(1000); + plot->set_render_schedule_mode(renderive::Plot_Render_Schedule_Mode::Chase_Latest); + if (radio_show_performance_overlay()) + plot->set_use_performance_shower(true); +} QWidget* Radio_Widget::create_spectrogram_power_plot() { class Spectrum_Plot : public renderive::Plot { public: @@ -22,6 +40,7 @@ QWidget* Radio_Widget::create_spectrogram_power_plot() { QMenu* menu{}; void init() override { Plot::init(); + configure_radio_plot_perf(this); object_name = "Spectrum_Plot"; auto data = create_renderable_node(get_root_renderable(), "Data_Renderable"); auto axis = create_renderable_node(get_root_renderable(), "Axis_Renderable"); @@ -52,11 +71,11 @@ QWidget* Radio_Widget::create_spectrogram_power_plot() { } void contextMenuEvent(QContextMenuEvent* event) override { if (!menu) { - auto ws = - bw(cw(sp.get(), -1), "频谱图") + - bw(cw(x_axis.get()), "频率x轴") + - bw(cw(y_axis.get()), "功率y轴") + - bw(cw(msr.get()), "多选框"); + 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()); @@ -65,11 +84,15 @@ QWidget* Radio_Widget::create_spectrogram_power_plot() { 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; - this->progress_bar1->value = spectrogram_line->get_power(middle_frequent, ok, renderive::SRC::Edit); - }; + if (!radio_mock_perf_mode()) { + progress_bar1->set_value = [this]() { + double middle_frequent = this->spectrogram_line->frequency_range().center(); + bool ok = false; + double power = spectrogram_line->get_power(middle_frequent, ok, renderive::SRC::Render); + if (ok) + this->progress_bar1->setValue(power); + }; + } return w; } QWidget* Radio_Widget::create_water_fall_plot() { @@ -82,6 +105,7 @@ QWidget* Radio_Widget::create_water_fall_plot() { QMenu* menu{}; void init() override { Plot::init(); + configure_radio_plot_perf(this); object_name = "Water_Fall_Plot"; auto data = create_renderable_node(get_root_renderable(), "Data_Renderable"); auto axis = create_renderable_node(get_root_renderable(), "Axis_Renderable"); @@ -114,11 +138,11 @@ QWidget* Radio_Widget::create_water_fall_plot() { } void contextMenuEvent(QContextMenuEvent* event) override { if (!menu) { - auto ws = - bw(cw(wf.get(), -1), "瀑布图") + - bw(cw(x_axis.get()), "频率轴") + - bw(cw(y_axis.get()), "时间轴") + - bw(cw(msr.get()), "多选框"); + auto ws = concat_widgets( + bw(cw(wf.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()); @@ -139,6 +163,7 @@ QWidget* Radio_Widget::create_audio_spectrogram_plot() { QMenu* menu{}; void init() override { Plot::init(); + configure_radio_plot_perf(this); object_name = "Spectrum_Plot"; auto data = create_renderable_node(get_root_renderable(), "Data_Renderable"); auto axis = create_renderable_node(get_root_renderable(), "Axis_Renderable"); @@ -169,11 +194,11 @@ QWidget* Radio_Widget::create_audio_spectrogram_plot() { } void contextMenuEvent(QContextMenuEvent* event) override { if (!menu) { - auto ws = - bw(cw(sp.get(), -1), "频谱图") + - bw(cw(x_axis.get()), "频率x轴") + - bw(cw(y_axis.get()), "功率y轴") + - bw(cw(msr.get()), "多选框"); + 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()); @@ -194,6 +219,7 @@ QWidget* Radio_Widget::create_time_power_plot() { QMenu* menu{}; void init() override { Plot::init(); + configure_radio_plot_perf(this); object_name = "Audio_Plot"; auto data = create_renderable_node(get_root_renderable(), "Data_Renderable"); auto axis = create_renderable_node(get_root_renderable(), "Axis_Renderable"); @@ -222,11 +248,11 @@ QWidget* Radio_Widget::create_time_power_plot() { } void contextMenuEvent(QContextMenuEvent* event) override { if (!menu) { - auto ws = - bw(cw(audio.get(), -1), "音频图") + - bw(cw(y_axis.get()), "功率y轴") + - bw(cw(x_axis.get()), "时间轴") + - bw(cw(msr.get()), "多选框"); + auto ws = concat_widgets( + bw(cw(audio.get(), -1), "音频图"), + bw(cw(y_axis.get()), "功率y轴"), + bw(cw(x_axis.get()), "时间轴"), + bw(cw(msr.get()), "多选框")); menu = create_menu(this, ws); } menu->exec(event->globalPos()); @@ -251,7 +277,7 @@ Radio_Widget::Radio_Widget(QWidget* parent) : Base_Widget(parent) { m6 = create_normal("MSG1\n", font_size); select_value_widget = new Frequent_Shower(this); int n = 5; - QVector tick_list(n); + std::vector tick_list(n); double space = 100.0 / n; for (int i = 0; i < n; ++i) { tick_list[i] = i * space; @@ -323,7 +349,9 @@ Radio_Widget::Radio_Widget(QWidget* parent) : Base_Widget(parent) { a_h2->addWidget(create_audio_spectrogram_plot(), 4); init_menu(); } -Radio_Widget::~Radio_Widget() {} +Radio_Widget::~Radio_Widget() { + Back_End::instance()->stop_mock_thread(); +} void Radio_Widget::init_menu() { int font_size = 30; auto btn1_1 = new Menu_Button("模式设置", font_size, []() {}); diff --git a/module/radio/BackEnd/SweepFrequencyWidget.cpp b/module/radio/BackEnd/SweepFrequencyWidget.cpp index d21bb3c..f602a27 100644 --- a/module/radio/BackEnd/SweepFrequencyWidget.cpp +++ b/module/radio/BackEnd/SweepFrequencyWidget.cpp @@ -1,7 +1,6 @@ #include "SweepFrequencyWidget.h" #include #include -#include #include #include #include "../component/FrequentShower.h" @@ -49,11 +48,11 @@ QWidget* Sweep_Frequency_Widget::create_spectrogram_power_plot() { } void contextMenuEvent(QContextMenuEvent* event) override { if (!menu) { - auto ws = - bw(cw(sf.get(), -1), "扫频图") + - bw(cw(x_axis.get()), "x轴") + - bw(cw(y_axis.get()), "y轴") + - bw(cw(msr.get()), "多选框"); + 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()), "多选框")); menu = create_menu(this, ws); } menu->exec(event->globalPos()); diff --git a/module/radio/Global.cpp b/module/radio/Global.cpp index 635e943..a7eb6ab 100644 --- a/module/radio/Global.cpp +++ b/module/radio/Global.cpp @@ -4,7 +4,7 @@ #include "menu/BaseWidgetMenu.h" #include -QVBoxLayout* create_vbox_layout(const QVector& children, QWidget *parent){ +QVBoxLayout* create_vbox_layout(const std::vector& children, QWidget *parent){ auto ret = new QVBoxLayout(parent); ret->setMargin(0); ret->setSpacing(0); @@ -15,7 +15,7 @@ QVBoxLayout* create_vbox_layout(const QVector& children, QWidget *pare return ret; } -QHBoxLayout* create_hbox_layout(const QVector& children, QWidget *parent){ +QHBoxLayout* create_hbox_layout(const std::vector& children, QWidget *parent){ auto ret = new QHBoxLayout(parent); ret->setMargin(0); ret->setSpacing(0); @@ -42,7 +42,7 @@ QRect get_max_rect(const QRect& rect, double WHRate){ } -int calculate_optimal_font_size(const QVector& text_list, const QSize& space_size, const QFont& font) { +int calculate_optimal_font_size(const std::vector& text_list, const QSize& space_size, const QFont& font) { int font_size = 1, textWidth, textHeight; do { textWidth = -1; diff --git a/module/radio/Global.h b/module/radio/Global.h index 9312010..f81ee78 100644 --- a/module/radio/Global.h +++ b/module/radio/Global.h @@ -8,12 +8,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include "psc_global_include/Singleton.hpp" class Global : public Psc::Singleton { public: @@ -21,11 +21,11 @@ public: int adapt_height(int full_screen_height); int adapt_width(int full_screen_width); }; -QVBoxLayout* create_vbox_layout(const QVector& children = {}, QWidget* parent = nullptr); -QHBoxLayout* create_hbox_layout(const QVector& children = {}, QWidget* parent = nullptr); +QVBoxLayout* create_vbox_layout(const std::vector& children = {}, QWidget* parent = nullptr); +QHBoxLayout* create_hbox_layout(const std::vector& children = {}, QWidget* parent = nullptr); QRect get_max_rect(const QRect& rect, double WHRate); int calculate_optimal_font_size(const QString& text, const QSize& space_size, const QFont& font); -int calculate_optimal_font_size(const QVector& text_list, const QSize& space_size, const QFont& font); +int calculate_optimal_font_size(const std::vector& text_list, const QSize& space_size, const QFont& font); QPushButton* create_button(const QString& text, int font_size, const std::function& func = nullptr); namespace renderive { template diff --git a/module/radio/Toolbox_private/CircularLinkedList.hpp b/module/radio/Toolbox_private/CircularLinkedList.hpp index 2f63536..47f5b0c 100644 --- a/module/radio/Toolbox_private/CircularLinkedList.hpp +++ b/module/radio/Toolbox_private/CircularLinkedList.hpp @@ -1,6 +1,6 @@ #ifndef Toolbox_Circular_Linked_List_H #define Toolbox_Circular_Linked_List_H - +#include namespace Toolbox { template struct Circular_Linked_List_Node { @@ -12,9 +12,9 @@ namespace Toolbox { public: Circular_Linked_List_Node *head = nullptr; Circular_Linked_List_Node *cur = nullptr; - void init(const QVector &data_list) { + void init(const std::vector &data_list) { head = new Circular_Linked_List_Node(); - head->data = data_list.first(); + head->data = data_list.front(); Circular_Linked_List_Node *prev = head; int n = data_list.size(); for (int i = 1; i < n - 1; i++) { @@ -25,7 +25,7 @@ namespace Toolbox { prev = node; } auto tail = new Circular_Linked_List_Node(); - tail->data = data_list.last(); + tail->data = data_list.back(); tail->prev = prev; prev->next = tail; tail->next = head; @@ -66,9 +66,9 @@ namespace Toolbox { node->next = that; that->prev = node; } - QVector *> to_vector() { + std::vector *> to_vector() { if (head == nullptr) return {}; - QVector *> ret; + std::vector *> ret; Circular_Linked_List_Node *cur = head; do { ret.push_back(cur); diff --git a/module/radio/Toolbox_private/Node.hpp b/module/radio/Toolbox_private/Node.hpp index 87c3827..013c9b7 100644 --- a/module/radio/Toolbox_private/Node.hpp +++ b/module/radio/Toolbox_private/Node.hpp @@ -1,7 +1,8 @@ #ifndef Toolbox_Node_H #define Toolbox_Node_H -#include -#include +#include +#include +#include namespace Toolbox { template class Node { @@ -9,37 +10,39 @@ namespace Toolbox { explicit Node() = default; int index() { if (!father) return -1; - return father->sons.indexOf(static_cast(this)); + auto it = std::find(father->sons.begin(), father->sons.end(), static_cast(this)); + if (it == father->sons.end()) return -1; + return static_cast(std::distance(father->sons.begin(), it)); } bool root() { return !father; } bool leaf() { return sons.empty(); } bool first() { if (!father) return false; - return this == father->sons.first(); + return this == father->sons.front(); } bool last() { if (!father) return false; - return this == father->sons.last(); + return this == father->sons.back(); } That *previous() { if (!father) return nullptr; - int i = father->sons.indexOf(static_cast(this)) - 1; + int i = index() - 1; if (i < 0) return nullptr; return father->sons[i]; } That *next() { if (!father) return nullptr; - int i = father->sons.indexOf(static_cast(this)) + 1; - if (i > father->sons.buffer_size()) return nullptr; + int i = index() + 1; + if (i <= 0 || i >= static_cast(father->sons.size())) return nullptr; return father->sons[i]; } That *last_child() { if (sons.empty()) return nullptr; - return sons.last(); + return sons.back(); } That *first_child() { if (sons.empty()) return nullptr; - return sons.first(); + return sons.front(); } That *root_node() { That *ret = static_cast(this); @@ -50,48 +53,50 @@ namespace Toolbox { } int deep() { That *ret = static_cast(this); + int depth = 0; while (ret->father != nullptr) { ret = ret->father; - ret++; + depth++; } - return ret; + return depth; } - //遍历值 - QVector deep_traversed() { + std::vector deep_traversed() { std::vector ret; - ret.append(static_cast(this)); + ret.push_back(static_cast(this)); for (auto &child: sons) { - ret.append(child->deep_traversed()); + std::vector child_values = child->deep_traversed(); + ret.insert(ret.end(), child_values.begin(), child_values.end()); } return ret; } - QVector sequence_traversed() { - QVector ret; - QQueue que; + std::vector sequence_traversed() { + std::vector ret; + std::queue que; That *that = static_cast(this); - que.enqueue(that); + que.push(that); while (!que.empty()) { - That *cur = que.dequeue(); - int n = cur->sons.buffer_size(); - ret.append(cur); + That *cur = que.front(); + que.pop(); + int n = static_cast(cur->sons.size()); + ret.push_back(cur); for (int i = 0; i < n; ++i) { - que.enqueue(cur->sons[i]); + que.push(cur->sons[i]); } } return ret; } - QVector descendants() { - QVector &&ret = sequence_traversed(); - ret.pop_front(); + std::vector descendants() { + std::vector ret = sequence_traversed(); + if (!ret.empty()) ret.erase(ret.begin()); return ret; } That *father = nullptr; - QVector sons; + std::vector sons; }; template class Node_Manager { public: - QVector roots; + std::vector roots; }; } -#endif \ No newline at end of file +#endif diff --git a/module/radio/Toolbox_private/RollObject.h b/module/radio/Toolbox_private/RollObject.h index 1bcd6cf..43db794 100644 --- a/module/radio/Toolbox_private/RollObject.h +++ b/module/radio/Toolbox_private/RollObject.h @@ -2,18 +2,21 @@ #define Toolbox_Roll_Widget_H #include #include +#include +#include +#include namespace Toolbox { template class Roll_Object : QObject { public: explicit Roll_Object(QObject *parent = nullptr) : QObject(parent) {} - explicit Roll_Object(QVector widgets, std::function enter_func, + explicit Roll_Object(std::vector widgets, std::function enter_func, std::function leave_func, QObject *parent) : widgets(std::move(widgets)), enter_func(enter_func), leave_func(leave_func), QObject(parent) { - if (enter_func) enter_func(widgets[index]); + if (!this->widgets.empty() && enter_func) enter_func(this->widgets[index]); } int index = 0; - QVector widgets; + std::vector widgets; std::function enter_func; std::function leave_func; T *cur() { @@ -22,7 +25,9 @@ namespace Toolbox { } void set_cur(T *cur) { if (widgets.empty()) return; - int new_index = widgets.indexOf(cur); + auto it = std::find(widgets.begin(), widgets.end(), cur); + if (it == widgets.end()) return; + int new_index = static_cast(std::distance(widgets.begin(), it)); if (leave_func) leave_func(widgets[index]); index = new_index; if (enter_func) enter_func(widgets[index]); @@ -32,7 +37,7 @@ namespace Toolbox { if (widgets.empty()) return; if (leave_func) leave_func(widgets[index]); widgets[index]->update(); - if (widgets.last() != widgets[index]) { + if (widgets.back() != widgets[index]) { index++; } else { index = 0; @@ -44,10 +49,10 @@ namespace Toolbox { if (widgets.empty()) return; if (leave_func) leave_func(widgets[index]); widgets[index]->update(); - if (widgets.first() != widgets[index]) { + if (widgets.front() != widgets[index]) { index--; } else { - index = widgets.size() - 1; + index = static_cast(widgets.size()) - 1; } if (enter_func) enter_func(widgets[index]); widgets[index]->update(); diff --git a/module/radio/Toolbox_private/view/FileFolderBar.cpp b/module/radio/Toolbox_private/view/FileFolderBar.cpp index 67b9c80..a7b7a3d 100644 --- a/module/radio/Toolbox_private/view/FileFolderBar.cpp +++ b/module/radio/Toolbox_private/view/FileFolderBar.cpp @@ -1,5 +1,6 @@ #include "FileFolderBar.h" #include +#include namespace Toolbox { File_Folder_Bar::File_Folder_Bar(QWidget *parent) : QWidget(parent) { //setAttribute(Qt::WA_OpaquePaintEvent); @@ -19,17 +20,18 @@ namespace Toolbox { QPainter painter(this); int index = 0; for (File_Folder *&root: roots) { - QQueue que; + std::queue que; root->deep = 0; - que.enqueue(root); + que.push(root); while (!que.empty()) { - File_Folder *cur = que.dequeue(); + File_Folder *cur = que.front(); + que.pop(); int n = cur->sons.size(); cur->draw(index++, &painter); for (int i = 0; i < n; ++i) { if (cur->is_show_sons) { cur->sons[i]->deep = cur->deep + 1; - que.enqueue(cur->sons[i]); + que.push(cur->sons[i]); } } } diff --git a/module/radio/component/ProgressBar.cpp b/module/radio/component/ProgressBar.cpp index 5df42ec..1a57998 100644 --- a/module/radio/component/ProgressBar.cpp +++ b/module/radio/component/ProgressBar.cpp @@ -1,13 +1,21 @@ #include "ProgressBar.h" #include +#include +#include +#include +#include -Progress_Bar::Progress_Bar(const QVector& tick_list, QWidget *parent) : QWidget(parent), tick_list(tick_list) { +Progress_Bar::Progress_Bar(const std::vector& tick_list, QWidget *parent) : QWidget(parent), tick_list(tick_list) { setAttribute(Qt::WA_OpaquePaintEvent, true); timer = startTimer(30); } double Progress_Bar::get_draw_width(double value) { int n = tick_list.size(); + if (n < 2 || QWidget::width() <= 0) + return 0.0; + if (!std::isfinite(value)) + value = tick_list.front().value; int i = 1; for(; i < n - 1; ++i) { double cur = tick_list[i].value; @@ -20,21 +28,28 @@ double Progress_Bar::get_draw_width(double value) { double lower = tick_list[lower_offset].value; double upper = tick_list[upper_offset].value; double w_step = (double)QWidget::width()/(double)(n-1); - double last_rate = qMax(0.0, (value - lower)/(upper - lower)); + double last_rate = upper == lower ? 0.0 : (value - lower)/(upper - lower); + last_rate = std::clamp(last_rate, 0.0, 1.0); double draw_width = w_step * (last_rate + lower_offset); - QString ticks; - for(Tick& tick : tick_list) { - ticks.append(" " + QString::number(tick.value)); - } - // qDebug() << QString("%1->[%2,%3] i=%4 n=%5 draw_width:%6 width:%7 ticks:%8 w_step:%9 last_rate:%10") - // .arg(value).arg(lower).arg(upper).arg(i).arg(n).arg(draw_width).arg(width()).arg(ticks) - // .arg(w_step).arg(last_rate); - return draw_width; + return std::clamp(draw_width, 0.0, (double)QWidget::width()); +} +void Progress_Bar::setValue(double value) { + if (thread() != QThread::currentThread()) { + queued_value.store(value, std::memory_order_release); + if (!queued_value_update.exchange(true, std::memory_order_acq_rel)) { + QMetaObject::invokeMethod(this, [this]() { + double value = queued_value.load(std::memory_order_acquire); + queued_value_update.store(false, std::memory_order_release); + setValue(value); + }, Qt::QueuedConnection); + } + return; + } + this->value = value; + update(); } - - - void Progress_Bar::paintEvent(QPaintEvent *event) { + Q_UNUSED(event) QPainter painter(this); painter.setPen(Qt::NoPen); painter.fillRect(rect(), QApplication::style()->standardPalette().brush(QPalette::Window)); @@ -44,18 +59,19 @@ void Progress_Bar::paintEvent(QPaintEvent *event) { int n = tick_list.size(); int tick_w = 1; double draw_width = get_draw_width(value); - // 背景 - painter.fillRect(0, 0, draw_width - tick_w - 4, height()/2, Qt::black); + int fill_width = std::max(0, static_cast(draw_width) - tick_w - 4); + if (fill_width > 0) + painter.fillRect(0, 0, fill_width, height()/2, Qt::black); int cur_x = 0; - // 进度条 + int tick_step = std::max(1, tick_w + (int)tick_space_w); while(cur_x + tick_w + 4 < draw_width){ painter.fillRect(cur_x, 0, tick_w, height()/2, Qt::gray); - cur_x += tick_w + (int)tick_space_w; + cur_x += tick_step; } int line_y = (int)hh + 2; - painter.fillRect(cur_x -(int)tick_space_w , 0, 4, line_y - 0, Qt::yellow); + int marker_x = std::clamp(cur_x - (int)tick_space_w, 0, std::max(0, QWidget::width() - 4)); + painter.fillRect(marker_x, 0, 4, line_y, Qt::yellow); painter.drawLine(0, line_y , (int)w, line_y); - // 画刻度 QFont font; font.setBold(true); QFontMetrics fm(font); diff --git a/module/radio/component/ProgressBar.h b/module/radio/component/ProgressBar.h index 4ddbc33..3eed36c 100644 --- a/module/radio/component/ProgressBar.h +++ b/module/radio/component/ProgressBar.h @@ -1,7 +1,8 @@ #ifndef Progress_Bar_H #define Progress_Bar_H #include - +#include +#include #include "../Global.h" struct Tick{ @@ -12,24 +13,26 @@ struct Tick{ QString that = (text[0] == '+' || text[0] == '-' || text[0] == '<' || text[0] == '>') ? text.mid(1) : text; value = that.toDouble(); } - Tick(QString text, QColor color, double value) : text(std::move(text)), color(std::move(color)){ - value = value; + Tick(QString text, QColor color, double value) : text(std::move(text)), color(std::move(color)), value(value){ } }; class Progress_Bar : public QWidget { public: - explicit Progress_Bar(const QVector& tick_list, QWidget *parent = nullptr); + explicit Progress_Bar(const std::vector& tick_list, QWidget *parent = nullptr); double tick_space_w = 1; double value = 0; int timer; std::function set_value = nullptr; + std::atomic_bool queued_value_update{false}; + std::atomic queued_value{0.0}; double get_draw_width(double value); + void setValue(double value); protected: void paintEvent(QPaintEvent *event) override; void timerEvent(QTimerEvent *event) override; - QVector tick_list; + std::vector tick_list; }; #endif diff --git a/module/radio/menu/BaseWidgetMenu.cpp b/module/radio/menu/BaseWidgetMenu.cpp index ca19ee1..3bde868 100644 --- a/module/radio/menu/BaseWidgetMenu.cpp +++ b/module/radio/menu/BaseWidgetMenu.cpp @@ -46,7 +46,7 @@ void Base_Widget_Menu::showEvent(QShowEvent *event) { event->accept(); } -void Base_Widget_Menu::add_menu_button_on_layout1(const QVector& buttons, int stretch) { +void Base_Widget_Menu::add_menu_button_on_layout1(const std::vector& buttons, int stretch) { for(Abstract_Menu_Button* btn : buttons){ first_layout->addWidget(btn, 1); roll_object.widgets.push_back(btn); @@ -58,7 +58,7 @@ void Base_Widget_Menu::add_menu_button_on_layout1(const QVector& buttons, int stretch) { +void Base_Widget_Menu::add_menu_button_on_layout2(const std::vector& buttons, int stretch) { for(Abstract_Menu_Button* btn : buttons){ second_layout->addWidget(btn, 1); roll_object.widgets.push_back(btn); @@ -71,11 +71,11 @@ void Base_Widget_Menu::add_menu_button_on_layout2(const QVector& buttons) { +void Base_Widget_Menu::add_menu_button_on_layout1(const std::vector& buttons) { add_menu_button_on_layout1(buttons, 5 - buttons.size()); } -void Base_Widget_Menu::add_menu_button_on_layout2(const QVector& buttons) { +void Base_Widget_Menu::add_menu_button_on_layout2(const std::vector& buttons) { add_menu_button_on_layout2(buttons, 5 - buttons.size()); } diff --git a/module/radio/menu/BaseWidgetMenu.h b/module/radio/menu/BaseWidgetMenu.h index 1b1436b..195ed4e 100644 --- a/module/radio/menu/BaseWidgetMenu.h +++ b/module/radio/menu/BaseWidgetMenu.h @@ -1,9 +1,9 @@ #ifndef Base_Widget_Menu_H #define Base_Widget_Menu_H #include "Renderive/export.h" -#include #include #include +#include #include "Widget/base/Node.hpp" #include "Widget/base/Roll_Object.h" class QHBoxLayout; @@ -22,10 +22,10 @@ public: Base_Widget_Menu* create_sub_widget_menu(Abstract_Menu_Button* btn); void esc(Base_Widget_Menu* menu); void confirm(); - void add_menu_button_on_layout1(const QVector& buttons, int stretch); - void add_menu_button_on_layout2(const QVector& buttons, int stretch); - void add_menu_button_on_layout1(const QVector& buttons); - void add_menu_button_on_layout2(const QVector& buttons); + void add_menu_button_on_layout1(const std::vector& buttons, int stretch); + void add_menu_button_on_layout2(const std::vector& buttons, int stretch); + void add_menu_button_on_layout1(const std::vector& buttons); + void add_menu_button_on_layout2(const std::vector& buttons); signals : void show_that();