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