diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 9dbc572..db8ac21 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -25,6 +25,7 @@ add_executable(geopro_desktop WIN32 panels/DatasetListPanel.cpp panels/ObjectTreePanel.cpp panels/DynamicFormView.cpp + panels/ObjectExceptionPanel.cpp CentralScene.cpp ProjectListDialog.cpp SettingsDialog.cpp) diff --git a/src/app/panels/ObjectExceptionPanel.cpp b/src/app/panels/ObjectExceptionPanel.cpp new file mode 100644 index 0000000..1dd112b --- /dev/null +++ b/src/app/panels/ObjectExceptionPanel.cpp @@ -0,0 +1,85 @@ +#include "panels/ObjectExceptionPanel.hpp" + +#include +#include +#include +#include + +#include "Theme.hpp" + +namespace geopro::app { + +namespace { +QTreeWidgetItem* addException(QTreeWidgetItem* parent, const geopro::data::ExceptionRow& e) { + auto* item = new QTreeWidgetItem(parent); + const QString type = + e.typeName.empty() ? QString() : QStringLiteral("(%1)").arg(QString::fromStdString(e.typeName)); + item->setText(0, QString::fromStdString(e.name) + type); + // 详情展开(D6):异常下挂一个详情子项,显示已加载摘要(多行)。 + if (!e.detailSummary.empty()) { + auto* detail = new QTreeWidgetItem(item); + detail->setText(0, QString::fromStdString(e.detailSummary)); + detail->setFirstColumnSpanned(true); + detail->setForeground(0, geopro::app::tokenColor("text/tertiary")); + } + return item; +} +} // namespace + +ObjectExceptionPanel::ObjectExceptionPanel(QWidget* parent) : QWidget(parent) { + auto* lay = new QVBoxLayout(this); + lay->setContentsMargins(0, 0, 0, 0); + lay->setSpacing(0); + + tree_ = new QTreeWidget(this); + tree_->setHeaderHidden(true); + tree_->setIndentation(14); + lay->addWidget(tree_, 1); + + hint_ = new QLabel(QStringLiteral("(勾选对象后显示其异常 / 异常体)"), this); + hint_->setAlignment(Qt::AlignCenter); + geopro::app::applyTokenizedStyleSheet(hint_, QStringLiteral("color:{{text/disabled}}; padding:16px;")); + lay->addWidget(hint_); + tree_->setVisible(false); +} + +void ObjectExceptionPanel::setGroups( + const std::vector& groups) { + tree_->clear(); + bool any = false; + for (const auto& g : groups) { + auto* objItem = new QTreeWidgetItem(tree_); + objItem->setText(0, QString::fromStdString(g.objectName)); + for (const auto& c : g.consortia) { + auto* cItem = new QTreeWidgetItem(objItem); + const QString ctype = c.typeName.empty() + ? QString() + : QStringLiteral("(%1)").arg(QString::fromStdString(c.typeName)); + cItem->setText(0, QStringLiteral("异常体 %1%2") + .arg(QString::fromStdString(c.name.empty() ? c.id : c.name)) + .arg(ctype)); + for (const auto& e : c.exceptions) { addException(cItem, e); any = true; } + } + if (!g.looseExceptions.empty()) { + auto* looseItem = new QTreeWidgetItem(objItem); + looseItem->setText(0, QStringLiteral("独立异常(未合并)")); + for (const auto& e : g.looseExceptions) { addException(looseItem, e); any = true; } + } + } + if (!any) { + showMessage(QStringLiteral("(所选对象暂无异常)")); + return; + } + hint_->setVisible(false); + tree_->setVisible(true); + tree_->expandAll(); +} + +void ObjectExceptionPanel::showMessage(const QString& message) { + tree_->clear(); + tree_->setVisible(false); + hint_->setText(message); + hint_->setVisible(true); +} + +} // namespace geopro::app diff --git a/src/app/panels/ObjectExceptionPanel.hpp b/src/app/panels/ObjectExceptionPanel.hpp new file mode 100644 index 0000000..473575f --- /dev/null +++ b/src/app/panels/ObjectExceptionPanel.hpp @@ -0,0 +1,23 @@ +#pragma once +#include +#include +#include "repo/RepoTypes.hpp" + +class QTreeWidget; +class QLabel; + +namespace geopro::app { + +// 被动:异常 + 异常体 只读树(对象→异常体→异常→详情 + 独立异常)。数据由控制器推送。 +class ObjectExceptionPanel : public QWidget { +public: + explicit ObjectExceptionPanel(QWidget* parent = nullptr); + void setGroups(const std::vector& groups); + void showMessage(const QString& message); + +private: + QTreeWidget* tree_ = nullptr; + QLabel* hint_ = nullptr; +}; + +} // namespace geopro::app