TreeWiget右键添加删除复制粘贴剪切和双击展开

项目中代码

#include "treewidget.h"
#include "dataprocess.h"
#include "addsondialog.h"
#include "dialog.h"
#include "setconfdialog.h"
#include <QHeaderView>
#include <QVector>
#include <vector>
#include <algorithm>
#include <iostream>

// 必须加上此宏定义,不然报错,导致无法提取树中数据
Q_DECLARE_METATYPE(TypeData)

TreeWidget::TreeWidget(QTreeWidget *parent) : QTreeWidget(parent)
{
    // 设置颜色
    QString strStyleSheet = QString("QSplitter::handle { background-color: rgb(179, 179, 179); }") //分割线的颜色
            + QString("QSplitter {border: 2px solid green}");
    this->setStyleSheet(strStyleSheet);

    this->setColumnCount(1);    // 设置列数
    this->setHeaderLabel(tr("Vehicle"));    // 设置标题
    this->menu = new QMenu;
    this->action1 = new QAction("设置当前菜单");
    this->action2 = new QAction("删除");
    this->action3 = new QAction("设置子菜单");
    this->action4 = new QAction("添加子菜单");
    this->action5 = new QAction("复制");
    this->action6 = new QAction("粘贴");
    this->action8 = new QAction("剪切");


    this->menu->addAction(action1);
    this->menu->addAction(action2);
    this->menu->addAction(action3);
    this->menu->addAction(action4);
    this->menu->addAction(action8);
    this->menu->addAction(action5);
    this->menu->addAction(action6);

    // 发送信号
   connect(action1, &QAction::triggered, this, &TreeWidget::SetCarItem, Qt::UniqueConnection);
   connect(action2, &QAction::triggered, this, &TreeWidget::DeleteCarItem, Qt::UniqueConnection);
   connect(action3, &QAction::triggered, this, &TreeWidget::SetSonItem, Qt::UniqueConnection);
   connect(action4, &QAction::triggered, this, &TreeWidget::AddSonItem, Qt::UniqueConnection);
   connect(action5, &QAction::triggered, this, &TreeWidget::CopyItem, Qt::UniqueConnection);
   connect(action6, &QAction::triggered, this, &TreeWidget::PasteItem, Qt::UniqueConnection);
   connect(action8, &QAction::triggered, this, &TreeWidget::ShearItem, Qt::UniqueConnection);
}

//初始化界面
void TreeWidget::InitUI()
{
    QVector<QString> vecCarName;
    this->mysqlData->GetCarIndex(vecCarName);

    // 将电控制系统放入树中
    for (int i = 0; i < vecCarName.size(); i++) {
        QTreeWidgetItem *widgetItem = new QTreeWidgetItem();
        widgetItem->setText(0, vecCarName[i]);
        // 树根
        this->addTopLevelItem(widgetItem);
    }

    // 双击展开事件 showSonItem槽函数触发
    connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(ShowSonItem(QTreeWidgetItem*,int)));
    //connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(ShowMenuData(QTreeWidgetItem*,int)));
    // 点击事件,显示右边参数,触发ShowMenuData槽函数
    connect(this, SIGNAL(itemPressed(QTreeWidgetItem*,int)), this, SLOT(ShowMenuData(QTreeWidgetItem*,int)));

    this->setStyle(QStyleFactory::create("windows"));   // 将树加上虚线

    //this->scrollToTop();    //让滚动条滚动到最顶部
    // 水平滑动条
    this->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
    this->header()->setStretchLastSection(false);

    this->expandAll();      //结点全部展开

}

// 添加车系Item
void TreeWidget::AddCarItem(QTreeWidgetItem*& item, TypeData& typeData)
{
    QString strTitle = "";
    // 查数据库得到title
    this->mysqlData->GetTMenuTitle(typeData.carid, typeData.textid, strTitle);

    QTreeWidgetItem *widgetItem1_1 = new QTreeWidgetItem();
    widgetItem1_1->setText(0, strTitle);
    widgetItem1_1->setData(0, Qt::UserRole, QVariant::fromValue(typeData));

    item->addChild(widgetItem1_1);
}


// 双击事件的槽函数
void TreeWidget::ShowSonItem(QTreeWidgetItem * item, int column)
{
    if (item != nullptr) {
        if (qApp->mouseButtons() == Qt::LeftButton) {   // 左键

            // 如果已经添加了子节点就无需再添加,删除子节点起到刷新的作用
            DataProcess::DeleteSonItem(item);
            // 节点深度
            int count = 0;
            QTreeWidgetItem* itemCurrent = item;
            // 求出树的深度
            this->LengthTreeItem(count, itemCurrent);

            // 添加ecu
            if (count == 0) {   // 第0层
                // 添加第0深度的内容
                this->AddZeroItem(item);
            } else if (count >= 1) {   // 第一层
                this->AddOneItem(item);
            }

        } else if (qApp->mouseButtons() == Qt::RightButton) {   // 右键
            //qDebug() << " double rightbutton";
        }
    }

}

// 添加第0深度的内容
void TreeWidget::AddZeroItem(QTreeWidgetItem*& item)
{
    // 那个根目录下,求出根的名字
    QString strTitle = item->text(0);
    QVector<QString> vecCarId;
    this->mysqlData->GetCarIndex(strTitle, vecCarId);
    // 查找TypeData表
    for (int i = 0; i < vecCarId.size(); i++) {
        QString strCarIndex = vecCarId[i].mid(2, vecCarId[i].size()-2);
        QVector<QString> vecTypeData;
        // 查找第0个及为根车系名
        this->mysqlData->GetVecTypeData(strCarIndex, "0", vecTypeData);
        if (vecTypeData.size() == 0) {
            continue;
        }
        TypeData typeData;
        typeData.GetVec(vecTypeData);
        this->AddCarItem(item, typeData);
    }
}

// 添加第一深度的内容
void TreeWidget::AddOneItem(QTreeWidgetItem*& item)
{
    TypeData typeData = item->data(0, Qt::UserRole).value<TypeData>();
    QString carId = typeData.carid;
    QString strId = typeData.id;
    // 查询DataConf表得到子目录
    QVector<DataConf> vecData = this->mysqlData->GetDataConf(carId, strId);

    //升序排序
    std::sort(vecData.begin(), vecData.end(), std::less<DataConf>());

    // 没有子节点
    if (vecData.size() == 0) {
        return;
    }
    // 加上子树
    for (int i = 0; i < vecData.size(); i++) {
        DataConf dataConf;

        dataConf = vecData[i];
        QTreeWidgetItem *sonItem = new QTreeWidgetItem();
        // 查typeData
        this->mysqlData->GetTypeData(dataConf.carid, dataConf.sonid, typeData);
        QString strTitle = "";
        // 得到标题
        this->mysqlData->GetTMenuTitle(typeData.carid, typeData.textid, strTitle);
        sonItem->setText(0, strTitle);
        if (vecData[i].visible == "0") {    // 不可见的就设置其他颜色
           sonItem->setForeground(0, QBrush(QColor("#0000FF")));
        }
        sonItem->setData(0, Qt::UserRole, QVariant::fromValue(typeData));
        item->addChild(sonItem);
    }
}

// 树的深度
void TreeWidget::LengthTreeItem(int& count, QTreeWidgetItem*& item)
{
    while(item && item->parent())
    {
        item = item->parent();
        count++;
    }
}

// 单击事件槽函数
void TreeWidget::ShowMenuData(QTreeWidgetItem * item, int column)
{

    if (item->parent() != nullptr) {
        if (qApp->mouseButtons() == Qt::LeftButton) {
            // 本身
            TypeData typeData = item->data(0, Qt::UserRole).value<TypeData>();

            // 父亲
            TypeData typeFatherData = item->parent()->data(0, Qt::UserRole).value<TypeData>();

            // 单击树节点发送信号
            // void NotifyMenuData(TypeData& typeData, TypeData& typeFatherData);
            emit(NotifyMenuData(typeData, typeFatherData));

        } else if (qApp->mouseButtons() == Qt::RightButton) {
            this->menu->exec(QCursor::pos());
        }
    }

}

// 设置配置信息
void TreeWidget::SetCarItem()
{
    qDebug() << "SetCarItem";
    QTreeWidgetItem *item = this->currentItem();   //获取光标所在位置的Item
    TypeData typeData = item->data(0, Qt::UserRole).value<TypeData>();

    Dialog dialog;  // 模态对话框
    dialog.mysqlData = this->mysqlData;
    dialog.typeData = typeData;
    dialog.SetWindowData();
    int r = dialog.exec();
    // 按下是确定要跟tree中的typedata
    if(r == QDialog::Accepted) {
        // 重新设置当前节点
        typeData = dialog.typeData;
        QString strTitle = "";
        this->mysqlData->GetTMenuTitle(typeData.carid, typeData.textid, strTitle);
        item->setText(0, strTitle);
        item->setData(0, Qt::UserRole, QVariant::fromValue(typeData));
        this->setCurrentItem(item);
        qDebug() << "accepted";
    } else if(r == QDialog::Rejected) {
        qDebug() << "Rejected";
    }
}

// 删除当前节点
void TreeWidget::DeleteCarItem()
{
    QTreeWidgetItem *item = this->currentItem();   //获取光标所在位置的Item
    this->DeleteItem(item);
}

// 设置孩子子目录
void TreeWidget::SetSonItem()
{
    QTreeWidgetItem *item = this->currentItem();   //获取光标所在位置的Item
    TypeData typeData = item->data(0, Qt::UserRole).value<TypeData>();

    SetConfDialog formDialog;  // 模态对话框
    formDialog.mysqlData = this->mysqlData;
    formDialog.typeData = typeData;
    formDialog.InitUI();

    int r = formDialog.exec();  // 显示后阻塞

    // 按下是确定要跟tree中的typedata
    if(r == QDialog::Accepted) {
        qDebug() << "accepted";
    } else if(r == QDialog::Rejected) {
        qDebug() << "Rejected";
    }

}


// 添加子车系
void TreeWidget::AddSonItem()
{
    QTreeWidgetItem *item = this->currentItem();   //获取光标所在位置的Item
    TypeData typeData = item->data(0, Qt::UserRole).value<TypeData>();

    AddSonDialog addDialog;  // 模态对话框
    addDialog.mysqlData = this->mysqlData;
    addDialog.typeData.carid = typeData.carid;
    addDialog.strfathId = typeData.id;

    int r = addDialog.exec();  // 显示后阻塞

    // 按下是确定要跟tree中的typedata
    if(r == QDialog::Accepted) {
        typeData = addDialog.typeData;
        QTreeWidgetItem *sonItem = new QTreeWidgetItem();

        QString strTitle;
        // 得到标题
        this->mysqlData->GetTMenuTitle(typeData.carid, typeData.textid, strTitle);
        sonItem->setText(0, strTitle);
        sonItem->setData(0, Qt::UserRole, QVariant::fromValue(typeData));
        // 加上子链
        item->addChild(sonItem);
    } else if(r == QDialog::Rejected) {
        qDebug() << "Rejected AddSonItem() ";
    }
}



// 拷贝
void TreeWidget::CopyItem()
{
    QTreeWidgetItem *item = this->currentItem();   //获取光标所在位置的Item
    this->currentTypeData = item->data(0, Qt::UserRole).value<TypeData>();    
    flagType = true;        // 粘贴设置true,可粘贴
}

// 粘贴
void TreeWidget::PasteItem()
{
    if (flagType == true) {
        TypeData sonTypeData = this->currentTypeData;

        QTreeWidgetItem *item = this->currentItem();   //获取光标所在位置的Item
        TypeData typeData = item->data(0, Qt::UserRole).value<TypeData>();
        QString fatherId = typeData.id;
        sonTypeData.carid = typeData.carid;

        DataProcess::InsertSql(this->mysqlData, sonTypeData, fatherId);

        QTreeWidgetItem *sonItem = new QTreeWidgetItem();

        QString strTitle = "";
        // 得到标题
        this->mysqlData->GetTMenuTitle(typeData.carid, typeData.textid, strTitle);
        sonItem->setText(0, strTitle);
        sonItem->setData(0, Qt::UserRole, QVariant::fromValue(sonTypeData));
        // 加上子链
        item->addChild(sonItem);

    }
}

// 剪切
void TreeWidget::ShearItem()
{
    QTreeWidgetItem *item = this->currentItem();   //获取光标所在位置的Item
    this->currentTypeData = item->data(0, Qt::UserRole).value<TypeData>();
    this->flagType = true;

    this->DeleteItem(item);
}

// 删除一个车系
void TreeWidget::DeleteItem(QTreeWidgetItem*& item)
{
    TypeData typeData = item->data(0, Qt::UserRole).value<TypeData>();
    QString strSonId = typeData.id;

    // 得到父节点
    QTreeWidgetItem* fatherItem = item->parent();
    TypeData typeFatherData = fatherItem->data(0, Qt::UserRole).value<TypeData>();
    QString strFatherId = typeFatherData.id;

    // 删除DataConf表中值
    this->mysqlData->DeleteDataConf(typeData.carid, strFatherId, strSonId);

    fatherItem->removeChild(item);
    if (item != nullptr) {
        delete item;
        item = nullptr;
    }
}


//
TreeWidget::~TreeWidget()
{
    if (this->action8 != nullptr) {
        delete this->action8;
        this->action8 = nullptr;
    }
    if (this->action6 != nullptr) {
        delete this->action6;
        this->action6 = nullptr;
    }
    if (this->action5 != nullptr) {
        delete this->action5;
        this->action5 = nullptr;
    }
    if (this->action4 != nullptr) {
        delete this->action4;
        this->action4 = nullptr;
    }
    if (this->action3 != nullptr) {
        delete this->action3;
        this->action3 = nullptr;
    }
    if (this->action2 != nullptr) {
        delete this->action2;
        this->action2 = nullptr;
    }
    if (this->action1 != nullptr) {
        delete this->action1;
        this->action1 = nullptr;
    }
    if (this->menu != nullptr) {
        delete this->menu;
        this->menu = nullptr;
    }

    if (this->delphItem != nullptr) {
        delete this->delphItem;
        this->delphItem = nullptr;
    }   

}
#ifndef TREEWIDGET_H
#define TREEWIDGET_H

#include <QWidget>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QApplication>
#include <QDebug>
#include <QStyleFactory>
#include <QScrollBar>
#include <QMenu>
#include <QAction>
#include "mysqldata.h"
#include "typedata.h"

// 车系界面树状图
class TreeWidget : public QTreeWidget
{
    Q_OBJECT
public:
    explicit TreeWidget(QTreeWidget *parent = nullptr);
    ~TreeWidget();

    void DeleteItem(QTreeWidgetItem*& item);

    // 树的深度
    void LengthTreeItem(int& count, QTreeWidgetItem*& item);

    // 添加第一深度的内容
    void AddOneItem(QTreeWidgetItem*& item);

    // 添加第0深度的内容
    void AddZeroItem(QTreeWidgetItem*& item);

public:
    void InitUI();      //初始化界面

public:
    QTreeWidgetItem *delphItem = nullptr;
    MysqlData* mysqlData = nullptr;
    QMenu* menu = nullptr;
    QAction* action1 = nullptr;
    QAction* action2 = nullptr;
    QAction* action3 = nullptr;
    QAction* action4 = nullptr;
    QAction* action5 = nullptr;
    QAction* action6 = nullptr;
    QAction* action8 = nullptr;

    TypeData currentTypeData;
    bool flagType = false;

public slots:
    // 双击事件的槽函数
    void ShowSonItem(QTreeWidgetItem * item, int column);

    // 单击事件槽函数
    void ShowMenuData(QTreeWidgetItem * item, int column);

    // 设置车系详细信息
    void SetCarItem();
    // 添加子车系
    void AddSonItem();
    // 删除指定车系
    void DeleteCarItem();
    // 设置子车系目录
    void SetSonItem();
    // 拷贝
    void CopyItem();
    // 粘贴
    void PasteItem();
    // 剪切
    void ShearItem();

    // 添加车系Item
    void AddCarItem(QTreeWidgetItem*& item, TypeData& typeData);

signals:
    void NotifyMenuData(TypeData typeData, TypeData typeFatherData);
};

#endif // TREEWIDGET_H
// 递归删除treeItem子节点避免内存泄漏
void DataProcess::DeleteSonItem(QTreeWidgetItem * item)
{
    if (item->childCount() != 0) {
        int count = item->childCount();
        while (count--) {
            QTreeWidgetItem * childItem = item->child(count); //index从大到小区做删除处理
            DataProcess::DeleteSonItem(childItem);
            item->removeChild(childItem);
            if (childItem != nullptr) {
                delete childItem;
                childItem = nullptr;
            }
        }
    }
}

 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值