zoukankan      html  css  js  c++  java
  • QTreeWidget实现一个打包小工具

    不要低估你的能力,不要高估你的毅力。

    前言

    最近因为需要,着手写了个打包工具,功能挺简单的,目前就是基本的文件和文件夹复制。由于要求使用QT进行开发,个人又没有学过,因此完成下面的内容确实花了不少时间。由于网上的资源较少,而且达不到想要的效果,因此自己动手实现了许多功能,代码可能较为冗余(哭),好在功能实现了,多少有了点欣慰之感。

    效果展示

    首先,先给出几张效果展示图,目前没有任何美化,只是完成了功能,还有很大的改善空间。

    1.运行截图为:

    2.从上到下,分为三个板块,功能相同,具体演示为:

    就是先打开一个文件夹,然后选择复制文件夹目录,选择复制即可。至于remove,可用于复制出错后删除相应文件,而generate按钮用于自动检索打开文件夹是否有批处理文件,有的话就执行。

    这个小工具的难点在于文件夹的树形展示和对相应选中文件的操作。在开始制作时,首先是想在网上找找有没有相应的例子,但遗憾的是找到的都是相应用法(只是将项目通过QT展现出来),没有相关操作。QT好像也没有相应的函数,所以根据QT的QTreeWidget中自带的特性,东补西凑地完成了。

    具体实现

    这里主要采用了QTreeWidget,前期网上很多都是使用QtreeView,但QTreeView好像主要用于展示,对展示后的相关操作比较麻烦,而且效果不太好,于是转向了QTreeWidget。二者主要区别:

    • QTreeView一般和相应的QXXModel合用,形成Model/View结构.

    • QTreeWidget继承自QTreeView ,是封闭了默认Model的QTreeView,其中的元素是QTreeWidgetItem类型,要插入只需将新建QTreeWidgetItem的父类设为指定的QTreeWidget就行(在QTreeWidgetItem的构造函数中指定),要删除直接delete掉QTreeWidgetItem就行

    两者的具体区别在此不多说,根据实际需要选择吧,这个小工具QTreeWidget比较适合,下面是实现源码。

    实现源码

    代码质量一般,其实相关功能的实现有多中方法,这里用的都是比较简单的,这里仅供参考。

    在QT中新建一个widgets项目,命名为Robust,更改相应内容如下:

    robust.h

    #ifndef ROBUST_H
    #define ROBUST_H
    
    #include "subqtreewidgetitem.h"
    #include "externarg.h"
    #include <qmainwindow>
    #include <qwidget>
    #include <qmessagebox>
    #include <qstring>
    #include <qfilesystemmodel>
    #include <qfiledialog>
    #include <qlist>
    #include <qfileinfolist>
    #include <qtreewidget>
    #include <qtreewidgetitem>
    #include <qprocess>
    #include <qdebug>
    
    namespace Ui {
    class Robust;
    }
    
    class Robust : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit Robust(QWidget *parent = 0);
        QFileInfoList allfile(subQTreeWidgetItem *root,QString path);
        ~Robust();
        void copy(QString openPath, QString selectPath, QTreeWidget * treeWidget, QTreeWidget * toTreeWidget);
        bool copyFileToPath(QString sourceDir ,QString toDir, bool coverFileIfExist);
        bool copyDirectoryFiles(const QString &fromDir, const QString &toDir, bool coverFileIfExist);
        QString treeItemToFullPath(QTreeWidgetItem* treeItem);
        void updateTreeWidgetShow(QString openPath, QTreeWidget * treeWidget);
        void updateTreeWidgetOpen(QString openPath, QTreeWidget * treeWidget);
        void remove(QString sourcePath, QTreeWidget *treeWidget);
        bool openFolder(QString openDir, QTreeWidget * treeWidget);
        bool generate(QString openPath,QTreeWidget * treeWidget);
    
    private slots:
        void on_open_proj_clicked();
        void on_copy_button_clicked();
        void on_selectPath_clicked();
        void on_generate_clicked();
        void on_remove_clicked();
        void on_open_proj_2_clicked();
        void on_copy_2_clicked();
        void on_selectPath_2_clicked();
        void on_generate_2_clicked();
        void on_remove_2_clicked();
        void on_open_proj_3_clicked();
        void on_copy_3_clicked();
        void on_selectPath_3_clicked();
        void on_generate_3_clicked();
        void on_remove_3_clicked();
    
    private:
        Ui::Robust *ui;
        QFileSystemModel *info;
    };
    
    #endif // ROBUST_H
    
    

    externarg.h

    #ifndef EXTERNARG
    #define EXTERNARG
    
    #endif // EXTERNARG
    #include <qstring>
    class ExternArg
    {
    public:
        ExternArg();
        //打开文件夹路径(不含文件夹名)
        static QString OPEN_PATH_1;
        //选择安装文件夹路径
        static QString SELECT_PATH_1;
        //打开文件件路径(包括文件夹名称)
        static QString OPEN_DIR_1;
    
        //打开文件夹路径(不含文件夹名)
        static QString OPEN_PATH_2;
        //选择安装文件夹路径
        static QString SELECT_PATH_2;
        //打开文件件路径(包括文件夹名称)
        static QString OPEN_DIR_2;
    
        //打开文件夹路径(不含文件夹名)
        static QString OPEN_PATH_3;
        //选择安装文件夹路径
        static QString SELECT_PATH_3;
        //打开文件件路径(包括文件夹名称)
        static QString OPEN_DIR_3;
    };
    

    subqtreewidgetitem.h

    #ifndef SUBQTREEWIDGETITEM
    #define SUBQTREEWIDGETITEM
    
    #endif // SUBQTREEWIDGETITEM
    #include <qtreewidgetitem>
    #pragma once
    class subQTreeWidgetItem : public QTreeWidgetItem
    {
    
    public:
        QString absPath;
        explicit subQTreeWidgetItem(const QStringList &strings, int type = Type);
        explicit subQTreeWidgetItem(QTreeWidget *view, int type = Type);
        subQTreeWidgetItem(QTreeWidget *view, const QStringList &strings, int type = Type);
    };
    

    robust.cpp

    这里只留到第一部分的代码,第二三部分类似。

    #include "robust.h"
    #include "ui_robust.h"
    
    Robust::Robust(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::Robust)
    {
        ui->setupUi(this);
    }
    
    Robust::~Robust()
    {
        delete ui;
    }
    
    
    /************************************************  基本功能的实现  **************************************************************/
    
    
    //打开文件夹,并以树形目录展示
    bool Robust::openFolder(QString openDir, QTreeWidget * treeWidget)
    {
        bool ok;
        if(QFile::exists(openDir))
        {
            treeWidget->clear();
            treeWidget->setHeaderLabel("project view");
            treeWidget->setSortingEnabled(true);
    //        treeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
            treeWidget->setSelectionMode(QAbstractItemView::MultiSelection);
            subQTreeWidgetItem* root = new subQTreeWidgetItem(treeWidget,QStringList()<<opendir); 设置一级目录展开="" qstringlist="" list="openDir.split("/");" int="" len="list.length();" root-="">setExpanded(true);
            root->setFirstColumnSpanned(true);
            root->setText(0,list.at(len-1));
            root->setIcon(0, QIcon(":/new/src/sourceFile/ico/proj.png"));
            root->setSelected(true);
            root->setCheckState(1, Qt::Checked);
            allfile(root,openDir);
            ok =true;
            return ok;
        }
        else
        {
            ok =false;
            return ok;
        }
    }
    
    //递归打开文件夹以树形结构显示的具体实现
    QFileInfoList Robust::allfile(subQTreeWidgetItem *root,QString path)
    {
        QDir dir(path);          //遍历各级子目录
        QDir dir_file(path);    //遍历子目录中所有文件
        dir_file.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);        //获取当前所有文件
        dir_file.setSorting(QDir::Size | QDir::Reversed);
        QFileInfoList list_file = dir_file.entryInfoList();
        for (int i = 0; i < list_file.size(); ++i) {       //将当前目录中所有文件添加到treewidget中
            QFileInfo fileInfo = list_file.at(i);
            QString name2=fileInfo.fileName();
            subQTreeWidgetItem* child = new subQTreeWidgetItem(QStringList()<<name2); child-="">setToolTip(0, path+"/"+name2);
            child->absPath = path+"/"+name2;
            child->setIcon(0, QIcon(":/new/src/sourceFile/ico/file_blue.png"));
            child->setCheckState(1, Qt::Checked);
            root->addChild(child);
        }
        QFileInfoList folder_list = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);   //获取当前所有目录
        QFileInfoList file_list=dir.entryInfoList(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
    
        for(int i = 0; i != folder_list.size(); i++)         //自动递归添加各目录到上一级目录
        {
            QString namepath = folder_list.at(i).absoluteFilePath();    //获取路径
            QFileInfo folderinfo= folder_list.at(i);
            QString name=folderinfo.fileName();      //获取目录名
            subQTreeWidgetItem* childroot = new subQTreeWidgetItem(QStringList()<<name); childroot-="">setToolTip(0, path+"/"+name);
            childroot->absPath = path+"/"+name;
            childroot->setIcon(0, QIcon(":/new/src/sourceFile/ico/dir.png"));
            childroot->setCheckState(1, Qt::Checked);
            root->addChild(childroot);              //将当前目录添加成path的子项
            QFileInfoList child_file_list = allfile(childroot,namepath);          //进行递归
            file_list.append(child_file_list);
            file_list.append(name);
        }
        return file_list;
    }
    
    //打开工程模块的显示更新
    void Robust::updateTreeWidgetOpen(QString openPath, QTreeWidget * treeWidget)
    {
        openFolder(openPath,treeWidget);
    }
    
    //递归获取所选文件或目录的相对路径,在这个基础上加上打开文件夹时的路径(没有文件夹名的路径),构成绝对路径。
    QString Robust::treeItemToFullPath(QTreeWidgetItem* treeItem)
    {
        QString fullPath= treeItem->text(0);
        while (treeItem->parent() != NULL)
        {
            fullPath= treeItem->parent()->text(0) + "/" + fullPath;
            treeItem = treeItem->parent();
        }
        return fullPath;
    }
    
    //文件和目录拷贝,这是为拷贝设置相应的路径和调用刷新treeWidget的内容显示。
    void Robust::copy(QString openPath, QString selectPath, QTreeWidget * treeWidget, QTreeWidget * toTreeWidget)
    {
        QList<qtreewidgetitem *=""> itemList;
        QString sourcePath;
        itemList = treeWidget->selectedItems();
        foreach(QTreeWidgetItem *item, itemList)
        {
            sourcePath = openPath + treeItemToFullPath(item);
    //      QString sourcePath= openPath + treeItemToFullPath(treeWidget->selectedItems().first());
            QFileInfo *info;
            info = new QFileInfo(sourcePath);
            QString destPath;
            qDebug()<<"the source path:"<<sourcepath; if="" (qfile::exists(selectpath))="" {="" 复制到所选择的目录="" destpath="selectPath+"/"+info-">fileName();
                qDebug()<<"select path"<<destpath; }="" else="" {="" qmessagebox::information(this,tr("warning"),tr("need="" select="" path"));="" return;="" 如果目标路径包含原路径,则跳过,否则将递归进入死循环="" if(destpath.contains(sourcepath,="" qt::casesensitive)){="" qdebug()<<"contains";="" continue;="" if(!info-="">isDir()){
                qDebug()<<"destirtion path:"<<destpath; bool="" ok="copyFileToPath(sourcePath,destPath,true);" qdebug()<<"file:="" "<<ok;="" }="" else="" {="" qdebug()<<"destirtion="" path:"<<destpath;="" qdebug()<<"dir:="" updatetreewidgetshow(selectpath,="" totreewidget);="" 拷贝文件的具体实现="" robust::copyfiletopath(qstring="" sourcefile="" ,qstring="" tofile,="" coverfileifexist)="" tofile.replace("\\","="" ");="" if="" (sourcefile="=" tofile){="" return="" true;="" (!qfile::exists(sourcefile)){="" false;="" qdir="" *createfile="new" qdir;="" exist="createfile-">exists(toFile);
        if (exist){
            if(coverFileIfExist){
                createfile->remove(toFile);
            }
        }//end if
    
        if(!QFile::copy(sourceFile, toFile))
        {
            return false;
        }
        return true;
    }
    
    //拷贝文件夹的具体实现
    bool Robust::copyDirectoryFiles(const QString &fromDir, const QString &toDir, bool coverFileIfExist)
    {
        QDir sourceDir(fromDir);
        QDir targetDir(toDir);
        if(!targetDir.exists()){   //如果目标目录不存在,则进行创建
            if(!targetDir.mkdir(targetDir.absolutePath()))
                return false;
        }
    
        QFileInfoList fileInfoList = sourceDir.entryInfoList();
        foreach(QFileInfo fileInfo, fileInfoList){
            if(fileInfo.fileName() == "." || fileInfo.fileName() == "..")
                continue;
    
            if(fileInfo.isDir()){    //当为目录时,递归的进行copy
                if(!copyDirectoryFiles(fileInfo.filePath(),
                                       targetDir.filePath(fileInfo.fileName()),
                                       coverFileIfExist))
                    return false;
            }
            else{            //当允许覆盖操作时,将旧文件进行删除操作
                if(coverFileIfExist && targetDir.exists(fileInfo.fileName())){
                    targetDir.remove(fileInfo.fileName());
                }
    
                // 进行文件copy
                if(!QFile::copy(fileInfo.filePath(),
                                targetDir.filePath(fileInfo.fileName()))){
                    return false;
                }
            }
        }
        return true;
    }
    
    //复制到所在目录的显示更新
    void Robust::updateTreeWidgetShow(QString openPath, QTreeWidget * treeWidget)
    {
        treeWidget->clear();
        QString aimPath;
        if (QFile::exists(openPath)){
            //复制到所选择的目录
            aimPath = openPath;
        }
        else
        {
            QMessageBox::information(this,tr("warning"),tr("need to select path"));
            return;
        }
        treeWidget->setHeaderLabel("the copy file");
        treeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
        treeWidget->setSortingEnabled(true);
        subQTreeWidgetItem* root1 = new subQTreeWidgetItem(treeWidget,QStringList()<<aimpath); 设置一级目录展开="" root1-="">setExpanded(true);
        root1->setFirstColumnSpanned(true);
        QStringList list1 = aimPath.split("/");
        int len1 = list1.length();
        root1->setText(0,list1.at(len1-1));
        root1->setIcon(0, QIcon(":/new/src/sourceFile/ico/proj.png"));
        root1->setSelected(true);
        root1->setCheckState(1, Qt::Checked);
        allfile(root1,aimPath);
    }
    
    //文件生成(编译)
    bool Robust::generate(QString openPath,QTreeWidget * treeWidget)
    {
        QDir dir(openPath);
        dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
        dir.setSorting(QDir::Size | QDir::Reversed);
    
        QFileInfoList list = dir.entryInfoList();
        for (int i = 0; i < list.size(); ++i) {
            QFileInfo fileInfo = list.at(i);
            if(fileInfo.suffix() == "bat")
            {
                QString filepath;
                filepath.append(fileInfo.path());
                qDebug()<<filepath; qprocess="" p(0);="" p.setworkingdirectory(filepath);="" 指定进程的工作目录="" filepath+="/" +fileinfo.filename();="" qdebug()<<filepath;="" qstring="" command="filepath;" p.start(command);="" p.waitforfinished();="" qdebug()<<"the="" result="" of="" exec="" bat:"<<qstring::fromlocal8bit(p.readallstandarderror());="" }="" updatetreewidgetopen(openpath,treewidget);="" return="" 1;="" 删除文件或文件夹="" void="" robust::remove(qstring="" selectpath,="" qtreewidget="" *treewidget)="" {="" int="" lastindex="selectPath.lastIndexOf("/")+1;" tempath="selectPath.mid(0,lastIndex)" +="" treeitemtofullpath(treewidget-="">selectedItems().first());
        qDebug()<<"the source path:"<<tempath; if(tempath="=" selectpath)="" {="" qmessagebox::information(this,tr("warning"),tr("can't="" remove="" the="" select="" dir"));="" return;="" }="" else="" qfileinfo="" *info;="" info="new" qfileinfo(tempath);="" if(info-="">isDir())
            {
                QDir tem = QDir(temPath);
                bool ok = tem.removeRecursively();
                qDebug()<<ok; }="" else="" {="" qfile="" *tem;="" tem="new" qfile(tempath);="" bool="" ok="tem-">remove();
                qDebug()<<ok; }="" updatetreewidgetshow(selectpath,="" treewidget);="" ************************************************="" 下面是各个模块的具体调用="" **************************************************************="" ********="" 第一板块的调用(treewidget_1和treewidget_2)="" ************="" 打开某个文件夹,并通过treewidget_1显示。="" void="" robust::on_open_proj_clicked()="" {="" externarg::open_dir_1="QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this," tr("view="" file"),="" qdir::currentpath()));="" qstring="" aimpath="ExternArg::OPEN_DIR_1.replace("\\","/");" qdebug()<<aimpath;="" qfileinfo="" *="" tem;="" tem="new" qfileinfo(aimpath);="" qdebug()<<"absolute="" path:="" "<<tem-="">absolutePath();
        //这里设置全局变量用于下面复制时的路径构造
        int i = tem->absolutePath().lastIndexOf("/");
        if(i == tem->absolutePath().length()-1)
        {
            ExternArg::OPEN_PATH_1 = tem->absolutePath();
        }
        else
        {
            ExternArg::OPEN_PATH_1 = tem->absolutePath()+"/";
        }
        qDebug()<<"ExternArg::OPEN_PATH"<<externarg::open_path_1; bool="" ok="openFolder(ExternArg::OPEN_DIR_1," ui-="">treeWidget_1);
        qDebug()<<ok; }="" 拷贝函数的调用="" void="" robust::on_copy_button_clicked()="" {="" copy(externarg::open_path_1,externarg::select_path_1,="" ui-="">treeWidget_1, ui->treeWidget_2);
    }
    
    //选择路径
    void Robust::on_selectPath_clicked()
    {
        QString path = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this, tr("view file"), QDir::currentPath()));
        ExternArg::SELECT_PATH_1 = path.replace("\\","/");
    }
    
    //编译调用
    void Robust::on_generate_clicked()
    {
        QString path = ExternArg::OPEN_DIR_1;
        bool ok = generate(path, ui->treeWidget_1);
        qDebug()<<ok; }="" 复制到所在文件夹的文件删除或文件夹删除="" void="" robust::on_remove_clicked()="" {="" qstring="" sourcepath="ExternArg::SELECT_PATH_1;" if(!qfile::exists(sourcepath))="" qmessagebox::information(this,tr("warning"),tr("need="" select="" path"));="" return;="" remove(sourcepath,ui-="">treeWidget_2);
    }
    

    externarg.cpp

    #include "externarg.h"
    
    ExternArg::ExternArg() {}
    
    QString ExternArg::OPEN_PATH_1 = "";
    QString ExternArg::SELECT_PATH_1 = "";
    QString ExternArg::OPEN_DIR_1 = "";
    
    QString ExternArg::OPEN_PATH_2 = "";
    QString ExternArg::SELECT_PATH_2 = "";
    QString ExternArg::OPEN_DIR_2 = "";
    
    QString ExternArg::OPEN_PATH_3 = "";
    QString ExternArg::SELECT_PATH_3 = "";
    QString ExternArg::OPEN_DIR_3 = "";
    

    subqtreewidgetitem.cpp

    #include "subqtreewidgetitem.h"
    
    subQTreeWidgetItem::subQTreeWidgetItem(const QStringList &strings1, int type1)
        :QTreeWidgetItem(strings1,type1)
    {
        absPath = "";
    }
    subQTreeWidgetItem::subQTreeWidgetItem(QTreeWidget *view1, int type1)
        :QTreeWidgetItem(view1, type1)
    {
        absPath = "";
    }
    subQTreeWidgetItem::subQTreeWidgetItem(QTreeWidget *view1, const QStringList &strings1, int type1)
        :QTreeWidgetItem(view1, strings1, type1)
    {
        absPath = "";
    }
    

    main.cpp

    #include "robust.h"
    #include "subqtreewidgetitem.h"
    #include <qapplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Robust w;
        w.show();
    
        return a.exec();
    }
    
    感谢阅读,如有问题,请批评指正,谢谢。
  • 相关阅读:
    用户 NT AUTHORITY\NETWORK SERVICE 登录失败解决方法
    [转]改变ASP.NET 2.0中的Membership的密码要求
    WINDOWS2003自动开关机的实现
    解决ASP.NET 的进程帐户没有访问 IIS的权限[转]
    byron的一首好诗
    推荐一个好用的日期控件
    程序员喝酒文化
    快速清除Word文档多余空行
    net2.0"服务器应用程序不可用"问题解决[转]
    GridView的第一列是ButtonField,字段名是"删除",想一点之后弹出确认框,否则返回.应该如何写?
  • 原文地址:https://www.cnblogs.com/clwsec/p/15679931.html
Copyright © 2011-2022 走看看