modify file entry info

This commit is contained in:
brige 2025-11-04 00:23:24 +08:00
parent d74a02e0c4
commit c1337ffe49
12 changed files with 130 additions and 83 deletions

View File

@ -103,6 +103,7 @@ void MainWindow::InitUI() {
connect(modelBrowser_, &ModelBrowser::WorkSpaceChange, propertyBrowser_, &PropertyBrowser::OnWorkSpaceChange); connect(modelBrowser_, &ModelBrowser::WorkSpaceChange, propertyBrowser_, &PropertyBrowser::OnWorkSpaceChange);
connect(modelBrowser_, &ModelBrowser::EntityChange, propertyBrowser_, &PropertyBrowser::OnEntityChange); connect(modelBrowser_, &ModelBrowser::EntityChange, propertyBrowser_, &PropertyBrowser::OnEntityChange);
connect(modelBrowser_, &ModelBrowser::FileEntryChange, propertyBrowser_, &PropertyBrowser::OnFileEntryChange);
qtOsgViewWidget_ = new OsgWidget; qtOsgViewWidget_ = new OsgWidget;
qtOsgViewWidget_->Initialize(); qtOsgViewWidget_->Initialize();

View File

@ -46,4 +46,5 @@ void ModelBrowser::InitUI() {
//ModelTreeWidget* treeWidget = modelBrowserPannal_->GetModelTreeWidget(); //ModelTreeWidget* treeWidget = modelBrowserPannal_->GetModelTreeWidget();
connect(treeWidget_, &ModelTreeWidget::WorkSpaceChange, this, &ModelBrowser::WorkSpaceChange); connect(treeWidget_, &ModelTreeWidget::WorkSpaceChange, this, &ModelBrowser::WorkSpaceChange);
connect(treeWidget_, &ModelTreeWidget::EntityChange, this, &ModelBrowser::EntityChange); connect(treeWidget_, &ModelTreeWidget::EntityChange, this, &ModelBrowser::EntityChange);
connect(treeWidget_, &ModelTreeWidget::FileEntryChange, this, &ModelBrowser::FileEntryChange);
} }

View File

@ -14,6 +14,7 @@ public:
Q_SIGNALS: Q_SIGNALS:
void WorkSpaceChange(const QVariant& workSpace); void WorkSpaceChange(const QVariant& workSpace);
void EntityChange(const QVariant& workSpace); void EntityChange(const QVariant& workSpace);
void FileEntryChange(const QVariant& fileEntry);
private: private:
void InitUI(); void InitUI();

View File

@ -5,5 +5,6 @@
enum ItemRol { enum ItemRol {
E_Workspace = Qt::ItemDataRole::UserRole + 1, E_Workspace = Qt::ItemDataRole::UserRole + 1,
E_Entity, E_Entity,
E_UUid E_UUid,
E_FileEntry
}; };

View File

@ -42,6 +42,7 @@ void ModelTreeWidget::OnWorkspaceChange(WorkSpace* workSpace) {
connect(workSpace, &WorkSpace::EntityAdded, this, &ModelTreeWidget::OnEntityAdded); connect(workSpace, &WorkSpace::EntityAdded, this, &ModelTreeWidget::OnEntityAdded);
connect(workSpace, &WorkSpace::EntityRemoved, this, &ModelTreeWidget::OnEntityRemoved); connect(workSpace, &WorkSpace::EntityRemoved, this, &ModelTreeWidget::OnEntityRemoved);
connect(workSpace, &WorkSpace::FilesChanged, this, &ModelTreeWidget::OnWorkspaceFilesChanged);
const QString& name = currentWorkSpace_->GetName(); const QString& name = currentWorkSpace_->GetName();
root_ = new QTreeWidgetItem(this); root_ = new QTreeWidgetItem(this);
@ -56,6 +57,12 @@ void ModelTreeWidget::OnWorkspaceChange(WorkSpace* workSpace) {
for (const auto& entity : entities) { for (const auto& entity : entities) {
AddEntity(root_, entity); AddEntity(root_, entity);
} }
// Create and populate curve entries branch
curvesRoot_ = new QTreeWidgetItem(root_);
curvesRoot_->setText(0, tr("Curves"));
curvesRoot_->setData(0, E_UUid, QString("CurvesRoot"));
PopulateCurveEntries();
} }
void ModelTreeWidget::OnEntityAdded(Entity* entity) { void ModelTreeWidget::OnEntityAdded(Entity* entity) {
@ -163,22 +170,17 @@ void ModelTreeWidget::OnWorkItemChanged(WorkSpaceItem* item) {
} }
void ModelTreeWidget::OnWorkItemCliecked(QTreeWidgetItem* item, int column) { void ModelTreeWidget::OnWorkItemCliecked(QTreeWidgetItem* item, int column) {
// Prefer entity, then file entry, then workspace
QVariant value = item->data(column, E_Entity); QVariant value = item->data(column, E_Entity);
bool isEntity = true; if (value.isValid()) { emit EntityChange(value); return; }
if (!value.isValid()) {
value = item->data(column, E_Workspace);
isEntity = false;
}
if (!value.isValid()) {
LOG_WARN("unknown data rol");
return;
}
if (isEntity) { value = item->data(column, E_FileEntry);
emit EntityChange(value); if (value.isValid()) { emit FileEntryChange(value); return; }
} else {
emit WorkSpaceChange(value); value = item->data(column, E_Workspace);
} if (value.isValid()) { emit WorkSpaceChange(value); return; }
LOG_WARN("unknown data rol");
} }
void ModelTreeWidget::OnItemDoubleClicked(QTreeWidgetItem* item, int column) { void ModelTreeWidget::OnItemDoubleClicked(QTreeWidgetItem* item, int column) {
@ -393,3 +395,32 @@ void ModelTreeWidget::AddEntity(class QTreeWidgetItem* parent, Entity* entity) {
AddEntity(item, child); AddEntity(item, child);
} }
} }
void ModelTreeWidget::PopulateCurveEntries() {
if (!currentWorkSpace_ || !curvesRoot_) return;
// Clear existing curve children
while (curvesRoot_->childCount() > 0) {
QTreeWidgetItem* child = curvesRoot_->child(0);
curvesRoot_->removeChild(child);
delete child;
}
const auto entries = currentWorkSpace_->GetFileEntries(FileEntryType::Curve);
for (const auto& entry : entries) {
if (!entry) continue;
QTreeWidgetItem* item = new QTreeWidgetItem;
item->setText(0, entry->GetName());
QVariant v;
v.setValue(entry.get());
item->setData(0, E_FileEntry, v);
item->setData(0, E_UUid, QString("Curve:%1").arg(entry->GetFileName()));
curvesRoot_->addChild(item);
}
}
void ModelTreeWidget::OnWorkspaceFilesChanged(FileEntryType type, std::shared_ptr<FileEntry> /*fileEntry*/) {
if (type == FileEntryType::Curve) {
PopulateCurveEntries();
}
}

View File

@ -6,6 +6,7 @@
#include "entities/Entity.h" #include "entities/Entity.h"
#include "workspace/WorkSpace.h" #include "workspace/WorkSpace.h"
#include "workspace/WorkSpaceItem.h" #include "workspace/WorkSpaceItem.h"
#include "workspace/FileEntry.h"
class ModelTreeWidget : public QTreeWidget { class ModelTreeWidget : public QTreeWidget {
Q_OBJECT Q_OBJECT
@ -22,6 +23,7 @@ public:
Q_SIGNALS: Q_SIGNALS:
void WorkSpaceChange(const QVariant& workSpace); void WorkSpaceChange(const QVariant& workSpace);
void EntityChange(const QVariant& entity); void EntityChange(const QVariant& entity);
void FileEntryChange(const QVariant& fileEntry);
protected: protected:
void contextMenuEvent(QContextMenuEvent* event) override; void contextMenuEvent(QContextMenuEvent* event) override;
@ -30,6 +32,8 @@ protected:
void OnWorkItemCliecked(QTreeWidgetItem* item, int column); void OnWorkItemCliecked(QTreeWidgetItem* item, int column);
void OnItemDoubleClicked(QTreeWidgetItem* item, int column); void OnItemDoubleClicked(QTreeWidgetItem* item, int column);
void OnWorkspaceFilesChanged(enum class FileEntryType type, std::shared_ptr<FileEntry> fileEntry);
void OnAddMeshEntity(const QString& mesh, const QString& name); void OnAddMeshEntity(const QString& mesh, const QString& name);
class SceneComponent* OnAddComponent(const QString& typeName, class Entity* entity); class SceneComponent* OnAddComponent(const QString& typeName, class Entity* entity);
@ -47,8 +51,10 @@ protected:
private: private:
//void initUI(); //void initUI();
void AddEntity(class QTreeWidgetItem* parent, Entity* entity); void AddEntity(class QTreeWidgetItem* parent, Entity* entity);
void PopulateCurveEntries();
private: private:
WorkSpace* currentWorkSpace_{ nullptr }; WorkSpace* currentWorkSpace_{ nullptr };
QTreeWidgetItem* root_{ nullptr }; QTreeWidgetItem* root_{ nullptr };
QTreeWidgetItem* curvesRoot_{ nullptr };
}; };

View File

@ -43,6 +43,7 @@ void PropertyBrowser::AttachDock(DockWidget* dockWidget) {
} }
void PropertyBrowser::OnWorkSpaceChange(const QVariant& value) { void PropertyBrowser::OnWorkSpaceChange(const QVariant& value) {
inFileEntryView_ = false;
WorkSpace* workspace = value.value<WorkSpace*>(); WorkSpace* workspace = value.value<WorkSpace*>();
if (nullptr == workspace) { if (nullptr == workspace) {
LOG_WARN("workspace is nullptr"); LOG_WARN("workspace is nullptr");
@ -70,25 +71,11 @@ void PropertyBrowser::OnWorkSpaceChange(const QVariant& value) {
QObject::connect(currentWorkspace_, &WorkSpace::FilesChanged, QObject::connect(currentWorkspace_, &WorkSpace::FilesChanged,
this, &PropertyBrowser::OnWorkspaceFilesChanged); this, &PropertyBrowser::OnWorkspaceFilesChanged);
// Mount all curve entries, each as its own top-level group // No longer mount file entries under workspace; file entries are handled separately
auto curves = currentWorkspace_->GetFileEntries(FileEntryType::Curve);
for (const auto& entry : curves) {
if (!entry) continue;
auto curve = entry->AsCurve();
if (!curve) continue;
// Use filename as stable unique id, and include display name in group title
const QString id = QString("CurveEntry:%1").arg(entry->GetFileName());
const QString title = QString("CurveEntry - %1").arg(entry->GetName());
QtProperty* cprop = curveEntryManager_->addProperty(title);
QCurveEntryAttribute attr(curve);
curveEntryManager_->setValue(cprop, attr);
addProperty(cprop, id);
}
} }
void PropertyBrowser::OnEntityChange(const QVariant& value) { void PropertyBrowser::OnEntityChange(const QVariant& value) {
inFileEntryView_ = false;
Entity* entity = value.value<Entity*>(); Entity* entity = value.value<Entity*>();
if (nullptr == entity) { if (nullptr == entity) {
LOG_WARN("engity is nullptr"); LOG_WARN("engity is nullptr");
@ -136,6 +123,43 @@ void PropertyBrowser::OnEntityChange(const QVariant& value) {
} }
} }
void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
FileEntry* entry = value.value<FileEntry*>();
if (!entry) {
LOG_WARN("file entry is nullptr");
return;
}
// Enter single FileEntry view mode and clear existing panels
inFileEntryView_ = true;
browser_->clear();
propertyToId_.clear();
idToProperty_.clear();
idToExpanded_.clear();
// Compute our id and ensure the property exists (create if missing)
const QString id = QString("CurveEntry:%1").arg(entry->GetFileName());
auto curve = entry->AsCurve();
if (!curve) {
LOG_WARN("file entry not a curve: %s", entry->GetFileName().toStdString().c_str());
return;
}
const QString title = QString("CurveEntry - %1").arg(entry->GetName());
QtProperty* prop = curveEntryManager_->addProperty(title);
QCurveEntryAttribute attr(curve);
curveEntryManager_->setValue(prop, attr);
addProperty(prop, id);
// Focus the corresponding group: expand and select it
if (prop) {
QtBrowserItem* item = browser_->topLevelItem(prop);
if (item) {
browser_->setExpanded(item, true);
browser_->setCurrentItem(item);
}
}
}
void PropertyBrowser::InitUI() { void PropertyBrowser::InitUI() {
QBoxLayout* layout = new QVBoxLayout(this); QBoxLayout* layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0); layout->setContentsMargins(0, 0, 0, 0);
@ -208,6 +232,8 @@ void PropertyBrowser::InitPropertyManager() {
void PropertyBrowser::OnWorkspaceFilesChanged(FileEntryType type, std::shared_ptr<FileEntry> fileEntry) { void PropertyBrowser::OnWorkspaceFilesChanged(FileEntryType type, std::shared_ptr<FileEntry> fileEntry) {
if (!currentWorkspace_) return; if (!currentWorkspace_) return;
// In single FileEntry view, skip workspace-driven group refresh to keep panel clean
if (inFileEntryView_) return;
// Refresh workspace group // Refresh workspace group
{ {
auto it = idToProperty_.find(tr("WorkSpace")); auto it = idToProperty_.find(tr("WorkSpace"));
@ -217,52 +243,6 @@ void PropertyBrowser::OnWorkspaceFilesChanged(FileEntryType type, std::shared_pt
workSpaceManager_->setValue(property, worksapceAttribute); workSpaceManager_->setValue(property, worksapceAttribute);
} }
} }
// Refresh curve entry groups when curve files mutate
if (type == FileEntryType::Curve) {
const auto curves = currentWorkspace_->GetFileEntries(FileEntryType::Curve);
// Desired ids for current curves
QSet<QString> desiredIds;
for (const auto& entry : curves) {
if (!entry) continue;
desiredIds.insert(QString("CurveEntry:%1").arg(entry->GetFileName()));
}
// Add or update properties for all current curves
for (const auto& entry : curves) {
if (!entry) continue;
auto curve = entry->AsCurve();
if (!curve) continue;
const QString id = QString("CurveEntry:%1").arg(entry->GetFileName());
const QString title = QString("CurveEntry - %1").arg(entry->GetName());
QCurveEntryAttribute attr(curve);
auto it = idToProperty_.find(id);
if (it != idToProperty_.end()) {
// Update existing group
curveEntryManager_->setValue(it.value(), attr);
} else {
// Create new group for this curve
QtProperty* prop = curveEntryManager_->addProperty(title);
curveEntryManager_->setValue(prop, attr);
addProperty(prop, id);
}
}
// Remove groups for curves that no longer exist
QList<QString> existingIds = idToProperty_.keys();
for (const auto& id : existingIds) {
if (id.startsWith("CurveEntry:") && !desiredIds.contains(id)) {
QtProperty* prop = idToProperty_[id];
browser_->removeProperty(prop);
propertyToId_.remove(prop);
idToExpanded_.remove(id);
idToProperty_.remove(id);
}
}
}
} }
void PropertyBrowser::InitComponentPropertyManager() { void PropertyBrowser::InitComponentPropertyManager() {

View File

@ -18,6 +18,7 @@ public:
void OnWorkSpaceChange(const QVariant& value); void OnWorkSpaceChange(const QVariant& value);
void OnEntityChange(const QVariant& value); void OnEntityChange(const QVariant& value);
void OnFileEntryChange(const QVariant& value);
void OnWorkspaceFilesChanged(enum class FileEntryType type, std::shared_ptr<FileEntry> fileEntry); void OnWorkspaceFilesChanged(enum class FileEntryType type, std::shared_ptr<FileEntry> fileEntry);
void Test(); void Test();
@ -55,5 +56,8 @@ private:
// Track current workspace for real-time refresh // Track current workspace for real-time refresh
class WorkSpace* currentWorkspace_{ nullptr }; class WorkSpace* currentWorkspace_{ nullptr };
// When true, we are showing a single FileEntry view (not workspace-wide groups)
bool inFileEntryView_{ false };
}; };

View File

@ -10,6 +10,7 @@
#include "entities/EntitiesManager.h" #include "entities/EntitiesManager.h"
#include "utils/Transform.h" #include "utils/Transform.h"
#include "utils/OsgUtils.h" #include "utils/OsgUtils.h"
#include "workspace/WorkSpaceManager.h"
QWorkspaceAttribute::QWorkspaceAttribute(class WorkSpace* workspace) QWorkspaceAttribute::QWorkspaceAttribute(class WorkSpace* workspace)
@ -138,9 +139,8 @@ void QWorkspaceAttribute::SetFileEntryPath(FileEntryType type, int index, const
// Update the path of the specific entry // Update the path of the specific entry
entries[index]->SetPath(path); entries[index]->SetPath(path);
// Trigger files changed signal properly
// Trigger files changed signal workspace_->NotifyFileEntryUpdated(type);
workspace_->SetFileEntryCount(type, static_cast<int>(entries.size()));
} }
QString QWorkspaceAttribute::GetFileEntryAbsPath(FileEntryType type, int index) const { QString QWorkspaceAttribute::GetFileEntryAbsPath(FileEntryType type, int index) const {
@ -659,6 +659,7 @@ QCurveEntryAttribute& QCurveEntryAttribute::operator=(const QCurveEntryAttribute
void QCurveEntryAttribute::SetName(const QString& name) { void QCurveEntryAttribute::SetName(const QString& name) {
if (!entry_) return; if (!entry_) return;
entry_->SetName(name); entry_->SetName(name);
if (auto ws = WorkSpaceManager::Get().GetCurrent()) { ws->NotifyFileEntryUpdated(FileEntryType::Curve); }
} }
QString QCurveEntryAttribute::GetName() const { QString QCurveEntryAttribute::GetName() const {
@ -669,6 +670,7 @@ QString QCurveEntryAttribute::GetName() const {
void QCurveEntryAttribute::SetChartType(ChartType type) { void QCurveEntryAttribute::SetChartType(ChartType type) {
if (!entry_) return; if (!entry_) return;
entry_->SetChartType(type); entry_->SetChartType(type);
if (auto ws = WorkSpaceManager::Get().GetCurrent()) { ws->NotifyFileEntryUpdated(FileEntryType::Curve); }
} }
ChartType QCurveEntryAttribute::GetChartType() const { ChartType QCurveEntryAttribute::GetChartType() const {
@ -703,6 +705,7 @@ void QCurveEntryAttribute::SetCurveCount(int count) {
entry_->RemoveCurveProperty(i); entry_->RemoveCurveProperty(i);
} }
} }
if (auto ws = WorkSpaceManager::Get().GetCurrent()) { ws->NotifyFileEntryUpdated(FileEntryType::Curve); }
} }
QString QCurveEntryAttribute::GetCurveName(int index) const { QString QCurveEntryAttribute::GetCurveName(int index) const {
@ -721,6 +724,7 @@ void QCurveEntryAttribute::SetCurveName(int index, const QString& name) {
// overwrite by remove/add pattern // overwrite by remove/add pattern
entry_->RemoveCurveProperty(index); entry_->RemoveCurveProperty(index);
entry_->AddCurveProperty(cp); entry_->AddCurveProperty(cp);
if (auto ws = WorkSpaceManager::Get().GetCurrent()) { ws->NotifyFileEntryUpdated(FileEntryType::Curve); }
} }
QColor QCurveEntryAttribute::GetCurveColor(int index) const { QColor QCurveEntryAttribute::GetCurveColor(int index) const {
@ -738,6 +742,7 @@ void QCurveEntryAttribute::SetCurveColor(int index, const QColor& color) {
cp.color = color; cp.color = color;
entry_->RemoveCurveProperty(index); entry_->RemoveCurveProperty(index);
entry_->AddCurveProperty(cp); entry_->AddCurveProperty(cp);
if (auto ws = WorkSpaceManager::Get().GetCurrent()) { ws->NotifyFileEntryUpdated(FileEntryType::Curve); }
} }
int QCurveEntryAttribute::GetWaveStart(int index) const { int QCurveEntryAttribute::GetWaveStart(int index) const {
@ -755,6 +760,7 @@ void QCurveEntryAttribute::SetWaveStart(int index, int start) {
cp.data.wave.start = start; cp.data.wave.start = start;
entry_->RemoveCurveProperty(index); entry_->RemoveCurveProperty(index);
entry_->AddCurveProperty(cp); entry_->AddCurveProperty(cp);
if (auto ws = WorkSpaceManager::Get().GetCurrent()) { ws->NotifyFileEntryUpdated(FileEntryType::Curve); }
} }
int QCurveEntryAttribute::GetWaveStop(int index) const { int QCurveEntryAttribute::GetWaveStop(int index) const {
@ -772,6 +778,7 @@ void QCurveEntryAttribute::SetWaveStop(int index, int stop) {
cp.data.wave.stop = stop; cp.data.wave.stop = stop;
entry_->RemoveCurveProperty(index); entry_->RemoveCurveProperty(index);
entry_->AddCurveProperty(cp); entry_->AddCurveProperty(cp);
if (auto ws = WorkSpaceManager::Get().GetCurrent()) { ws->NotifyFileEntryUpdated(FileEntryType::Curve); }
} }
double QCurveEntryAttribute::GetReportX(int index) const { double QCurveEntryAttribute::GetReportX(int index) const {
@ -789,6 +796,7 @@ void QCurveEntryAttribute::SetReportX(int index, double x) {
cp.data.report.x = x; cp.data.report.x = x;
entry_->RemoveCurveProperty(index); entry_->RemoveCurveProperty(index);
entry_->AddCurveProperty(cp); entry_->AddCurveProperty(cp);
if (auto ws = WorkSpaceManager::Get().GetCurrent()) { ws->NotifyFileEntryUpdated(FileEntryType::Curve); }
} }
double QCurveEntryAttribute::GetReportY(int index) const { double QCurveEntryAttribute::GetReportY(int index) const {
@ -806,4 +814,5 @@ void QCurveEntryAttribute::SetReportY(int index, double y) {
cp.data.report.y = y; cp.data.report.y = y;
entry_->RemoveCurveProperty(index); entry_->RemoveCurveProperty(index);
entry_->AddCurveProperty(cp); entry_->AddCurveProperty(cp);
if (auto ws = WorkSpaceManager::Get().GetCurrent()) { ws->NotifyFileEntryUpdated(FileEntryType::Curve); }
} }

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include <QString> #include <QString>
#include <QColor> #include <QColor>
@ -398,3 +398,7 @@ private:
ChartProperties chartProperties_; ChartProperties chartProperties_;
ImageProperties imageProperties_; ImageProperties imageProperties_;
}; };
// Enable QVariant support for FileEntry pointers
#include <QMetaType>
Q_DECLARE_METATYPE(FileEntry*)

View File

@ -379,3 +379,9 @@ void WorkSpace::ExecuteCommands(CommandWhen when) {
} }
cmdMgr_->Execute(this, when); cmdMgr_->Execute(this, when);
} }
// 统一属性更新通知:不改变数量,仅提升序号并广播 FilesChanged
void WorkSpace::NotifyFileEntryUpdated(FileEntryType type, std::shared_ptr<FileEntry> fileEntry) {
++filesSeq_;
emit FilesChanged(type, fileEntry);
}

View File

@ -127,6 +127,9 @@ public:
void OnLoaded(); void OnLoaded();
// 通知:某类型的文件条目属性已更新(不改变数量,仅触发刷新)
void NotifyFileEntryUpdated(FileEntryType type, std::shared_ptr<FileEntry> fileEntry = nullptr);
Q_SIGNALS: Q_SIGNALS:
void EntityAdded(class Entity* entity); void EntityAdded(class Entity* entity);
void EntityRemoved(class Entity* entity); void EntityRemoved(class Entity* entity);