From c86c24488c646853152d03ccff46d1b3b0c98df7 Mon Sep 17 00:00:00 2001 From: lenn Date: Thu, 27 Nov 2025 15:02:39 +0800 Subject: [PATCH] =?UTF-8?q?setting.cc=E9=A2=84=E7=95=99=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/setting.cc | 36 +++++++++++++- components/view.cc | 111 +++++++++++++++++++++++++----------------- 2 files changed, 99 insertions(+), 48 deletions(-) diff --git a/components/setting.cc b/components/setting.cc index d779b5a..1441f4b 100644 --- a/components/setting.cc +++ b/components/setting.cc @@ -244,6 +244,28 @@ static auto AddProfileLongItem(creeper::ThemeManager& manager) { fbpro::Clickable {[]{ ShowAddProfileDialog(); }}, }; } +static auto ImportProfileLongItem(creeper::ThemeManager& manager) { + return new FilledButton { + fbpro::ThemeManager {manager}, + fbpro::Text {QStringLiteral("导入配置")}, + widget::pro::SizePolicy {QSizePolicy::Fixed, QSizePolicy::Expanding}, + widget::pro::MinimumHeight {40}, + widget::pro::MinimumWidth {320}, + fbpro::Radius {12}, + fbpro::Clickable {[]{ qDebug() << "ImportProfileLongItem"; }}, + }; +} +static auto ExportProfileLongItem(creeper::ThemeManager& manager) { + return new FilledButton { + fbpro::ThemeManager {manager}, + fbpro::Text {QStringLiteral("导出配置")}, + widget::pro::SizePolicy {QSizePolicy::Fixed, QSizePolicy::Expanding}, + widget::pro::MinimumHeight {40}, + widget::pro::MinimumWidth {320}, + fbpro::Radius {12}, + fbpro::Clickable {[]{ qDebug() << "ExportProfileLongItem"; }}, + }; +} static auto ProfileItemComponent(creeper::ThemeManager& manager, ConfigProfile& profile, const std::shared_ptr>>& profiles_store) { QString matrix_size = "规格:" + QString{ "%1 * %2" }.arg(profile.matrix_width).arg(profile.matrix_height); @@ -421,9 +443,19 @@ auto SettingComponent(SettingComponentState& state) noexcept -> raw_pointer { + lnpro::Item{ + AddProfileLongItem(state.manager) + }, + lnpro::Item { + ImportProfileLongItem(state.manager) + }, + lnpro::Item { + ExportProfileLongItem(state.manager) + } }, + + col::pro::Item{ scroll::pro::ThemeManager { state.manager }, scroll::pro::HorizontalScrollBarPolicy { Qt::ScrollBarAlwaysOff }, diff --git a/components/view.cc b/components/view.cc index 574ba66..8c8ede1 100644 --- a/components/view.cc +++ b/components/view.cc @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -509,6 +510,45 @@ SensorUiState& sensor_state() { return state; } +static void RefreshPortsForView(SensorUiState& sensor) { + QStringList ports_list; + const auto ports = ffmsep::CPStreamCore::list_available_ports(); + ports_list.reserve(static_cast(ports.size())); + for (const auto& info: ports) { + ports_list.emplace_back(QString::fromStdString(info.port)); + } + if (!sensor.selected_port.isEmpty()) { + const bool exists = ports_list.contains(sensor.selected_port); + if (!exists) { + sensor.selected_port = ports_list.isEmpty() ? QString{} : ports_list.front(); + } + } + else if (!ports_list.isEmpty()) { + sensor.selected_port = ports_list.front(); + } + + sensor.port_items->set(std::move(ports_list)); + RefreshProfilesForView(); +} + +class PortHoverRefreshFilter final : public QObject { + public: + explicit PortHoverRefreshFilter(SensorUiState& sensor, QObject* parent = nullptr) + : QObject(parent) + , sensor_(sensor) { } + + protected: + bool eventFilter(QObject* watched, QEvent* event) override { + if (event && event->type() == QEvent::Enter) { + RefreshPortsForView(sensor_); + } + return QObject::eventFilter(watched, event); + } + + private: + SensorUiState& sensor_; +}; + } // namespace void RefreshProfilesForView() { @@ -570,17 +610,23 @@ static auto ComConfigComponent(ThemeManager& manager) { lnpro::Item{ dmpro::ThemeManager{ manager }, dmpro::LeadingIcon{ material::icon::kArrowDropDown, material::regular::font }, - dmpro::TextChanged{ [sensor_ptr = &sensor](QString text) { - // const auto text = self.currentText(); - if (!text.isEmpty()) { - sensor_ptr->selected_port = text; - } - } }, - dmpro::LabelText{ "COM" }, - MutableForward{ + dmpro::TextChanged{ [sensor_ptr = &sensor](QString text) { + // const auto text = self.currentText(); + if (!text.isEmpty()) { + sensor_ptr->selected_port = text; + } + } }, + dmpro::LabelText{ "COM" }, + MutableForward{ dmpro::Items{}, sensor.port_items, }, + dmpro::Apply{ [&sensor](dropdown_menu::internal::DropdownMenu& self) { + if (!self.property("portHoverRefreshAttached").toBool()) { + self.installEventFilter(new PortHoverRefreshFilter(sensor, &self)); + self.setProperty("portHoverRefreshAttached", true); + } + } }, }, lnpro::Item{ dmpro::ThemeManager{ manager }, @@ -619,11 +665,11 @@ static auto ComConfigComponent(ThemeManager& manager) { icon_button::pro::FontIcon{}, link_icon_context, }, - ibpro::Clickable{ [sensor_ptr = &sensor, link_icon_context] { - auto& sensor = *sensor_ptr; - if (!sensor.controller) { - return; - } + ibpro::Clickable{ [sensor_ptr = &sensor, link_icon_context] { + auto& sensor = *sensor_ptr; + if (!sensor.controller) { + return; + } if (sensor.controller->is_connected()) { sensor.controller->stop(); link_icon_context->set(QString::fromLatin1(material::icon::kAddLink)); @@ -639,41 +685,14 @@ static auto ComConfigComponent(ThemeManager& manager) { std::cerr << "Failed to start sensor stream: " << sensor.controller->last_error().toStdString() << "\n"; - } - } - } } }, - lnpro::Item{ - ibpro::ThemeManager{ manager }, - ibpro::FixedSize{ 40, 40 }, - ibpro::Color{ IconButton::Color::TONAL }, - ibpro::Font{ material::kRegularExtraSmallFont }, - ibpro::FontIcon{ material::icon::kRefresh }, - ibpro::Clickable{ [&sensor] { - QStringList ports_list; - const auto ports = ffmsep::CPStreamCore::list_available_ports(); - ports_list.reserve(static_cast(ports.size())); - for (const auto& info: ports) { - ports_list.emplace_back(QString::fromStdString(info.port)); - } - if (!sensor.selected_port.isEmpty()) { - const bool exists = ports_list.contains(sensor.selected_port); - if (!exists) { - sensor.selected_port = ports_list.isEmpty() ? QString{} : ports_list.front(); } } - else if (!ports_list.isEmpty()) { - sensor.selected_port = ports_list.front(); - } - - sensor.port_items->set(std::move(ports_list)); - RefreshProfilesForView(); - } }, - }, - lnpro::Item{ - fbpro::ThemeManager{ manager }, - fbpro::FixedSize{ 40, 40 }, - fbpro::Radius{ 8.0 }, - // fbpro::Color { IconButton::Color::TONAL }, + } } }, + lnpro::Item{ + fbpro::ThemeManager{ manager }, + fbpro::FixedSize{ 40, 40 }, + fbpro::Radius{ 8.0 }, + // fbpro::Color { IconButton::Color::TONAL }, fbpro::Font{ material::kRegularExtraSmallFont }, fbpro::Text{ "drive_file_move" }, fbpro::Clickable{ [&sensor] {