add delete file entity

This commit is contained in:
brige 2025-11-09 13:24:44 +08:00
parent 6e63251b27
commit 5e6b554f90
4 changed files with 123 additions and 6 deletions

View File

@ -4,6 +4,7 @@
#include <QUuid>
#include <QVariant>
#include <QMenu>
#include <QMessageBox>
#include <osgEarthUtil/EarthManipulator>
@ -144,14 +145,30 @@ void ModelTreeWidget::OnEntityRemoved(Entity* entity) {
void ModelTreeWidget::contextMenuEvent(QContextMenuEvent* event) {
QTreeWidgetItem* item = itemAt(event->pos());
if (nullptr != item) {
QVariant value = item->data(0, E_Entity);
if (!value.isValid()) {
LOG_WARN("unknown data E_Entity");
// Try entity menu first
QVariant valueEntity = item->data(0, E_Entity);
if (valueEntity.isValid()) {
Entity* entity = valueEntity.value<Entity*>();
PopupEntityMenu(event, entity);
return;
}
Entity* entity = value.value<Entity*>();
PopupEntityMenu(event, entity);
// Then file entry menu
QVariant valueEntry = item->data(0, E_FileEntry);
if (valueEntry.isValid()) {
auto* entry = valueEntry.value<FileEntry*>();
QMenu menu(this);
QAction* deleteAction = new QAction(tr("Delete File"), this);
menu.addAction(deleteAction);
connect(deleteAction, &QAction::triggered, [this, entry]() {
OnDeleteFileEntry(entry);
});
menu.exec(event->globalPos());
return;
}
// Otherwise, show nothing for group/root
return;
} else {
return;
QMenu menu(this);
@ -301,6 +318,37 @@ void ModelTreeWidget::OnDeleteEntity(Entity* entity) {
entity->Destory();
}
void ModelTreeWidget::OnDeleteFileEntry(FileEntry* entry) {
if (!entry) {
LOG_WARN("OnDeleteFileEntry: entry is nullptr");
return;
}
auto workspace = WorkSpaceManager::Get().GetCurrent();
if (!workspace) {
LOG_WARN("OnDeleteFileEntry: workspace is nullptr");
return;
}
// Confirm deletion of the workspace-managed item (non-destructive to physical file)
auto res = QMessageBox::question(this, tr("Confirm"), tr("Delete this file entry from workspace?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
if (res != QMessageBox::Yes) {
return;
}
bool ok = workspace->RemoveFileEntry(entry->GetType(), entry);
if (!ok) {
QMessageBox::warning(this, tr("Prompt"), tr("Delete failed"));
return;
}
// Clear property panel to avoid showing stale info of deleted item
QVariant v;
v.setValue(workspace);
emit WorkSpaceChange(v);
}
void ModelTreeWidget::PopupEntityMenu(QContextMenuEvent* event, Entity* entity) {
QMenu menu(this);

View File

@ -39,6 +39,7 @@ protected:
class SceneComponent* OnAddComponent(const QString& typeName, class Entity* entity);
void OnDeleteEntity(class Entity* entity);
void OnDeleteFileEntry(class FileEntry* entry);
void PopupEntityMenu(QContextMenuEvent* event, class Entity* entity);

View File

@ -381,3 +381,66 @@ void WorkSpace::NotifyFileEntryUpdated(FileEntryType type, std::shared_ptr<FileE
++filesSeq_;
emit FilesChanged(type, fileEntry);
}
// 删除指定指针的文件条目(不删除物理文件,仅移出工作空间管理)
bool WorkSpace::RemoveFileEntry(FileEntryType type, FileEntry* entry) {
if (!entry) {
LOG_WARN("RemoveFileEntry: entry is nullptr");
return false;
}
auto it = files_.find(type);
if (it == files_.end()) {
LOG_WARN("RemoveFileEntry: type not found: {}", FileEntryTypeToString(type));
return false;
}
auto& vec = it->second;
auto pos = std::find_if(vec.begin(), vec.end(), [entry](const std::shared_ptr<FileEntry>& sp){ return sp.get() == entry; });
if (pos == vec.end()) {
LOG_WARN("RemoveFileEntry: entry not found in type: {}", FileEntryTypeToString(type));
return false;
}
vec.erase(pos);
++filesSeq_;
emit FilesChanged(type, nullptr);
LOG_INFO("Removed file entry of type: {}", FileEntryTypeToString(type));
return true;
}
// 按索引删除文件条目
bool WorkSpace::RemoveFileEntryAt(FileEntryType type, int index) {
auto it = files_.find(type);
if (it == files_.end()) {
LOG_WARN("RemoveFileEntryAt: type not found: {}", FileEntryTypeToString(type));
return false;
}
auto& vec = it->second;
if (index < 0 || index >= static_cast<int>(vec.size())) {
LOG_WARN("RemoveFileEntryAt: invalid index {} for type {}", index, FileEntryTypeToString(type));
return false;
}
vec.erase(vec.begin() + index);
++filesSeq_;
emit FilesChanged(type, nullptr);
LOG_INFO("Removed file entry at index {} for type {}", index, FileEntryTypeToString(type));
return true;
}
// 按文件名删除文件条目(匹配工作空间内记录的文件名)
bool WorkSpace::RemoveFileEntryByName(FileEntryType type, const QString& fileName) {
auto it = files_.find(type);
if (it == files_.end()) {
LOG_WARN("RemoveFileEntryByName: type not found: {}", FileEntryTypeToString(type));
return false;
}
auto& vec = it->second;
auto pos = std::find_if(vec.begin(), vec.end(), [&fileName](const std::shared_ptr<FileEntry>& sp){ return sp && sp->GetFileName() == fileName; });
if (pos == vec.end()) {
LOG_WARN("RemoveFileEntryByName: file not found: {}", fileName.toUtf8().constData());
return false;
}
vec.erase(pos);
++filesSeq_;
emit FilesChanged(type, nullptr);
LOG_INFO("Removed file entry by name: {} for type {}", fileName.toUtf8().constData(), FileEntryTypeToString(type));
return true;
}

View File

@ -68,12 +68,17 @@ public:
// New unified file entry management
FileEntryResult SetFileEntry(std::shared_ptr<FileEntry> fileEntry, bool is_copy = true);
std::vector<std::shared_ptr<FileEntry>> GetFileEntries(FileEntryType type) const;
std::vector<std::shared_ptr<FileEntry>> GetFileEntries(FileEntryType type) const;
// Manage grouped file entries
bool SetFileEntryCount(FileEntryType type, int count);
QString GetFileEntryAbsPath(FileEntryType type, int index) const;
// Remove file entries
bool RemoveFileEntry(FileEntryType type, class FileEntry* entry);
bool RemoveFileEntryAt(FileEntryType type, int index);
bool RemoveFileEntryByName(FileEntryType type, const QString& fileName);
inline void SetHomeViewpoint(const osgEarth::Viewpoint& viewpoint) {
homeViewpoint_ = viewpoint;
homeViewpoint_.setHeading(0.0); // Ensure heading is set to 0.0