Qt工作笔记-代理及自定义委托,实现开关功能

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq78442761/article/details/84565120

整体源码下载如下:

https://download.csdn.net/download/qq78442761/10810431

效果图如下:

源码如下:

adddialog.h

#ifndef ADDDIALOG_H
#define ADDDIALOG_H

#include <QDialog>

struct AddData{
    QString name;
    QString shellFilePath;
};

namespace Ui {
class AddDialog;
}

class AddDialog : public QDialog
{
    Q_OBJECT

public:
    AddDialog(QWidget *parent = 0);
    AddData *getAddData();

    void setNameAndFilePath(const QString name, const QString filePath);
    ~AddDialog();

protected:
    void closeEvent(QCloseEvent *event);

protected slots:
    void okBtnClicked();
    void selectBtnClicked();

private:
    Ui::AddDialog *ui;
    AddData *m_addData;
};

#endif // ADDDIALOG_H

fileoper.h

#ifndef FILEOPER_H
#define FILEOPER_H

#include <QString>
#include <QVector>

class FileOper
{
public:
    FileOper(const QString fileName);
    ~FileOper();
    QVector<QString> &getContextVec();
    void clearContextVec();
    void saveFile();
    void readFile();

private:
    QString m_fileName;
    QVector<QString> m_contextVec;
};

#endif // FILEOPER_H

mydelegate.h

#ifndef MYDELEGATE_H
#define MYDELEGATE_H

#include <QStyledItemDelegate>

class MyDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    explicit MyDelegate(QWidget *parent = 0);

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index)const;
    QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;

protected:
    void paint();
};

#endif // MYDELEGATE_H

myonoff.h

#ifndef MYONOFF_H
#define MYONOFF_H

#include <QMetaType>
#include <QRect>

QT_BEGIN_NAMESPACE
class QPainter;
QT_END_NAMESPACE

class MyOnOff
{
public:
    enum EditMode {Editable, ReadOnly};

    MyOnOff(const bool isOpenStatus = false);
    bool getIsOpenStatus();
    void setIsOpenStatus(const bool isOpenStatus);
    void painter(QPainter *painter, const QRect &rect, const QPalette palette, EditMode mode) const;

private:
    bool m_isOpen;
};

Q_DECLARE_METATYPE(MyOnOff)

#endif // MYONOFF_H

myonoffeditor.h

#ifndef MYONOFFEDITOR_H
#define MYONOFFEDITOR_H

#include <QWidget>
#include "myonoff.h"

class MyOnOffEditor : public QWidget
{
    Q_OBJECT
public:
    explicit MyOnOffEditor(QWidget *parent = 0);
    void setMyOnOffStatus(const bool myOnOffStatus);
    bool getMyOnOffStatus();

protected:
    void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;

private:
    MyOnOff m_myOnOff;
};

#endif // MYONOFFEDITOR_H

mytreeview.h

#ifndef MYTREEVIEW_H
#define MYTREEVIEW_H

#include <QTreeView>
#include <QVector>

class MyTreeView : public QTreeView
{
    Q_OBJECT
public:
    MyTreeView(QWidget *parent = 0);
    void initWidget(const QVector<QString> vec);

protected:
    void contextMenuEvent(QContextMenuEvent *event);

    void addItem(const QString name, const QString filePath);

protected slots:
    void addContextMenuCalled();
    void removeContextMenuCalled();
    void doubleCilckedCalled(const QModelIndex &index);

private:
    int m_currentSelectRow;

};

#endif // MYTREEVIEW_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QRect>

QT_BEGIN_NAMESPACE
class QCloseEvent;
QT_END_NAMESPACE

class FileOper;

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

protected:
    void initWidget();
    void closeEvent(QCloseEvent *event);

private:
    Ui::Widget *ui;

    QRect m_screenRect;
    FileOper *m_fileOper;
};

#endif // WIDGET_H

adddialog.cpp

#include "adddialog.h"
#include "ui_adddialog.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QDebug>

AddDialog::AddDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::AddDialog)
{
    ui->setupUi(this);

    m_addData = new AddData;

    this->setWindowTitle("添加");
    ui->selectShellLineEdit->setEnabled(false);
    connect(ui->okPushButton, SIGNAL(clicked(bool)), this, SLOT(okBtnClicked()));
    connect(ui->selectPushButton, SIGNAL(clicked(bool)), this, SLOT(selectBtnClicked()));
}

AddData *AddDialog::getAddData()
{
    return m_addData;
}

void AddDialog::setNameAndFilePath(const QString name, const QString filePath)
{
    this->setWindowTitle("编辑");
    ui->nameLineEdit->setText(name);
    ui->selectShellLineEdit->setText(filePath);
}

AddDialog::~AddDialog()
{
    delete ui;
    delete m_addData;
}

void AddDialog::closeEvent(QCloseEvent *event)
{
    Q_UNUSED(event)
    this->reject();
}

void AddDialog::okBtnClicked(){

    if(ui->nameLineEdit->text().isEmpty() || ui->selectShellLineEdit->text().isEmpty()){

        QMessageBox::information(this, "提示", "LineEdit不能为空");
        return;
    }
    int btnClicked = QMessageBox::information(this, "提示", "是否确定保存?", QMessageBox::Save, QMessageBox::Cancel);

    if(btnClicked == QMessageBox::Save){

        m_addData->name = ui->nameLineEdit->text();
        m_addData->shellFilePath = ui->selectShellLineEdit->text();
        this->accept();
    }
}

void AddDialog::selectBtnClicked()
{
    QString fileName = QFileDialog::getOpenFileName(this, "选择shell文件", "/home", "Shell Files(*.sh)");
    ui->selectShellLineEdit->setText(fileName);
}

fileoper.cpp

#include "fileoper.h"
#include <QDebug>
#include <QTextStream>
#include <QFile>

FileOper::FileOper(const QString fileName)
{
    m_fileName = fileName;
}

FileOper::~FileOper()
{
    qDebug()<< "~FileOper() called";
}

QVector<QString> &FileOper::getContextVec()
{
    return m_contextVec;
}

void FileOper::clearContextVec()
{
    m_contextVec.clear();
}

void FileOper::saveFile()
{
    QFile file(m_fileName);
    if(!file.open(QFile::WriteOnly | QFile::Text)){
        throw "file can't open";
    }

    QTextStream out(&file);
    for(int i = 0; i < m_contextVec.size(); i++){
        out << m_contextVec[i] << "\n";
    }
    file.close();
}

void FileOper::readFile()
{
    QFile file(m_fileName);
    if(!file.open(QFile::ReadOnly | QFile::Text)){
        throw "file open failed";
    }

    QTextStream in(&file);
    while(!in.atEnd()){
        m_contextVec << in.readLine();
    }
    file.close();
}

main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

mydelegate.cpp

#include "mydelegate.h"
#include "myonoff.h"
#include "myonoffeditor.h"

#include <QPainter>
#include <QDebug>
#include <QTextItem>

MyDelegate::MyDelegate(QWidget *parent) : QStyledItemDelegate(parent)
{

}

void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if(index.column() == 1){

        if(option.state & QStyle::State_Selected){
            painter->fillRect(option.rect, option.palette.highlight());
        }

        painter->save();
        painter->setPen(Qt::black);
        painter->drawText(option.rect.x(), option.rect.y(), option.rect.width(), option.rect.height(), Qt::AlignCenter, "双击查看及修改文件路径");
        painter->restore();
    }
    else if(index.data().canConvert<MyOnOff>()){

        if(option.state & QStyle::State_Selected){
            painter->fillRect(option.rect, option.palette.highlight());
        }

        MyOnOff myOnOff = qvariant_cast<MyOnOff>(index.data());
        myOnOff.painter(painter, option.rect, option.palette, MyOnOff::ReadOnly);
    }
    else{

        QStyledItemDelegate::paint(painter, option, index);
    }
}

QSize MyDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QSize size = QStyledItemDelegate::sizeHint(option, index);
    size.setHeight(size.height() + 12);
    return size;
}

QWidget *MyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    Q_UNUSED(option)

    if(index.data().canConvert<MyOnOff>()){

        MyOnOffEditor *editor = new MyOnOffEditor(parent);
        MyOnOff myOnOff = qvariant_cast<MyOnOff>(index.data());
        editor->setMyOnOffStatus(myOnOff.getIsOpenStatus());
        return editor;
    }
    else{
        return NULL;
    }
}

void MyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    Q_UNUSED(index)

    if(index.data().canConvert<MyOnOff>()){

        MyOnOff myOnOff = qvariant_cast<MyOnOff>(index.data());
        MyOnOffEditor *myOnOffEditor = qobject_cast<MyOnOffEditor*>(editor);
        myOnOffEditor->setMyOnOffStatus(!myOnOff.getIsOpenStatus());
    }
    else{
        QStyledItemDelegate::setEditorData(editor, index);
    }
}

void MyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    if(index.data().canConvert<MyOnOff>()){

        MyOnOffEditor *myOnOffEditor = qobject_cast<MyOnOffEditor*>(editor);
        model->setData(index, QVariant::fromValue(MyOnOff(myOnOffEditor->getMyOnOffStatus())));
    }
    else
        QStyledItemDelegate::setModelData(editor, model, index);
}

myonoff.cpp

#include "myonoff.h"
#include <QImage>
#include <QPainter>
#include <QPalette>
#include <QDebug>

MyOnOff::MyOnOff(const bool isOpenStatus)
{
    m_isOpen = isOpenStatus;
}

bool MyOnOff::getIsOpenStatus()
{
    return m_isOpen;
}

void MyOnOff::setIsOpenStatus(const bool isOpenStatus)
{
    m_isOpen = isOpenStatus;
}

void MyOnOff::painter(QPainter *painter, const QRect &rect, const QPalette palette, EditMode mode) const
{
    painter->setRenderHint(QPainter::Antialiasing, true);
    painter->save();

    if(mode == Editable){
        painter->setBrush(palette.highlight());
    }
    else{
        painter->setBrush(palette.foreground());
    }

    if(m_isOpen){
        painter->drawImage(rect.x() + 45, rect.y(), QImage(":/img/imgOpen.png"));
    }
    else{
        painter->drawImage(rect.x() + 45, rect.y(), QImage(":/img/imgClose.png"));
    }
    painter->restore();
}

myonoffeditro.cpp

#include "myonoffeditor.h"
#include <QPainter>
#include <QDebug>

MyOnOffEditor::MyOnOffEditor(QWidget *parent) : QWidget(parent)
{
    setMouseTracking(true);
    setAutoFillBackground(true);
}

void MyOnOffEditor::setMyOnOffStatus(const bool myOnOffStatus)
{
    m_myOnOff.setIsOpenStatus(myOnOffStatus);
}

bool MyOnOffEditor::getMyOnOffStatus()
{
    return m_myOnOff.getIsOpenStatus();
}

void MyOnOffEditor::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)

    QPainter painter(this);
    painter.save();
    m_myOnOff.painter(&painter, rect(), this->palette(), MyOnOff::Editable);
    painter.restore();
}

mytreeview.cpp

#include "mytreeview.h"
#include <QContextMenuEvent>
#include <QMenu>
#include <QDebug>
#include <QStandardItemModel>

#include <QAbstractItemModel>
#include <QModelIndex>
#include "adddialog.h"
#include "myonoff.h"

MyTreeView::MyTreeView(QWidget *parent)
    : QTreeView(parent)
{
    m_currentSelectRow = -1;
    connect(this, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(doubleCilckedCalled(QModelIndex)));
}

void MyTreeView::initWidget(const QVector<QString> vec)
{
    for(int i = 0; i < vec.size(); i++){
        QStringList nameAndPath = vec[i].split(";");
        addItem(nameAndPath[0], nameAndPath[1]);
    }
}

void MyTreeView::contextMenuEvent(QContextMenuEvent *event)
{
    QMenu menu;
    menu.addAction("添加", this, SLOT(addContextMenuCalled()));

    static_cast<QStandardItemModel*>(model());
    QModelIndex index = indexAt(event->pos());
    if(index.isValid()){

        m_currentSelectRow = index.row();
        menu.addAction("删除", this, SLOT(removeContextMenuCalled()));
    }
    menu.exec(event->globalPos());
}

void MyTreeView::addItem(const QString name, const QString filePath)
{
    int rowCount = model()->rowCount();
    static_cast<QStandardItemModel*>(model())->setItem(rowCount, 0, new QStandardItem(name));
    static_cast<QStandardItemModel*>(model())->setItem(rowCount, 1, new QStandardItem(filePath));

    QStandardItem *myOnOff = new QStandardItem;
    myOnOff->setData(QVariant::fromValue(MyOnOff(false)), 0);
    static_cast<QStandardItemModel*>(model())->setItem(rowCount, 2, myOnOff);
}

void MyTreeView::addContextMenuCalled()
{
    AddDialog addDialog;

    if(addDialog.exec() == QDialog::Accepted){

        //qDebug()<< addDialog.getAddData()->name << "\t" <<addDialog.getAddData()->shellFilePath;
        addItem(addDialog.getAddData()->name, addDialog.getAddData()->shellFilePath);
    }


}

void MyTreeView::removeContextMenuCalled()
{
    if(m_currentSelectRow != -1){

        static_cast<QStandardItemModel*>(model())->removeRow(m_currentSelectRow);
        m_currentSelectRow = -1;
    }
}

void MyTreeView::doubleCilckedCalled(const QModelIndex &index)
{
    if(index.column() == 1){

        QString name = static_cast<QStandardItemModel*>(model())->item(index.row(), 0)->data(0).toString();
        QString filePath = static_cast<QStandardItemModel*>(model())->item(index.row(), 1)->data(0).toString();

        AddDialog editDialog;
        editDialog.setNameAndFilePath(name, filePath);
        if(editDialog.exec() == QDialog::Accepted){

            QString newName = editDialog.getAddData()->name;
            QString newPath = editDialog.getAddData()->shellFilePath;

            static_cast<QStandardItemModel*>(model())->item(index.row(), 0)->setData(newName, 0);
            static_cast<QStandardItemModel*>(model())->item(index.row(), 1)->setData(newPath, 0);
        }
    }
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include "mydelegate.h"
#include "myonoff.h"
#include "fileoper.h"

#include <QDesktopWidget>
#include <QVariant>
#include <QDebug>
#include <QCloseEvent>
#include <QHeaderView>
#include <QMessageBox>
#include <QStandardItemModel>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    m_fileOper = new FileOper("context.txt");

    m_fileOper->readFile();
    initWidget();
}

Widget::~Widget()
{
    delete ui;
    delete m_fileOper;
}

void Widget::initWidget()
{
    m_screenRect = QApplication::desktop()->screenGeometry();
    move((m_screenRect.width() - this->width())/2, (m_screenRect.height() - this->height())/2);


    QStringList headerLables;
    headerLables << "名称" << "shell文件路径" << "当前状态";

    QStandardItemModel *stdModel = new QStandardItemModel;
    stdModel->setHorizontalHeaderLabels(headerLables);
    ui->treeView->setModel(stdModel);
    ui->treeView->setEditTriggers(QAbstractItemView::DoubleClicked);
    ui->treeView->setItemDelegate(new MyDelegate);
    ui->treeView->initWidget(m_fileOper->getContextVec());

    ui->treeView->header()->setSectionResizeMode(1, QHeaderView::Stretch);
    ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Fixed);
    ui->treeView->header()->setSectionResizeMode(2, QHeaderView::Fixed);
}

void Widget::closeEvent(QCloseEvent *event)
{
    int result = QMessageBox::information(this, "提示", "是否保存", QMessageBox::Ok, QMessageBox::Cancel);
    if(result == QMessageBox::Ok){

        m_fileOper->clearContextVec();
        for(int i = 0; i < ui->treeView->model()->rowCount(); i++){
            QString name = static_cast<QStandardItemModel*>(ui->treeView->model())->item(i, 0)->data(0).toString();
            QString path = static_cast<QStandardItemModel*>(ui->treeView->model())->item(i, 1)->data(0).toString();
            m_fileOper->getContextVec() << name + ";" + path;
        }

        try{
            m_fileOper->saveFile();
            qApp->exit();
        }
        catch(const char *err){
            qDebug()<< err;
        }

    }
    else if(result == QMessageBox::Cancel){
        qApp->exit();
    }
    else{

    }
    event->ignore();
}

猜你喜欢

转载自blog.csdn.net/qq78442761/article/details/84565120