diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index d56b9d5..5d4f914 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -83,6 +83,7 @@ add_executable(geopro_desktop WIN32 panels/columns/Column3DAnalysis.cpp panels/columns/CategorySection.cpp panels/columns/CategoryAnalysisTab.cpp + panels/columns/DateRangeEdit.cpp panels/columns/ColumnDrawer.cpp panels/AnomalyTablePanel.cpp panels/LoadingOverlay.cpp diff --git a/src/app/panels/columns/CategorySection.cpp b/src/app/panels/columns/CategorySection.cpp index 97decc8..1fbcfb4 100644 --- a/src/app/panels/columns/CategorySection.cpp +++ b/src/app/panels/columns/CategorySection.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include "panels/columns/DateRangeEdit.hpp" #include #include #include @@ -68,21 +68,10 @@ CategorySection::CategorySection(const CategorySpec& spec, geopro::data::Dataset [this](int) { rebuildList(); }); filterRow->addWidget(arrayCombo_); } - auto makeDate = [this]() { - auto* d = new QDateEdit(body_); - d->setCalendarPopup(true); - d->setDisplayFormat(QStringLiteral("yyyy-MM-dd")); - d->setSpecialValueText(QStringLiteral("不限")); // 最小日期→显示"不限" - d->setDate(d->minimumDate()); - connect(d, &QDateEdit::dateChanged, this, [this](const QDate&) { rebuildList(); }); - return d; - }; - fromDate_ = makeDate(); - toDate_ = makeDate(); filterRow->addWidget(new QLabel(QStringLiteral("采集"), body_)); - filterRow->addWidget(fromDate_, 1); - filterRow->addWidget(new QLabel(QStringLiteral("至"), body_)); - filterRow->addWidget(toDate_, 1); + dateRange_ = new DateRangeEdit(body_); + connect(dateRange_, &DateRangeEdit::rangeChanged, this, [this] { rebuildList(); }); + filterRow->addWidget(dateRange_, 1); body->addLayout(filterRow); // 段体:可勾选数据树(勾选=渲染)。复用数据列表卡片委托与 populateDatasetList。 @@ -152,17 +141,17 @@ bool CategorySection::passesFilters(const DsRow& row) const { if (!hit) return false; } } - // 采集时间段(collectTime 经 dict 取;缺则回退 createTime;最小日期="不限"不约束)。 - const bool hasFrom = fromDate_ && fromDate_->date() > fromDate_->minimumDate(); - const bool hasTo = toDate_ && toDate_->date() > toDate_->minimumDate(); - if (hasFrom || hasTo) { + // 采集时间范围(collectTime 经 dict 取;缺则回退 createTime;空范围不约束)。 + const QDate from = dateRange_ ? dateRange_->from() : QDate(); + const QDate to = dateRange_ ? dateRange_->to() : QDate(); + if (from.isValid() || to.isValid()) { const DsTypeFields* f = dict_ ? dict_->fields(spec_.dsTypeCode) : nullptr; std::string ts = f ? collectTimeOf(row, *f) : std::string(); if (ts.empty()) ts = row.createTime; const QDate d = QDate::fromString(QString::fromStdString(ts).left(10), QStringLiteral("yyyy-MM-dd")); if (d.isValid()) { - if (hasFrom && d < fromDate_->date()) return false; - if (hasTo && d > toDate_->date()) return false; + if (from.isValid() && d < from) return false; + if (to.isValid() && d > to) return false; } } return true; diff --git a/src/app/panels/columns/CategorySection.hpp b/src/app/panels/columns/CategorySection.hpp index e85ca08..afb77c6 100644 --- a/src/app/panels/columns/CategorySection.hpp +++ b/src/app/panels/columns/CategorySection.hpp @@ -18,6 +18,8 @@ class DatasetFieldDictionary; namespace geopro::app { +class DateRangeEdit; + // 单个数据类型大类段(spec §7):段头(标题/折叠 + 装置类型/日期筛选 + 「+新增三维体」)+ 段体(可勾选数据树)。 // 勾选数据行 = 渲染(帘面/体素/切片);段头生成按钮据当前勾选源发 generateVolumeRequested。 class CategorySection : public QWidget { @@ -51,8 +53,7 @@ private: QToolButton* header_ = nullptr; // 折叠头(标题 + 箭头) QWidget* body_ = nullptr; // 段体容器(折叠时隐藏) QComboBox* arrayCombo_ = nullptr; // 装置类型筛选(仅 hasArrayTypeFilter) - QDateEdit* fromDate_ = nullptr; // 采集时间段·起 - QDateEdit* toDate_ = nullptr; // 采集时间段·止 + DateRangeEdit* dateRange_ = nullptr; // 采集时间范围筛选(起止双日历,可清空) QTreeWidget* list_ = nullptr; }; diff --git a/src/app/panels/columns/DateRangeEdit.cpp b/src/app/panels/columns/DateRangeEdit.cpp new file mode 100644 index 0000000..0a8e927 --- /dev/null +++ b/src/app/panels/columns/DateRangeEdit.cpp @@ -0,0 +1,97 @@ +#include "panels/columns/DateRangeEdit.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include "Theme.hpp" + +namespace geopro::app { + +DateRangeEdit::DateRangeEdit(QWidget* parent) : QWidget(parent) { + auto* lay = new QHBoxLayout(this); + lay->setContentsMargins(0, 0, 0, 0); + lay->setSpacing(0); + btn_ = new QToolButton(this); + btn_->setToolButtonStyle(Qt::ToolButtonTextOnly); + btn_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + btn_->setPopupMode(QToolButton::InstantPopup); + btn_->setToolTip(QStringLiteral("按采集时间筛选(起 ~ 止),可清空")); + connect(btn_, &QToolButton::clicked, this, &DateRangeEdit::openPopup); + lay->addWidget(btn_); + updateText(); +} + +void DateRangeEdit::openPopup() { + if (!popup_) { + popup_ = new QFrame(this, Qt::Popup); + popup_->setFrameShape(QFrame::StyledPanel); + applyTokenizedStyleSheet( + popup_, QStringLiteral("QFrame{background:{{bg/panel}};border:1px solid {{border/default}};" + "border-radius:8px;}")); + auto* v = new QVBoxLayout(popup_); + v->setContentsMargins(space::kSm, space::kSm, space::kSm, space::kSm); + + auto* cals = new QHBoxLayout(); + auto* fromCol = new QVBoxLayout(); + fromCol->addWidget(new QLabel(QStringLiteral("起始"), popup_)); + fromCal_ = new QCalendarWidget(popup_); + fromCol->addWidget(fromCal_); + cals->addLayout(fromCol); + auto* toCol = new QVBoxLayout(); + toCol->addWidget(new QLabel(QStringLiteral("结束"), popup_)); + toCal_ = new QCalendarWidget(popup_); + toCol->addWidget(toCal_); + cals->addLayout(toCol); + v->addLayout(cals); + + auto* btns = new QHBoxLayout(); + auto* clr = new QPushButton(QStringLiteral("清空"), popup_); + auto* ok = new QPushButton(QStringLiteral("确定"), popup_); + connect(clr, &QPushButton::clicked, this, &DateRangeEdit::clearAndClose); + connect(ok, &QPushButton::clicked, this, &DateRangeEdit::applyAndClose); + btns->addWidget(clr); + btns->addStretch(1); + btns->addWidget(ok); + v->addLayout(btns); + } + // 已有范围则定位到当前值,否则日历默认今天(不再 1752)。 + if (from_.isValid()) fromCal_->setSelectedDate(from_); + if (to_.isValid()) toCal_->setSelectedDate(to_); + popup_->adjustSize(); + popup_->move(mapToGlobal(QPoint(0, height()))); + popup_->show(); +} + +void DateRangeEdit::applyAndClose() { + from_ = fromCal_->selectedDate(); + to_ = toCal_->selectedDate(); + if (from_.isValid() && to_.isValid() && from_ > to_) std::swap(from_, to_); // 起>止则交换 + if (popup_) popup_->hide(); + updateText(); + emit rangeChanged(); +} + +void DateRangeEdit::clearAndClose() { + from_ = QDate(); + to_ = QDate(); + if (popup_) popup_->hide(); + updateText(); + emit rangeChanged(); +} + +void DateRangeEdit::updateText() { + if (!from_.isValid() && !to_.isValid()) { + btn_->setText(QStringLiteral("全部时间 ▾")); + return; + } + const QString f = from_.isValid() ? from_.toString(QStringLiteral("yyyy-MM-dd")) : QStringLiteral("不限"); + const QString t = to_.isValid() ? to_.toString(QStringLiteral("yyyy-MM-dd")) : QStringLiteral("不限"); + btn_->setText(QStringLiteral("%1 ~ %2 ▾").arg(f, t)); +} + +} // namespace geopro::app diff --git a/src/app/panels/columns/DateRangeEdit.hpp b/src/app/panels/columns/DateRangeEdit.hpp new file mode 100644 index 0000000..b7bb7bb --- /dev/null +++ b/src/app/panels/columns/DateRangeEdit.hpp @@ -0,0 +1,38 @@ +#pragma once +#include +#include + +class QToolButton; +class QCalendarWidget; +class QFrame; + +namespace geopro::app { + +// 日期范围选择器(spec 采集时间筛选):一个按钮显示「起 ~ 止」,点开弹双日历面板选起止; +// 可清空(回到"全部时间");默认不限,日历定位今天(不再停在 1752)。 +class DateRangeEdit : public QWidget { + Q_OBJECT +public: + explicit DateRangeEdit(QWidget* parent = nullptr); + + QDate from() const { return from_; } // 无效 QDate = 不限下限 + QDate to() const { return to_; } // 无效 QDate = 不限上限 + +signals: + void rangeChanged(); + +private: + void openPopup(); + void applyAndClose(); + void clearAndClose(); + void updateText(); + + QToolButton* btn_ = nullptr; + QFrame* popup_ = nullptr; + QCalendarWidget* fromCal_ = nullptr; + QCalendarWidget* toCal_ = nullptr; + QDate from_; + QDate to_; +}; + +} // namespace geopro::app