# Qt C++ 代码规范标准
## BattlefieldExplorationSystem 项目专用

**版本**: 1.0  
**适用范围**: Qt 5.15 + C++17  
**最后更新**: 2024-12-30  

---

## 📋 目录

1. [概述](#概述)
2. [命名约定](#命名约定)
3. [代码格式](#代码格式)
4. [文件组织](#文件组织)
5. [Qt特性使用规范](#qt特性使用规范)
6. [注释与文档](#注释与文档)
7. [内存管理与资源](#内存管理与资源)
8. [错误处理](#错误处理)
9. [性能优化指南](#性能优化指南)
10. [代码审查检查清单](#代码审查检查清单)

---

## 概述

本规范基于Qt官方编码风格、Google C++ Style Guide和现代C++最佳实践，专门为BattlefieldExplorationSystem项目制定。旨在提高代码质量、可读性和可维护性，确保项目达到工业级标准。

### 核心原则
- **一致性**: 整个项目保持统一的编码风格
- **可读性**: 代码应该自解释，易于理解
- **安全性**: 优先考虑类型安全和内存安全
- **性能**: 在不影响可读性的前提下优化性能
- **Qt最佳实践**: 充分利用Qt框架特性

---

## 命名约定

### 类名 (PascalCase)
```cpp
// ✅ 正确
class MainWindow;
class DeviceManager;
class UAVDatabase;

// ❌ 错误
class mainWindow;
class device_manager;
class uavDatabase;
```

### 函数名 (camelCase)
```cpp
// ✅ 正确
void setupUI();
void connectSignals();
void onButtonClicked();

// ❌ 错误
void SetupUI();
void connect_signals();
void on_button_clicked();
```

### 变量名

#### 成员变量 (m_前缀 + camelCase)
```cpp
class MainWindow {
private:
    // ✅ 正确
    Ui::MainWindow *m_ui;
    DeviceListPanel *m_deviceListPanel;
    QTimer *m_heartbeatTimer;
    
    // ❌ 错误 - 项目中发现的问题
    Ui::MainWindow *ui;  // 缺少m_前缀
    DeviceListPanel *deviceListPanel;  // 不一致的命名
};
```

#### 局部变量 (camelCase)
```cpp
// ✅ 正确
QString deviceName = "UAV-001";
int signalStrength = 85;
QList<DeviceInfo> deviceList;

// ❌ 错误
QString device_name = "UAV-001";
int SignalStrength = 85;
```

#### 常量 (UPPER_CASE)
```cpp
// ✅ 正确
const int MAX_DEVICE_COUNT = 100;
const QString DEFAULT_IP_ADDRESS = "192.168.1.1";
const double GPS_PRECISION = 0.000001;

// ❌ 错误 - 项目中发现的硬编码问题
this->setMinimumSize(1400, 1000);  // 应该使用命名常量
```

### 文件名
```cpp
// ✅ 正确
MainWindow.h / MainWindow.cpp
DeviceCard.h / DeviceCard.cpp
UAVDatabase.h / UAVDatabase.cpp

// ❌ 错误
mainwindow.h
device_card.cpp
```

---

## 代码格式

### 缩进和空格
- **缩进**: 使用4个空格，不使用Tab
- **行长度**: 最大100字符
- **空格**: 操作符前后加空格

```cpp
// ✅ 正确
if (deviceStatus == DeviceStatus::Online) {
    m_statusLabel->setText("设备在线");
    m_statusIndicator->setStyleSheet("color: green;");
}

// ❌ 错误
if(deviceStatus==DeviceStatus::Online){
m_statusLabel->setText("设备在线");
m_statusIndicator->setStyleSheet("color: green;");
}
```

### 大括号位置
```cpp
// ✅ 正确 - K&R风格
class DeviceCard : public QWidget
{
    Q_OBJECT

public:
    explicit DeviceCard(const DeviceInfo &info, QWidget *parent = nullptr);
    
private slots:
    void onUpdateRequested();
};

void DeviceCard::setupUI()
{
    if (m_deviceInfo.type == "uav") {
        // UAV特定设置
    } else {
        // 其他设备设置
    }
}
```

### 指针和引用
```cpp
// ✅ 正确
QWidget *parent = nullptr;
const DeviceInfo &info = getDeviceInfo();
std::unique_ptr<QTimer> timer;

// ❌ 错误
QWidget* parent = nullptr;
QWidget * parent = nullptr;
const DeviceInfo& info = getDeviceInfo();
```

---

## 文件组织

### 头文件包含顺序
```cpp
// ✅ 正确顺序
// 1. 对应的头文件
#include "MainWindow.h"

// 2. Qt系统头文件
#include <QMainWindow>
#include <QApplication>
#include <QTimer>

// 3. 第三方库头文件
#include <memory>
#include <vector>

// 4. 项目内部头文件
#include "ui/components/DeviceListPanel.h"
#include "core/database/UAVDatabase.h"
#include "utils/SystemLogger.h"
```

### Include Guard
```cpp
// ✅ 正确 - 使用#pragma once
#pragma once

#include <QWidget>

class DeviceCard : public QWidget
{
    // 类定义
};

// ❌ 错误 - 传统的include guard（虽然可用但不推荐）
#ifndef DEVICECARD_H
#define DEVICECARD_H
// ...
#endif
```

### 前向声明
```cpp
// ✅ 正确 - 在头文件中使用前向声明
// DeviceCard.h
#pragma once

class QLabel;
class QPushButton;
class DeviceInfo;

class DeviceCard : public QWidget
{
private:
    QLabel *m_nameLabel;
    QPushButton *m_controlButton;
    std::unique_ptr<DeviceInfo> m_deviceInfo;
};
```

---

## Qt特性使用规范

### 信号槽连接
```cpp
// ✅ 正确 - 使用新式语法
connect(m_deviceListPanel, &DeviceListPanel::deviceSelected,
        this, &MainWindow::onDeviceSelected);

connect(m_timer, &QTimer::timeout,
        this, [this]() {
            updateDeviceStatus();
        });

// ❌ 错误 - 旧式语法（项目中发现的问题）
connect(button, SIGNAL(clicked()), this, SLOT(onButtonClicked()));
```

### Q_OBJECT宏位置
```cpp
// ✅ 正确
class MainWindow : public QMainWindow
{
    Q_OBJECT  // 紧跟在类声明后

public:
    explicit MainWindow(QWidget *parent = nullptr);
    
signals:
    void deviceAdded(const DeviceInfo &info);
    
private slots:
    void onDeviceSelected(const DeviceInfo &info);
};
```

### 属性系统
```cpp
// ✅ 正确
class DeviceCard : public QWidget
{
    Q_OBJECT
    Q_PROPERTY(DeviceStatus status READ status WRITE setStatus NOTIFY statusChanged)

public:
    DeviceStatus status() const { return m_status; }
    void setStatus(DeviceStatus status);

signals:
    void statusChanged(DeviceStatus status);

private:
    DeviceStatus m_status = DeviceStatus::Unknown;
};
```

---

## 注释与文档

### Doxygen文档注释
```cpp
/**
 * @file DeviceCard.h
 * @brief 设备卡片组件定义
 * @author BattlefieldExplorationSystem Team
 * @date 2024-12-30
 * @version 1.0
 * 
 * 设备卡片组件，用于显示单个设备的详细信息和状态。
 * 支持UAV和地面机器人两种设备类型的统一显示。
 * 
 * @note 依赖Qt GUI模块
 * @since 1.0
 */

/**
 * @class DeviceCard
 * @brief 设备信息显示卡片
 * 
 * 提供设备信息的可视化显示，包括：
 * - 设备基本信息（名称、类型、IP地址）
 * - 实时状态显示（在线状态、信号强度、电量）
 * - 操作控制按钮（详情、控制、定位）
 * 
 * @warning 需要定期更新设备状态以保持界面同步
 * @see DeviceInfo, DeviceStatus
 */
class DeviceCard : public QWidget
{
    Q_OBJECT

public:
    /**
     * @brief 构造函数
     * @param info 设备信息结构体
     * @param parent 父窗口指针，默认为nullptr
     * 
     * 创建设备卡片并初始化UI组件。
     * 根据设备类型自动设置相应的图标和样式。
     * 
     * @note 构造后需要调用updateStatus()更新状态
     */
    explicit DeviceCard(const DeviceInfo &info, QWidget *parent = nullptr);
    
    /**
     * @brief 更新设备状态
     * @param status 新的设备状态
     * 
     * 更新设备的在线状态、信号强度和电量信息。
     * 同时更新UI显示的颜色和图标。
     * 
     * @warning 此函数应该在主线程中调用
     */
    void updateStatus(const DeviceStatus &status);
};
```

### 行内注释
```cpp
void MainWindow::setupUI()
{
    // 设置窗口最小尺寸 - 确保所有组件正常显示
    this->setMinimumSize(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT);
    
    // 计算窗口居中位置
    QRect screenGeometry = QApplication::desktop()->screenGeometry();
    int centerX = (screenGeometry.width() - this->width()) / 2;
    int centerY = (screenGeometry.height() - this->height()) / 2;
    this->move(centerX, centerY);
    
    // TODO: 添加窗口状态保存功能
    // FIXME: 在高DPI显示器上可能需要调整尺寸计算
}
```

---

## 内存管理与资源

### 智能指针使用
```cpp
// ✅ 正确 - 使用智能指针
class MainWindow : public QMainWindow
{
private:
    std::unique_ptr<Ui::MainWindow> m_ui;
    std::shared_ptr<DatabaseManager> m_dbManager;
    std::unique_ptr<QTimer> m_heartbeatTimer;
};

// 构造函数中
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , m_ui(std::make_unique<Ui::MainWindow>())
    , m_dbManager(std::make_shared<DatabaseManager>())
    , m_heartbeatTimer(std::make_unique<QTimer>(this))
{
    m_ui->setupUi(this);
}

// ❌ 错误 - 原始指针（项目中发现的问题）
Ui::MainWindow *ui;  // 容易造成内存泄漏
QTimer *timer;       // 生命周期管理不明确
```

### Qt对象树管理
```cpp
// ✅ 正确 - 利用Qt父子关系
void MainWindow::setupDevicePanel()
{
    // Qt对象会自动管理子对象的生命周期
    m_deviceListPanel = new DeviceListPanel(this);  // this作为parent
    m_systemLogPanel = new SystemLogPanel(this);
    
    // 或者使用智能指针 + 父子关系
    auto deviceCard = std::make_unique<DeviceCard>(deviceInfo, this);
    m_deviceCards.push_back(std::move(deviceCard));
}
```

### 资源文件管理
```cpp
// ✅ 正确 - 使用资源系统
const QString ICON_UAV = ":/images/uav.png";
const QString ICON_ROBOT = ":/images/robot.png";
const QString STYLE_SHEET = ":/styles/military_theme.qss";

// ❌ 错误 - 硬编码路径
QString iconPath = "/home/user/project/images/uav.png";  // 不可移植
```

---

## 错误处理

### 异常安全
```cpp
// ✅ 正确 - RAII和异常安全
class DatabaseConnection
{
public:
    explicit DatabaseConnection(const QString &connectionString)
    {
        m_db = QSqlDatabase::addDatabase("QMYSQL");
        m_db.setDatabaseName(connectionString);
        if (!m_db.open()) {
            throw std::runtime_error("Failed to open database");
        }
    }
    
    ~DatabaseConnection()
    {
        if (m_db.isOpen()) {
            m_db.close();
        }
    }
    
    // 禁止拷贝，允许移动
    DatabaseConnection(const DatabaseConnection&) = delete;
    DatabaseConnection& operator=(const DatabaseConnection&) = delete;
    DatabaseConnection(DatabaseConnection&&) = default;
    DatabaseConnection& operator=(DatabaseConnection&&) = default;

private:
    QSqlDatabase m_db;
};
```

### 错误码处理
```cpp
// ✅ 正确 - 使用枚举类表示错误状态
enum class DatabaseError
{
    Success,
    ConnectionFailed,
    QueryFailed,
    InvalidData,
    PermissionDenied
};

class DatabaseManager
{
public:
    DatabaseError connectToDatabase(const QString &host, int port,
                                   const QString &username, const QString &password)
    {
        // ❌ 项目中发现的安全问题 - 硬编码密码
        // db.setPassword("hzk200407140238");  // 绝对不能这样做！
        
        // ✅ 正确 - 从配置文件读取
        auto config = ConfigManager::instance().getDatabaseConfig();
        m_db.setHostName(config.host);
        m_db.setPort(config.port);
        m_db.setUserName(config.username);
        m_db.setPassword(config.password);  // 从安全配置读取
        
        if (!m_db.open()) {
            return DatabaseError::ConnectionFailed;
        }
        
        return DatabaseError::Success;
    }
};
```

---

## 性能优化指南

### Qt容器使用
```cpp
// ✅ 正确 - 选择合适的容器
QVector<DeviceInfo> m_devices;        // 随机访问，频繁插入删除
QList<QString> m_logMessages;         // 顺序访问，前后插入
QHash<QString, DeviceCard*> m_deviceCards;  // 快速查找

// 预分配容量
m_devices.reserve(MAX_DEVICE_COUNT);

// 使用const引用避免拷贝
for (const auto &device : m_devices) {
    updateDeviceDisplay(device);
}
```

### 信号槽优化
```cpp
// ✅ 正确 - 使用Qt::QueuedConnection处理跨线程
connect(m_worker, &WorkerThread::dataReady,
        this, &MainWindow::onDataReceived,
        Qt::QueuedConnection);

// 使用lambda避免创建槽函数
connect(m_timer, &QTimer::timeout, this, [this]() {
    // 简单的更新操作
    m_statusLabel->setText(getCurrentTime());
});
```

### 内存优化
```cpp
// ✅ 正确 - 延迟初始化
class MainWindow : public QMainWindow
{
private:
    mutable std::unique_ptr<ExpensiveWidget> m_expensiveWidget;
    
public:
    ExpensiveWidget* getExpensiveWidget() const
    {
        if (!m_expensiveWidget) {
            m_expensiveWidget = std::make_unique<ExpensiveWidget>();
        }
        return m_expensiveWidget.get();
    }
};
```

---

## 代码审查检查清单

### 基本检查
- [ ] 所有类名使用PascalCase
- [ ] 所有函数名使用camelCase  
- [ ] 私有成员变量使用m_前缀
- [ ] 常量使用UPPER_CASE命名
- [ ] 头文件包含顺序正确
- [ ] 使用#pragma once而非传统include guard

### Qt特定检查
- [ ] Q_OBJECT宏位置正确
- [ ] 信号槽连接使用新式语法
- [ ] 正确设置Qt对象的父子关系
- [ ] 资源文件使用qrc系统管理

### 安全检查
- [ ] 无硬编码密码或敏感信息
- [ ] 使用智能指针管理动态内存
- [ ] 正确的异常安全保证
- [ ] 输入参数验证充分

### 性能检查
- [ ] 容器预分配容量（如适用）
- [ ] 使用const引用传递大对象
- [ ] 避免不必要的对象拷贝
- [ ] 合理使用延迟初始化

### 文档检查
- [ ] 公共接口有完整Doxygen注释
- [ ] 复杂逻辑有行内注释说明
- [ ] 文件头信息完整
- [ ] TODO/FIXME标记清晰

---

## 工具配置

### clang-format配置
创建`.clang-format`文件：
```yaml
BasedOnStyle: Google
IndentWidth: 4
ColumnLimit: 100
PointerAlignment: Left
```

### 静态分析工具
```bash
# cppcheck
cppcheck --enable=all --std=c++17 src/

# clang-static-analyzer  
scan-build qmake && scan-build make
```

---

**注意**: 本规范应该逐步应用到现有代码中，避免一次性大规模修改。建议在每次代码修改时同步应用相关规范。
