#include "DataPanelManager.h" #include "DataPanel.h" #include "DataPanelFactory.h" #include "ui/DockWidget.h" #include "ui/DockTitleBar.h" #include "ui/MainWindow.h" #include "workspace/FileEntry.h" #include "common/SpdLogger.h" #include #include const QString DataPanelManager::PANEL_OBJECT_NAME_PREFIX = "DataPanel_"; DataPanelManager::DataPanelManager(MainWindow* mainWindow, QObject* parent) : QObject(parent) , mainWindow_(mainWindow) , currentWorkspace_(nullptr) { LOG_INFO("DataPanelManager initialized"); } DataPanelManager::~DataPanelManager() { ClearAllPanels(); LOG_INFO("DataPanelManager destroyed"); } void DataPanelManager::SetWorkspace(WorkSpace* workspace) { if (currentWorkspace_ == workspace) { return; } // Disconnect old workspace signal connections if (currentWorkspace_) { disconnect(currentWorkspace_, nullptr, this, nullptr); } currentWorkspace_ = workspace; // Connect new workspace signals if (currentWorkspace_) { connect(currentWorkspace_, &WorkSpace::FilesChanged, this, &DataPanelManager::OnFilesChanged); } // Update all panel types if (currentWorkspace_) { UpdatePanelsForType(FileEntryType::Curve); UpdatePanelsForType(FileEntryType::Surface); UpdatePanelsForType(FileEntryType::Table); UpdatePanelsForType(FileEntryType::Light); } else { ClearAllPanels(); } } int DataPanelManager::GetActivePanelCount(FileEntryType fileType) const { if (static_cast(fileType) == -1) { // Return total count return dataPanels_.size(); } // Count panels of specific type int count = 0; for (auto it = dataPanels_.begin(); it != dataPanels_.end(); ++it) { if (it.value()->GetFileType() == fileType) { count++; } } return count; } QList DataPanelManager::GetPanelsOfType(FileEntryType fileType) const { QList panels; for (auto it = dataPanels_.begin(); it != dataPanels_.end(); ++it) { if (it.value()->GetFileType() == fileType) { panels.append(it.value()); } } return panels; } void DataPanelManager::OnWorkspaceChanged(WorkSpace* workspace) { SetWorkspace(workspace); } void DataPanelManager::OnFilesChanged(FileEntryType type) { // Only respond to supported file types if (!DataPanelFactory::IsTypeSupported(type)) { return; } UpdatePanelsForType(type); } void DataPanelManager::OnPanelClosed() { DataPanel* panel = qobject_cast(sender()); if (panel) { RemovePanel(panel); } } void DataPanelManager::UpdatePanelsForType(FileEntryType fileType) { if (!currentWorkspace_) { ClearPanelsOfType(fileType); return; } // Get files of specified type from current workspace std::vector files = currentWorkspace_->GetFileEntries(fileType); // Limit to maximum panels per type const int maxPanels = qMin(static_cast(files.size()), GetMaxPanelCount()); // Find panels to remove (excess panels of this type) QStringList keysToRemove; for (auto it = dataPanels_.begin(); it != dataPanels_.end(); ++it) { DataPanel* panel = it.value(); if (panel->GetFileType() == fileType && panel->GetIndex() >= maxPanels) { keysToRemove.append(it.key()); } } // Remove excess panels for (const QString& key : keysToRemove) { RemovePanel(dataPanels_[key]); } // Create or update panels for (int i = 0; i < maxPanels; ++i) { const FileEntry& fileEntry = files[i]; QString filePath = currentWorkspace_->GetFileEntryAbsPath(fileEntry.type, i); QString panelKey = QString("%1_%2").arg(FileEntryTypeToString(fileType)).arg(i); if (dataPanels_.contains(panelKey)) { // Check if file path has changed DataPanel* existingPanel = dataPanels_[panelKey]; if (existingPanel->GetFilePath() != filePath) { // File path changed, recreate panel RemovePanel(existingPanel); CreateDataPanel(fileType, filePath); } else { // File path unchanged, refresh data existingPanel->RefreshPanel(); } } else { // Create new panel CreateDataPanel(fileType, filePath); } } } DataPanel* DataPanelManager::CreateDataPanel(FileEntryType fileType, const QString& filePath) { if (GetActivePanelCount(fileType) >= GetMaxPanelCount()) { LOG_WARN("Cannot create more {} panels, maximum count reached: {}", FileEntryTypeToString(fileType), GetMaxPanelCount()); return nullptr; } // Find next available index for this file type int index = FindNextAvailableIndex(fileType); QString panelKey = QString("%1_%2").arg(FileEntryTypeToString(fileType)).arg(index); // Create dock widget DockWidget* dockWidget = new DockWidget(mainWindow_); dockWidget->setObjectName(GeneratePanelObjectName(fileType, index)); // Set title bar DockTitleBar* titleBar = new DockTitleBar(dockWidget); dockWidget->SetDockWidgetTitleBar(titleBar); // Connect signals connect(dockWidget, &DockWidget::dockLocationChanged, this, [this](Qt::DockWidgetArea area) { // Handle dock location changes if needed }); // Add to main window mainWindow_->addDockWidget(Qt::RightDockWidgetArea, dockWidget); // Create panel using factory DataPanel* panel = DataPanelFactory::CreatePanel(fileType, index, filePath, dockWidget); if (!panel) { LOG_ERROR("Failed to create panel for type: {}", FileEntryTypeToString(fileType)); dockWidget->deleteLater(); return nullptr; } panel->InitUI(); dockWidget->setWidget(panel); // Set panel's dock widget reference panel->SetDockWidget(dockWidget); // Connect panel signals connect(panel, &DataPanel::PanelClosed, this, &DataPanelManager::OnPanelClosed); // Save references dataPanels_[panelKey] = panel; dockWidgets_[panelKey] = dockWidget; LOG_INFO("Created {} panel {} for file: {}", FileEntryTypeToString(fileType), index, filePath.toStdString()); return panel; } void DataPanelManager::RemovePanel(DataPanel* panel) { if (!panel) { return; } // Find panel key QString panelKey; for (auto it = dataPanels_.begin(); it != dataPanels_.end(); ++it) { if (it.value() == panel) { panelKey = it.key(); break; } } if (panelKey.isEmpty()) { return; } // Remove dock widget if (dockWidgets_.contains(panelKey)) { DockWidget* dockWidget = dockWidgets_[panelKey]; mainWindow_->removeDockWidget(dockWidget); dockWidget->deleteLater(); } // Remove from mappings dataPanels_.remove(panelKey); dockWidgets_.remove(panelKey); // Delete panel panel->deleteLater(); LOG_INFO("Removed {} panel {}", FileEntryTypeToString(panel->GetFileType()), panel->GetIndex()); } void DataPanelManager::ClearAllPanels() { // Get copy of all keys QStringList keys = dataPanels_.keys(); // Remove panels one by one for (const QString& key : keys) { RemovePanel(dataPanels_[key]); } LOG_INFO("Cleared all data panels"); } void DataPanelManager::ClearPanelsOfType(FileEntryType fileType) { QStringList keysToRemove; for (auto it = dataPanels_.begin(); it != dataPanels_.end(); ++it) { if (it.value()->GetFileType() == fileType) { keysToRemove.append(it.key()); } } for (const QString& key : keysToRemove) { RemovePanel(dataPanels_[key]); } LOG_INFO("Cleared all {} panels", FileEntryTypeToString(fileType)); } QString DataPanelManager::GeneratePanelObjectName(FileEntryType fileType, int index) const { return QString("%1%2_%3").arg(PANEL_OBJECT_NAME_PREFIX) .arg(FileEntryTypeToString(fileType)) .arg(index); } int DataPanelManager::FindNextAvailableIndex(FileEntryType fileType) const { int index = 0; QString baseKey = QString("%1_").arg(FileEntryTypeToString(fileType)); while (dataPanels_.contains(baseKey + QString::number(index))) { index++; } return index; }