整体源码下载如下:
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();
}