diff --git a/src/translations/Dyt_zh_CN.ts b/src/translations/Dyt_zh_CN.ts index eae835fa..114ec4c7 100644 --- a/src/translations/Dyt_zh_CN.ts +++ b/src/translations/Dyt_zh_CN.ts @@ -14,198 +14,198 @@ - + File Path: - + Select curve data file... - + ... - + File Name: - - + + - - + File Size: - + Chart Properties - + Chart Name: - + Chart 1 - + Enter chart name... - + Chart Type: - + X Axis Title: - + Enter X axis title... - + Y Axis Title: - + Enter Y axis title... - + Time: - + Axis Range Settings - + X Tick Count: - + X Min: - + Y Max: - + Y Min: - + X Max: - + Y Tick Count: - + Curve Management - + Curves: - + Add Curve - + Remove - + Selected Curve Properties - + Curve Name: - + Enter curve name... - + Curve Color: - + Select Color - + background-color: rgb(255, 0, 0); border: 1px solid black; - + Data Start: - + Data Stop: - + X Value: - + Y Value: - + Add File - + Cancel @@ -406,166 +406,186 @@ - + File Path: - + Select light data file... - + ... - + File Name: - - - + + + - - + File Size: - + + Chart Properties + + + + + Chart Names: + + + + Color Properties - + Open Color: - - + + Select Color - + background-color: rgb(0, 255, 0); border: 1px solid black; - + Close Color: - + background-color: rgb(255, 0, 0); border: 1px solid black; - + Light Management - + Lights: - + Add Light Row - + Remove - + Selected Light Properties - + Light Names: - + Enter light names (comma separated)... - - Light Data: + + Light Datas: - + Enter data values (comma separated integers)... - + Edit Data - + Row Index: - + Add File - + Cancel - - + + Warning + + + + + Please enter a Chart name. + + + + + Error - + Unable to get current workspace - + Curve file count has reached the limit (9 files) - + File already exists - + File copy failed - + Invalid file - + Failed to add file @@ -656,6 +676,351 @@ + + AddPolarDlg + + + Add Polar + + + + + File Selection + + + + + File Path: + + + + + Select curve data file... + + + + + ... + + + + + File Name: + + + + + + - + + + + + File Size: + + + + + Angular Axis + + + + + + Title: + + + + + + Enter axis title... + + + + + + Min: + + + + + + Max: + + + + + + Count: + + + + + + Unit: + + + + + + Enter axis Unit... + + + + + Radial Axis + + + + + Curve Management + + + + + Curves: + + + + + Add + + + + + Remove + + + + + Selected Curve Properties + + + + + Name: + + + + + Enter curve name... + + + + + Color: + + + + + Select Color + + + + + background-color: rgb(255, 0, 0); border: 1px solid black; + + + + + Angular: + + + + + Radial: + + + + + X Value: + + + + + Y Value: + + + + + Add File + + + + + Cancel + + + + + Chart Properties + + + + + Time: + + + + + Chart Name: + + + + + Chart 1 + + + + + Enter chart name... + + + + + AddPolarFileDlg + + + + + + + + + + + + + + + + + Validation Error + + + + + Please select a data file. + + + + + Selected file does not exist. + + + + + Selected file is not readable. Please check file permissions. + + + + + File is too large (over 100MB). Please select a smaller file. + + + + + At least one curve must be defined. + + + + + Curve %1 name cannot be empty. + + + + + Curve name '%1' is duplicated. Please use different names. + + + + + Curve name '%1' is too long. Please limit to 50 characters. + + + + + Curve '%1' X value is out of range. Please ensure it is between -1000000 and 1000000. + + + + + Curve '%1' Y value is out of range. Please ensure it is between -1000000 and 1000000. + + + + + Chart name cannot be empty. + + + + + Chart name is too long. Please limit to 100 characters. + + + + + Angular axis minimum value must be less than maximum value. + + + + + Radial axis minimum value must be less than maximum value. + + + + + Time parameter cannot be negative. + + + + + Curve %1 + + + + + + + Error + + + + + Failed to create file entry + + + + + Unable to get current workspace + + + + + Curve file count has reached the limit (9 files) + + + + + File already exists + + + + + File copy failed + + + + + Invalid file + + + + + Failed to add file + + + AddSurfaceFileDlg @@ -669,237 +1034,280 @@ - + Select surface data file... - + Browse... - + Chart Properties - + X Axis Title: - + Y Axis Title: - + Z Axis Title: - + Time Parameter: - + X Range: - - - + + + to - + X Count: - + Y Range: - + Y Count: - + Z Range: - + Z Count: - + Surface Management - + Add Surface - + Remove - + Surface Properties - + + Name: - + Color: - + Select Color - + Start Point: - + End Point: - + + X-Map: + + + + + + + x + + + + + + + y + + + + + + + z + + + + + Y-Map: + + + + + Z-Map: + + + + Data Format Parameters - + X Column: - + Y Column: - + Z Column: - + Separator: - + , - + X Grid Size: - + Y Grid Size: - + Has Header Row - + Surface Data Files (*.txt *.dat *.csv);;All Files (*.*) - - Select Surface Data File + + Add Surface Dialog - - + + + Warning - + Please add at least one surface. - + Please fill in all axis titles. - + Select Surface Color - - - + + Please enter a Surface name. + + + + + + Error - + Failed to create surface file entry. - + Unable to get current workspace - + Surface file count has reached the limit (9 files) - + File already exists - + File copy failed - + Invalid file - + Failed to add file @@ -917,276 +1325,270 @@ - + File Path: - + Select table data file... - + ... - + File Name: - - + + - - + File Size: - + Basic Information - + Enter table name... - + Table Name: - + Time Parameter: - + Table Headers Configuration - + File has header row - + Headers (comma-separated): - + e.g., Time, Value1, Value2, Value3... - + Tip: Headers will be auto-detected if file has header row - + Parsing Parameters - + Skip Rows: - + Auto-detect parameters - + Encoding: - + UTF-8 - + GBK - + ASCII - + ISO-8859-1 - + Curves Configuration - + Add Curve - + Remove Curve - + Curve Properties - + Name: - + Enter curve name... - + Color: - + Select Color - + Data: - + Enter data values (comma-separated)... - + Data values must match the number of headers - + Add File - + Cancel - - - - + + - + + Warning - + Please configure table headers first. - + Select Curve Color - + Please configure table headers. - - Please add at least one curve. - - - - + Curve %1 name cannot be empty. - + Curve '%1' data cannot be empty. - + Curve '%1' data count (%2) doesn't match headers count (%3). - + Please enter a table name. - - - + + + Error - + Failed to create table file entry. - + Unable to get current workspace - + Table file count has reached the limit - + File already exists - + File copy failed - + Invalid file - + Failed to add file @@ -1505,6 +1907,11 @@ new light file + + + new polar file + + FitCurveChartView @@ -1782,27 +2189,22 @@ - - PresetModelToolBox - - - - + Ships - + Satellites - + Missiles - + Jammers @@ -1892,127 +2294,70 @@ - + Open Workspace - - + + Dyt Files (*.dyt) - - - - - - - - - - - - - - - - - - - - - + + + + + + prompt - - - - - + + + + + + please create workspace first - + Save Workspace - - - - - Error - - - - - - - - Failed to create file entry - - - - - - - - up to 9 files allowed for this type - - - - - - - - file already added for this type - - - - - - - - copy file failed - - - - - - - - invalid file - - - - - + + Curve[%1] - - + + Surface[%1] - - + + Table[%1] - - + + Light[%1] + + + Polar[%1] + + QtBoolEdit @@ -2085,48 +2430,48 @@ QtConeWaveComponentManager - - + + ConeWaveComponent - + Height - + Radius - + waveCount - + waveSpeed - + baseColor - + waveColor - + ringBrightAlpha - + ringDarkAlpha @@ -2232,28 +2577,28 @@ QtDashedLineComponentManager - - + + DashedLineComponent - + Start - + End - + Radius - + Color @@ -2269,17 +2614,17 @@ QtEntityPropertyManager - + Name - + Visible - + Transform @@ -2361,13 +2706,13 @@ QtMeshComponetManager - - + + MeshComponent - + Mesh @@ -2416,13 +2761,13 @@ QtPathComponentManager - - + + PathComponent - + Path @@ -2672,95 +3017,100 @@ QtWorkspacePropertyManager - + Name - + Description - + Timestep - + SimMatlab - + MatlabParam - + WavePath - + ReportPath - + RDPath - + CommondPath - + Count - + Curve[%1] - + Surface[%1] - + Table[%1] - + Light[%1] - + Curves - + Surfaces - + Tables - + Lights + + + Polars + + SignalIndicatorLampUI @@ -2773,22 +3123,22 @@ SimuRunMenu - + no workspace - + no commands - + Commands - + unnamed @@ -2874,53 +3224,53 @@ - + Name - + input workspace name - + Path - + select workspace save path - - + + ... - + commond Path - + select commond file path - + describe - + Sure - + Cancel diff --git a/src/ui/ModelBrowser/ModelInfo.h b/src/ui/ModelBrowser/ModelInfo.h new file mode 100644 index 00000000..e6582e44 --- /dev/null +++ b/src/ui/ModelBrowser/ModelInfo.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include + +/** + * @brief Model information structure + * + * Contains all information for a single preset model, including name, display name, + * description, mesh file path, icon path, and enabled status. + */ +struct ModelInfo { + QString name; ///< Model name (unique identifier) + QString displayName; ///< Display name (for UI display) + QString description; ///< Model description + QString meshFile; ///< 3D mesh file path + QString icon; ///< Icon file path + bool enabled; ///< Whether this model is enabled + + /** + * @brief Default constructor + * Model is enabled by default + */ + ModelInfo() : enabled(true) {} + + /** + * @brief Constructor with parameters + */ + ModelInfo(const QString& name, const QString& displayName, const QString& description, + const QString& meshFile, const QString& icon, bool enabled = true) + : name(name), displayName(displayName), description(description), + meshFile(meshFile), icon(icon), enabled(enabled) {} +}; + +/** + * @brief Model category structure + * + * Contains information for a model category, such as ships, satellites, missiles, jammers, etc. + * Each category contains multiple specific models. + */ +struct ModelCategory { + QString name; ///< Category name (unique identifier) + QString displayName; ///< Display name (for UI display) + QString icon; ///< Category icon path + QVector models; ///< All models in this category +}; \ No newline at end of file diff --git a/src/ui/ModelBrowser/PresetModelConfigParser.cpp b/src/ui/ModelBrowser/PresetModelConfigParser.cpp index 2b02c3c0..ffecfe72 100644 --- a/src/ui/ModelBrowser/PresetModelConfigParser.cpp +++ b/src/ui/ModelBrowser/PresetModelConfigParser.cpp @@ -102,6 +102,7 @@ bool PresetModelConfigParser::ParseXmlFile(const QString& filePath) const char* modelDisplayName = modelElement->Attribute("displayName"); const char* description = modelElement->Attribute("description"); const char* meshFile = modelElement->Attribute("meshFile"); + const char* modelIcon = modelElement->Attribute("icon"); const char* enabled = modelElement->Attribute("enabled"); if (!modelName) { @@ -114,6 +115,7 @@ bool PresetModelConfigParser::ParseXmlFile(const QString& filePath) model.displayName = modelDisplayName ? QString::fromUtf8(modelDisplayName) : model.name; model.description = description ? QString::fromUtf8(description) : ""; model.meshFile = meshFile ? QString::fromUtf8(meshFile) : ""; + model.icon = modelIcon ? QString::fromUtf8(modelIcon) : ""; model.enabled = enabled ? (strcmp(enabled, "true") == 0) : true; category.models.append(model); diff --git a/src/ui/ModelBrowser/PresetModelConfigParser.h b/src/ui/ModelBrowser/PresetModelConfigParser.h index ffa556c2..a61f1d27 100644 --- a/src/ui/ModelBrowser/PresetModelConfigParser.h +++ b/src/ui/ModelBrowser/PresetModelConfigParser.h @@ -3,24 +3,7 @@ #include #include #include -#include - -struct ModelInfo { - QString name; - QString displayName; - QString description; - QString meshFile; - bool enabled; - - ModelInfo() : enabled(true) {} -}; - -struct ModelCategory { - QString name; - QString displayName; - QString icon; - QVector models; -}; +#include "ModelInfo.h" class PresetModelConfigParser { diff --git a/src/ui/ModelBrowser/PresetModelListWidget.cpp b/src/ui/ModelBrowser/PresetModelListWidget.cpp new file mode 100644 index 00000000..3942decf --- /dev/null +++ b/src/ui/ModelBrowser/PresetModelListWidget.cpp @@ -0,0 +1,144 @@ +#include "ui/ModelBrowser/PresetModelListWidget.h" + +#include +#include +#include +#include + +#include "common/RecourceHelper.h" +#include "common/SpdLogger.h" + +PresetModelListWidget::PresetModelListWidget(QWidget* parent) + : QListWidget(parent) +{ + setDragEnabled(true); + setDragDropMode(QAbstractItemView::DragOnly); + + // Configure list widget for icon-text vertical layout + setViewMode(QListView::IconMode); + setResizeMode(QListView::Adjust); + setMovement(QListView::Static); + setGridSize(QSize(100, 80)); // Width x Height for each item + setIconSize(QSize(48, 48)); // Icon size + setSpacing(5); // Spacing between items +} + +void PresetModelListWidget::startDrag(Qt::DropActions supportedActions) { + QListWidgetItem* item = currentItem(); + if (nullptr == item) { + return; + } + + QString modelType = property("modelType").toString(); + QString modelName = item->data(Qt::UserRole).toString(); + if (modelName.isEmpty()) { + modelName = item->text(); // Fallback to item text + } + + QMimeData* mimeData = new QMimeData; + + QString dragData = QString("%1|%2").arg(modelType, modelName); + mimeData->setData("application/x-preset-model", dragData.toUtf8()); + + // Create drag object + QDrag* drag = new QDrag(this); + drag->setMimeData(mimeData); + + // Create drag pixmap with icon on top and text below + const int iconSize = 32; + const int textHeight = 20; + const int totalWidth = 80; + const int totalHeight = iconSize + textHeight + 5; // 5px spacing between icon and text + + QPixmap pixmap(totalWidth, totalHeight); + pixmap.fill(Qt::transparent); + + QPainter painter(&pixmap); + painter.setRenderHint(QPainter::Antialiasing); + + // Draw semi-transparent background + painter.setBrush(QColor(255, 255, 255, 80)); // White with 70% opacity + painter.setPen(QPen(QColor(200, 200, 200, 200), 1)); // Light gray border + painter.drawRoundedRect(2, 2, totalWidth - 4, totalHeight - 4, 4, 4); + + // Draw icon at the top center + QPixmap iconPixmap = item->icon().pixmap(iconSize, iconSize); + if (!iconPixmap.isNull()) { + int iconX = (totalWidth - iconSize) / 2; + painter.drawPixmap(iconX, 0, iconPixmap); + } else { + // Draw a default placeholder icon + int iconX = (totalWidth - iconSize) / 2; + painter.setPen(QPen(Qt::gray, 2)); + painter.setBrush(Qt::lightGray); + painter.drawRect(iconX, 0, iconSize, iconSize); + painter.setPen(Qt::black); + painter.drawText(iconX, 0, iconSize, iconSize, Qt::AlignCenter, "?"); + } + + // Draw text below the icon + painter.setPen(Qt::black); + QFont font = painter.font(); + font.setPointSize(8); + painter.setFont(font); + + QRect textRect(0, iconSize + 5, totalWidth, textHeight); + painter.drawText(textRect, Qt::AlignCenter | Qt::TextWordWrap, item->text()); + drag->setPixmap(pixmap); + + // Set hot spot to the center of the icon (not the entire pixmap) + int hotSpotX = totalWidth / 2; + int hotSpotY = iconSize / 2; // Center of the icon part only + drag->setHotSpot(QPoint(hotSpotX, hotSpotY)); + + // Execute drag + drag->exec(Qt::CopyAction); + +} + +void PresetModelListWidget::setModelType(const QString& modelType) { + modelType_ = modelType; + setProperty("modelType", modelType_); +} + +QString PresetModelListWidget::getModelType() const { + return modelType_; +} + +void PresetModelListWidget::setModelList(const QVector& models) { + modelList_ = models; + + clear(); + + for (const ModelInfo& modelInfo : models) { + if (!modelInfo.enabled) continue; // Skip disabled models + + QListWidgetItem* item = new QListWidgetItem(modelInfo.displayName.isEmpty() ? modelInfo.name : modelInfo.displayName); + item->setFlags(item->flags() | Qt::ItemIsDragEnabled); + + // Use icon from ModelInfo if available + if (!modelInfo.icon.isEmpty()) { + QString presetsPath = QString("%1/%2").arg(RecourceHelper::Get().GetResourcesPath(), modelInfo.icon); + QIcon icon(presetsPath); + item->setIcon(icon); + } else { + // Create a default icon if no icon is specified + QPixmap pixmap(48, 48); + pixmap.fill(Qt::lightGray); + QPainter painter(&pixmap); + painter.setPen(Qt::black); + painter.drawRect(0, 0, 47, 47); + painter.drawText(pixmap.rect(), Qt::AlignCenter, "?"); + item->setIcon(QIcon(pixmap)); + } + + // Store model name as simple string + item->setData(Qt::UserRole, modelInfo.name); + + addItem(item); + } +} + +QVector PresetModelListWidget::getModelList() const { + return modelList_; +} diff --git a/src/ui/ModelBrowser/PresetModelListWidget.h b/src/ui/ModelBrowser/PresetModelListWidget.h new file mode 100644 index 00000000..408fec71 --- /dev/null +++ b/src/ui/ModelBrowser/PresetModelListWidget.h @@ -0,0 +1,23 @@ +#include +#include +#include "ui/ModelBrowser/ModelInfo.h" + +class PresetModelListWidget : public QListWidget +{ + Q_OBJECT +public: + explicit PresetModelListWidget(QWidget* parent = nullptr); + + void setModelType(const QString& modelType); + QString getModelType() const; + + void setModelList(const QVector& models); + QVector getModelList() const; + +protected: + void startDrag(Qt::DropActions supportedActions); + +private: + QString modelType_; + QVector modelList_; +}; diff --git a/src/ui/ModelBrowser/PresetModelPanel.cpp b/src/ui/ModelBrowser/PresetModelPanel.cpp index 01d8d18a..dcafb751 100644 --- a/src/ui/ModelBrowser/PresetModelPanel.cpp +++ b/src/ui/ModelBrowser/PresetModelPanel.cpp @@ -8,11 +8,14 @@ #include #include #include +#include #include #include #include #include +#include +#include "common/RecourceHelper.h" #include "common/SpdLogger.h" #include "ui/DockTitleBar.h" #include "ui/DockWidget.h" @@ -23,6 +26,7 @@ PresetModelPanel::PresetModelPanel(QWidget *parent) : QWidget(parent) , ui(new Ui::PresetModelPanel) + , dragSourceWidget_(nullptr) { ui->setupUi(this); InitUI(); @@ -50,13 +54,14 @@ void PresetModelPanel::AttachDock(DockWidget* dockWidget) void PresetModelPanel::InitUI() { // Try to load model data from configuration files - if (m_configParser.LoadAllConfigs("workspace/presets")) { + QString presetsPath = QString("%1/presets").arg(RecourceHelper::Get().GetResourcesPath()); + if (configParser_.LoadAllConfigs(presetsPath)) { // Successfully loaded from configuration files LoadModelsFromConfig(); } else { // Failed to load configuration files, use hardcoded defaults as fallback LOG_WARN("Failed to load preset models from config files, using hardcoded defaults. Error: {}", - m_configParser.GetLastError().toStdString()); + configParser_.GetLastError().toStdString()); LoadDefaultModels(); } } @@ -64,161 +69,175 @@ void PresetModelPanel::InitUI() void PresetModelPanel::LoadModelsFromConfig() { // Load ship models - QStringList shipModels = m_configParser.GetModelNames("Ship"); - if (!shipModels.isEmpty()) { - PopulateModelList(ui->shipList, "Ship", shipModels); + ModelCategory shipCategory = configParser_.GetCategory("Ship"); + if (!shipCategory.models.isEmpty()) { + ui->shipList->setModelType("Ship"); + ui->shipList->setModelList(shipCategory.models); } // Load satellite models - QStringList satelliteModels = m_configParser.GetModelNames("Satellite"); - if (!satelliteModels.isEmpty()) { - PopulateModelList(ui->satelliteList, "Satellite", satelliteModels); + ModelCategory satelliteCategory = configParser_.GetCategory("Satellite"); + if (!satelliteCategory.models.isEmpty()) { + ui->satelliteList->setModelType("Satellite"); + ui->satelliteList->setModelList(satelliteCategory.models); } // Load missile models - QStringList missileModels = m_configParser.GetModelNames("Missile"); - if (!missileModels.isEmpty()) { - PopulateModelList(ui->missileList, "Missile", missileModels); + ModelCategory missileCategory = configParser_.GetCategory("Missile"); + if (!missileCategory.models.isEmpty()) { + ui->missileList->setModelType("Missile"); + ui->missileList->setModelList(missileCategory.models); } // Load jammer models - QStringList jammerModels = m_configParser.GetModelNames("Jammer"); - if (!jammerModels.isEmpty()) { - PopulateModelList(ui->jammerList, "Jammer", jammerModels); + ModelCategory jammerCategory = configParser_.GetCategory("Jammer"); + if (!jammerCategory.models.isEmpty()) { + ui->jammerList->setModelType("Jammer"); + ui->jammerList->setModelList(jammerCategory.models); } } void PresetModelPanel::LoadDefaultModels() { // Use hardcoded default models as fallback mechanism - QStringList shipModels = { - "Destroyer", - "Aircraft Carrier", - "Frigate", - "Submarine" + QVector shipModels = { + {"destroyer", "Destroyer", "Naval destroyer vessel", "", ":/icons/ship.png", true}, + {"aircraft_carrier", "Aircraft Carrier", "Large naval vessel", "", ":/icons/ship.png", true}, + {"frigate", "Frigate", "Fast naval vessel", "", ":/icons/ship.png", true}, + {"submarine", "Submarine", "Underwater vessel", "", ":/icons/ship.png", true} }; - PopulateModelList(ui->shipList, "Ship", shipModels); + ui->shipList->setModelType("Ship"); + ui->shipList->setModelList(shipModels); - QStringList satelliteModels = { - "Communication Satellite", - "Weather Satellite", - "GPS Satellite", - "Spy Satellite" + QVector satelliteModels = { + {"comm_satellite", "Communication Satellite", "Communication satellite", "", ":/icons/satellite.png", true}, + {"weather_satellite", "Weather Satellite", "Weather monitoring satellite", "", ":/icons/satellite.png", true}, + {"gps_satellite", "GPS Satellite", "GPS navigation satellite", "", ":/icons/satellite.png", true}, + {"spy_satellite", "Spy Satellite", "Reconnaissance satellite", "", ":/icons/satellite.png", true} }; - PopulateModelList(ui->satelliteList, "Satellite", satelliteModels); + ui->satelliteList->setModelType("Satellite"); + ui->satelliteList->setModelList(satelliteModels); - QStringList missileModels = { - "Cruise Missile", - "Ballistic Missile", - "Anti-Ship Missile", - "Surface-to-Air Missile" + QVector missileModels = { + {"cruise_missile", "Cruise Missile", "Long-range cruise missile", "", ":/icons/missile.png", true}, + {"ballistic_missile", "Ballistic Missile", "Ballistic missile", "", ":/icons/missile.png", true}, + {"anti_ship_missile", "Anti-Ship Missile", "Anti-ship missile", "", ":/icons/missile.png", true}, + {"sam_missile", "Surface-to-Air Missile", "Surface-to-air missile", "", ":/icons/missile.png", true} }; - PopulateModelList(ui->missileList, "Missile", missileModels); + ui->missileList->setModelType("Missile"); + ui->missileList->setModelList(missileModels); - QStringList jammerModels = { - "Electronic Jammer", - "Communication Jammer", - "Radar Jammer", - "GPS Jammer" + QVector jammerModels = { + {"electronic_jammer", "Electronic Jammer", "Electronic warfare jammer", "", ":/icons/jammer.png", true}, + {"comm_jammer", "Communication Jammer", "Communication jammer", "", ":/icons/jammer.png", true}, + {"radar_jammer", "Radar Jammer", "Radar jamming device", "", ":/icons/jammer.png", true}, + {"gps_jammer", "GPS Jammer", "GPS jamming device", "", ":/icons/jammer.png", true} }; - PopulateModelList(ui->jammerList, "Jammer", jammerModels); + ui->jammerList->setModelType("Jammer"); + ui->jammerList->setModelList(jammerModels); } -void PresetModelPanel::PopulateModelList(QListWidget* listWidget, const QString& modelType, const QStringList& models) -{ - if (!listWidget) return; +// void PresetModelPanel::OnModelItemDoubleClicked(QListWidgetItem* item) +// { +// if (!item) return; - // Set the model type as a property for later use - listWidget->setProperty("modelType", modelType); +// // Get the list widget that contains this item +// QListWidget* listWidget = item->listWidget(); +// if (!listWidget) return; - for (const QString& model : models) { - QListWidgetItem* item = new QListWidgetItem(model); - item->setFlags(item->flags() | Qt::ItemIsDragEnabled); +// QString modelType = listWidget->property("modelType").toString(); + +// // Get model name from stored data +// QString modelName = item->data(Qt::UserRole).toString(); +// if (modelName.isEmpty()) { +// modelName = item->text(); // Fallback to display text +// } + +// LOG_INFO("Model double-clicked: {} of type {}", qPrintable(modelName), qPrintable(modelType)); + +// // Emit signal for model selection +// emit ModelDropped(modelType, modelName); +// } + +// bool PresetModelPanel::eventFilter(QObject* obj, QEvent* event) +// { +// QListWidget* listWidget = qobject_cast(obj); +// if (!listWidget) { +// return QWidget::eventFilter(obj, event); +// } + +// if (event->type() == QEvent::MouseButtonPress) { +// QMouseEvent* mouseEvent = static_cast(event); +// if (mouseEvent->button() == Qt::LeftButton) { +// dragStartPosition_ = mouseEvent->pos(); +// dragSourceWidget_ = listWidget; +// } +// } else if (event->type() == QEvent::MouseMove) { +// QMouseEvent* mouseEvent = static_cast(event); +// if (!(mouseEvent->buttons() & Qt::LeftButton)) { +// return QWidget::eventFilter(obj, event); +// } - if (modelType == "Ship") { - item->setIcon(QIcon(":/icons/ship.png")); - } else if (modelType == "Satellite") { - item->setIcon(QIcon(":/icons/satellite.png")); - } else if (modelType == "Missile") { - item->setIcon(QIcon(":/icons/missile.png")); - } else if (modelType == "Jammer") { - item->setIcon(QIcon(":/icons/jammer.png")); - } +// if ((mouseEvent->pos() - dragStartPosition_).manhattanLength() < QApplication::startDragDistance()) { +// return QWidget::eventFilter(obj, event); +// } - listWidget->addItem(item); - } +// QListWidgetItem* item = listWidget->itemAt(dragStartPosition_); +// if (!item) { +// return QWidget::eventFilter(obj, event); +// } + +// QString modelType = listWidget->property("modelType").toString(); + +// // Get model name from stored data +// QString modelName = item->data(Qt::UserRole).toString(); +// if (modelName.isEmpty()) { +// modelName = item->text(); // Fallback to item text +// } + +// // Create mime data +// QMimeData* mimeData = new QMimeData; +// QString dragData = QString("%1|%2").arg(modelType, modelName); +// mimeData->setData("application/x-preset-model", dragData.toUtf8()); + +// // Create drag object +// QDrag* drag = new QDrag(this); +// drag->setMimeData(mimeData); + +// // Set drag pixmap (icon or text) +// QPixmap pixmap(item->icon().pixmap(32, 32)); +// if (pixmap.isNull()) { +// pixmap = QPixmap(100, 30); +// pixmap.fill(Qt::transparent); +// QPainter painter(&pixmap); +// painter.setPen(Qt::black); +// painter.drawText(pixmap.rect(), Qt::AlignCenter, item->text()); +// } +// drag->setPixmap(pixmap); + +// // Execute drag +// Qt::DropAction dropAction = drag->exec(Qt::CopyAction); +// Q_UNUSED(dropAction); + +// return true; +// } - connect(listWidget, &QListWidget::itemDoubleClicked, this, &PresetModelPanel::OnModelItemDoubleClicked); -} +// return QWidget::eventFilter(obj, event); +// } -void PresetModelPanel::SetupDragAndDrop(QListWidget* listWidget) -{ - listWidget->setDragDropMode(QAbstractItemView::DragOnly); - listWidget->setDefaultDropAction(Qt::CopyAction); -} +// // DraggableListWidget implementation +// DraggableListWidget::DraggableListWidget(const QString& modelType, QWidget* parent) +// : QListWidget(parent), modelType_(modelType) +// { +// setProperty("modelType", modelType); +// } -void PresetModelPanel::OnModelItemDoubleClicked(QListWidgetItem* item) -{ - if (!item) return; - - QListWidget* listWidget = item->listWidget(); - if (!listWidget) return; - - QString modelType = listWidget->property("modelType").toString(); - QString modelName = item->text(); - - emit ModelDropped(modelType, modelName); -} +// void DraggableListWidget::mousePressEvent(QMouseEvent* event) +// { +// QListWidget::mousePressEvent(event); +// } -// DraggableListWidget implementation -DraggableListWidget::DraggableListWidget(const QString& modelType, QWidget* parent) - : QListWidget(parent), modelType_(modelType) -{ - setProperty("modelType", modelType); -} - -void DraggableListWidget::mousePressEvent(QMouseEvent* event) -{ - if (event->button() == Qt::LeftButton) { - dragStartPosition_ = event->pos(); - } - QListWidget::mousePressEvent(event); -} - -void DraggableListWidget::mouseMoveEvent(QMouseEvent* event) { - if (!(event->buttons() & Qt::LeftButton)) { - return; - } - - if ((event->pos() - dragStartPosition_).manhattanLength() < QApplication::startDragDistance()) { - return; - } - - QListWidgetItem* item = itemAt(dragStartPosition_); - if (!item) { - return; - } - - QDrag* drag = new QDrag(this); - QMimeData* mimeData = new QMimeData; - - QString modelType = this->property("modelType").toString(); - QString modelName = item->text(); - QString dragData = QString("%1|%2").arg(modelType, modelName); - - mimeData->setData("application/x-preset-model", dragData.toUtf8()); - drag->setMimeData(mimeData); - - QPixmap pixmap(item->icon().pixmap(32, 32)); - if (pixmap.isNull()) { - pixmap = QPixmap(100, 30); - pixmap.fill(Qt::transparent); - QPainter painter(&pixmap); - painter.setPen(Qt::black); - painter.drawText(pixmap.rect(), Qt::AlignCenter, modelName); - } - drag->setPixmap(pixmap); - - Qt::DropAction dropAction = drag->exec(Qt::CopyAction); - Q_UNUSED(dropAction); -} \ No newline at end of file +// void DraggableListWidget::mouseMoveEvent(QMouseEvent* event) +// { +// QListWidget::mouseMoveEvent(event); +// } \ No newline at end of file diff --git a/src/ui/ModelBrowser/PresetModelPanel.h b/src/ui/ModelBrowser/PresetModelPanel.h index d73543c3..1fe4aa62 100644 --- a/src/ui/ModelBrowser/PresetModelPanel.h +++ b/src/ui/ModelBrowser/PresetModelPanel.h @@ -10,14 +10,18 @@ #include #include #include +#include +#include +#include +#include +#include "ModelInfo.h" #include "PresetModelConfigParser.h" -QT_BEGIN_NAMESPACE namespace Ui { class PresetModelPanel; } -QT_END_NAMESPACE class DockWidget; + /** * @brief Preset model panel class * @@ -40,42 +44,12 @@ public: */ void AttachDock(DockWidget* dockWidget); -Q_SIGNALS: - /** - * @brief Signal emitted when model is dragged to scene - * @param modelType Model type - * @param modelName Model name - * @param position Scene position (optional) - */ - void ModelDropped(const QString& modelType, const QString& modelName, const QPointF& position = QPointF()); - -private slots: - /** - * @brief Handle model item double click event - * @param item Clicked item - */ - void OnModelItemDoubleClicked(QListWidgetItem* item); - private: /** * @brief Initialize user interface */ void InitUI(); - /** - * @brief Populate model list with items - * @param listWidget List widget to populate - * @param modelType Model type - * @param models Model name list - */ - void PopulateModelList(QListWidget* listWidget, const QString& modelType, const QStringList& models); - - /** - * @brief Setup drag and drop functionality - * @param listWidget List widget to setup drag and drop - */ - void SetupDragAndDrop(QListWidget* listWidget); - /** * @brief Load models from configuration file */ @@ -88,26 +62,9 @@ private: private: Ui::PresetModelPanel *ui; - PresetModelConfigParser m_configParser; -}; - -/** - * @brief Custom list widget with drag and drop support - */ -class DraggableListWidget : public QListWidget { - Q_OBJECT - -public: - explicit DraggableListWidget(const QString& modelType, QWidget* parent = nullptr); - -Q_SIGNALS: - void ItemDragged(const QString& modelType, const QString& modelName); - -protected: - void mousePressEvent(QMouseEvent* event) override; - void mouseMoveEvent(QMouseEvent* event) override; - -private: - QString modelType_; + PresetModelConfigParser configParser_; + + // Drag and drop support QPoint dragStartPosition_; -}; \ No newline at end of file + QListWidget* dragSourceWidget_; +}; diff --git a/src/ui/ModelBrowser/PresetModelPanel.ui b/src/ui/ModelBrowser/PresetModelPanel.ui index 8df142c3..f0b9eab7 100644 --- a/src/ui/ModelBrowser/PresetModelPanel.ui +++ b/src/ui/ModelBrowser/PresetModelPanel.ui @@ -14,6 +14,9 @@ Preset Models + + 5 + 5 @@ -26,16 +29,10 @@ 5 - - 5 - - - - PresetModelToolBox - + - 0 + 1 @@ -43,15 +40,30 @@ 0 0 290 - 540 + 470 Ships + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + - + QAbstractItemView::DragOnly @@ -68,15 +80,30 @@ 0 0 290 - 540 + 470 Satellites + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + - + QAbstractItemView::DragOnly @@ -93,15 +120,30 @@ 0 0 290 - 540 + 470 Missiles + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + - + QAbstractItemView::DragOnly @@ -118,15 +160,30 @@ 0 0 290 - 540 + 470 Jammers + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + - + QAbstractItemView::DragOnly @@ -141,6 +198,13 @@ + + + PresetModelListWidget + QListWidget +
ui/ModelBrowser/PresetModelListWidget.h
+
+
- \ No newline at end of file + diff --git a/src/viewer/OsgWidget.cpp b/src/viewer/OsgWidget.cpp index 9d90214a..96628894 100644 --- a/src/viewer/OsgWidget.cpp +++ b/src/viewer/OsgWidget.cpp @@ -191,10 +191,14 @@ void OsgWidget::paintEvent(QPaintEvent*) { } void OsgWidget::dragEnterEvent(QDragEnterEvent* event) { - // 检查是否是预制模型拖拽 + LOG_INFO("OsgWidget::dragEnterEvent - Available formats:{}", event->mimeData()->formats().join(",").toStdString()); + + // Check if it's a preset model drag if (event->mimeData()->hasFormat("application/x-preset-model")) { + LOG_INFO("OsgWidget::dragEnterEvent - Accept preset model drag"); event->acceptProposedAction(); } else { + LOG_INFO("OsgWidget::dragEnterEvent - Ignore drag, not preset model format"); event->ignore(); } } @@ -209,28 +213,33 @@ void OsgWidget::dragMoveEvent(QDragMoveEvent* event) { } void OsgWidget::dropEvent(QDropEvent* event) { - // 检查是否是预制模型拖拽 + LOG_INFO("OsgWidget::dropEvent - Start processing drop event"); + if (event->mimeData()->hasFormat("application/x-preset-model")) { QByteArray data = event->mimeData()->data("application/x-preset-model"); QString modelInfo = QString::fromUtf8(data); - // 解析模型信息 (格式: "modelType|modelName") + LOG_INFO("OsgWidget::dropEvent - Received model info:{}", modelInfo.toStdString()); + QStringList parts = modelInfo.split("|"); if (parts.size() == 2) { QString modelType = parts[0]; QString modelName = parts[1]; - // 获取拖拽位置 QPointF position = event->posF(); - // 处理预制模型拖拽 + LOG_INFO("OsgWidget::dropEvent - Parse success, type:{} name:{} position:({},{})", modelType.toStdString(), modelName.toStdString(), position.x(), position.y()); + OnPresetModelDropped(modelType, modelName, position); event->acceptProposedAction(); + LOG_INFO("OsgWidget::dropEvent - Drag processing completed, accepted"); } else { + LOG_ERROR("OsgWidget::dropEvent - Data format error, expected: type|name, actual:{}", modelInfo.toStdString()); event->ignore(); } } else { + LOG_INFO("OsgWidget::dropEvent - Not preset model format, ignore drag"); event->ignore(); } } @@ -241,7 +250,7 @@ void OsgWidget::OnPresetModelDropped(const QString& modelType, const QString& mo // 2. 创建对应的Entity和MeshComponent // 3. 添加到场景中 - qDebug() << "预制模型拖拽:" << modelType << modelName << "位置:" << position; + LOG_INFO("OsgWidget::OnPresetModelDropped - Dropped model type:{} name:{} position:({}, {})", modelType.toStdString(), modelName.toStdString(), position.x(), position.y()); // 这里暂时只是输出调试信息,后续需要集成实体系统 } diff --git a/workspace/presets/jammers.xml b/workspace/presets/jammers.xml index cd936285..9941ef0c 100644 --- a/workspace/presets/jammers.xml +++ b/workspace/presets/jammers.xml @@ -3,21 +3,11 @@ - - - \ No newline at end of file diff --git a/workspace/presets/missiles.xml b/workspace/presets/missiles.xml index d38d5838..f3b873ed 100644 --- a/workspace/presets/missiles.xml +++ b/workspace/presets/missiles.xml @@ -1,23 +1,8 @@ - - - - \ No newline at end of file diff --git a/workspace/presets/satellites.xml b/workspace/presets/satellites.xml index 07f48118..00e6057b 100644 --- a/workspace/presets/satellites.xml +++ b/workspace/presets/satellites.xml @@ -1,23 +1,8 @@ - - - - \ No newline at end of file diff --git a/workspace/presets/ships.xml b/workspace/presets/ships.xml index 98af9f07..8979bbbb 100644 --- a/workspace/presets/ships.xml +++ b/workspace/presets/ships.xml @@ -3,21 +3,11 @@ - - - \ No newline at end of file