我的工具 Qt( 1.< 截图工具> 、2. <流布局,自动换行>、3. <基本消息框>、4.<正则表达式,包含给表格设置>、5.<文件目录操作、读写,拷贝,删除,清空等>、6.<输出信息到屏幕,精确显示信息所在的文件的行>)

#ifndef WANGCHUAN_H
#define WANGCHUAN_H

#define WC_QT 1  // 如果当前项目是qt则置1,纯c++则置0

#if WC_QT
#include <QGuiApplication>
#include <QPixmap>
#include <QWidget>
#include <QMenu>
#include <QPoint>
#include <QSize>
#include <QMouseEvent>
#include <QPushButton>
#include <QtDebug>
#include <QDesktopWidget>
#include <QMutex>
#include <QApplication>
#include <QPainter>
#include <QFileDialog>
#include <QEvent>
#include <QDateTime>
#include <QStringList>
#include <QScreen>
#include <QLayout>
#include <QStyle>
#include <QMessageBox>
#include <QRegExpValidator>
#include <QStyleOptionViewItem>
#include <QItemDelegate>
#include <QLineEdit>
#include <QStyledItemDelegate>
#include <QJsonParseError>
#include <QTextCodec>
#endif
#include <vector>
#include <fstream>
#include <filesystem>
#include <iostream>

// 6、输出日志信息到屏幕
//   [详细显示输出信息的位置,精确到所在文件的行]
// 使用 : wc_LOG(...)   //直接调用宏函数
// 使用c的printf格式进行输出。
// eg:
//    wc_LOG("%s%d","输出结果:",23);
//    wc_LOG("%s","你好世界!");
//    wc_LOG("%d",100);
#define wc_LOG(...){\
printf("%s","\n>> >> >>\n");\
    printf("%10s","日志:\n");\
    printf("%s%s%s","\t在",__FILE__,"文件中,\n");\
    printf("%s%d%s","\t第",__LINE__,"行。\n");\
    printf("%s","\t");\
    printf(__VA_ARGS__);\
    printf("%s","\n<< << <<\n");\
}

/*
 * 工具:
 *
 * 1、<截取屏幕工具>
 *       位置——>99行
 *       详见:Screenshot
 *
 * 2、<流布局>
 *       位置——>425行
 *       功能:
 *          【如果软件界面窗口大小发生变化,布局里面的控件,进行自动换行】
 *       详见:FlowLayout
 *
 * 3、<基本消息框>
 *       位置——>639行
 *       功能:
 *          【question消息,疑问消息框;information消息框  信息消息框;warning消息框 警告消息框;critical消息框】
 *       详见:Message
 *
 * 4、<正则表达式>
 *        位置——>736行
 *        功能:
 *            包含(用于给表格设置正则表达式,)
 *            总结项目中常用表达式格式
 *        详见:Messagebox
 *
 * 5、<操作文件/目录>
 *        位置——>783行
 *        功能:
 *            【Qt:创建新目录、获取程序所在路经、枚举目录下所有文件、枚举目录下所有目录、清空目录】
 *            【c++:删除目录、创建目录、初始化目录u、获取程序所在目录、绝对路经、获取目录下的所有文件、一个文件覆盖另一个文件、删除文件、读取文件内容】
 *        详见:FileManage
 *
 * 6、<输出日志信息到屏幕>
 *        位置——>39行
 *        功能:
 *            【详细显示输出内容所在的文件,以及所在的具体行数】
 *        详见:wc_LOG()
 *
 */
namespace wangchuan{
#if WC_QT
    namespace Screenshot
    {
        // 1、截取屏幕工具
        // 使用 : ScreenWidget::Instance()->showFullScreen();   //直接调用实例
        // 可以在程序重写一个键盘事件,通过快捷键来调用该实例
        // eg:
            //    virtual void keyPressEvent(QKeyEvent * event) override
            //    {
            //        switch (event->key())
            //        {
            //            // F1键
            //            case Qt::Key_F1:
            //                qDebug() <<"F1";
            //                wangchuan::Screenshot::ScreenWidget::Instance()->showFullScreen();   //直接调用实例
            //            break;
            //        }
            //    }

        #define STRDATETIME qPrintable (QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"))
        //截屏对象类
        class Screen
        {
        public:
            enum STATUS {SELECT, MOV, SET_W_H};
            Screen() {}
            Screen(QSize size)
            {
                maxWidth = size.width();
                maxHeight = size.height();
                startPos = QPoint(-1, -1);
                endPos = startPos;
                leftUpPos = startPos;
                rightDownPos = startPos;
                status = SELECT;
            }
            void setStart(QPoint pos)
            {
                startPos = pos;
            }
            void setEnd(QPoint pos)
            {
                endPos = pos;
                leftUpPos = startPos;
                rightDownPos = endPos;
                cmpPoint(leftUpPos, rightDownPos);
            }
            QPoint getStart()
            {
                return startPos;
            }
            QPoint getEnd()
            {
                return endPos;
            }

            QPoint getLeftUp()
            {
                return leftUpPos;
            }
            QPoint getRightDown()
            {
                return rightDownPos;
            }

            STATUS getStatus()
            {
                return status;
            }

            void setStatus(STATUS status)
            {
                this->status = status;
            }

            int width()
            {
                return maxWidth;
            }
            int height()
            {
                return maxHeight;
            }
            bool isInArea(QPoint pos)          // 检测pos是否在截图区域内
            {
                if (pos.x() > leftUpPos.x() && pos.x() < rightDownPos.x() && pos.y() > leftUpPos.y() && pos.y() < rightDownPos.y()) {
                    return true;
                }
                return false;
            }
            void move(QPoint p)                // 按 p 移动截图区域
            {
                int lx = leftUpPos.x() + p.x();
                int ly = leftUpPos.y() + p.y();
                int rx = rightDownPos.x() + p.x();
                int ry = rightDownPos.y() + p.y();
                if (lx < 0) {
                    lx = 0;
                    rx -= p.x();
                }
                if (ly < 0) {
                    ly = 0;
                    ry -= p.y();
                }
                if (rx > maxWidth)  {
                    rx = maxWidth;
                    lx -= p.x();
                }
                if (ry > maxHeight) {
                    ry = maxHeight;
                    ly -= p.y();
                }
                leftUpPos = QPoint(lx, ly);
                rightDownPos = QPoint(rx, ry);
                startPos = leftUpPos;
                endPos = rightDownPos;
            }

        private:
            QPoint leftUpPos, rightDownPos;     //记录 截图区域 左上角、右下角
            QPoint startPos, endPos;            //记录 鼠标开始位置、结束位置
            int maxWidth, maxHeight;            //记录屏幕大小
            STATUS status;                      //三个状态: 选择区域、移动区域、设置width height

            void cmpPoint(QPoint &leftTop, QPoint &rightDown)//比较两位置,判断左上角、右下角
            {
                QPoint l = leftTop;
                QPoint r = rightDown;

                if (l.x() <= r.x()) {
                    if (l.y() <= r.y()) {
                        ;
                    } else {
                        leftTop.setY(r.y());
                        rightDown.setY(l.y());
                    }
                } else {
                    if (l.y() < r.y()) {
                        leftTop.setX(r.x());
                        rightDown.setX(l.x());
                    } else {
                        QPoint tmp;
                        tmp = leftTop;
                        leftTop = rightDown;
                        rightDown = tmp;
                    }
                }
            }
        };
        //截屏窗口类
        class ScreenWidget : public QWidget
        {
            Q_OBJECT
        public:

            static ScreenWidget *Instance()
            {
//                if (self.isNull()) {
//                    static QMutex mutex;
//                    QMutexLocker locker(&mutex);
//                    if (self.isNull()) {
//                        self.reset(new ScreenWidget);
//                    }
//                }
//                return self.data();
                static auto screenw = new ScreenWidget;
                return screenw;
            }
            explicit ScreenWidget(QWidget *parent = 0)
            {
                //this->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
                menu = new QMenu(this);
                menu->addAction("保存当前截图", this, SLOT(saveScreen()));
                menu->addAction("保存全屏截图", this, SLOT(saveFullScreen()));
                menu->addAction("截图另存为", this, SLOT(saveScreenOther()));
                menu->addAction("全屏另存为", this, SLOT(saveFullOther()));
                menu->addAction("退出截图", this, SLOT(hide()));

                //取得屏幕大小
                screen = new Screen(QApplication::desktop()->size());
                //保存全屏图像
                fullScreen = new QPixmap();
            }
        private:
           // static QScopedPointer<ScreenWidget> self;
            QMenu *menu;            //右键菜单对象
            Screen *screen;         //截屏对象
            QPixmap *fullScreen;    //保存全屏图像
            QPixmap *bgScreen;      //模糊背景图
            QPoint movPos;          //坐标
        protected:
            void contextMenuEvent(QContextMenuEvent *e)
            {
                this->setCursor(Qt::ArrowCursor);
                menu->exec(cursor().pos());
            }
            void mousePressEvent(QMouseEvent *e)
            {
                int status = screen->getStatus();

                if (status == Screen::SELECT) {
                    screen->setStart(e->pos());
                } else if (status == Screen::MOV) {
                    if (screen->isInArea(e->pos()) == false) {
                        screen->setStart(e->pos());
                        screen->setStatus(Screen::SELECT);
                    } else {
                        movPos = e->pos();
                        this->setCursor(Qt::SizeAllCursor);
                    }
                }
                this->update();
            }
            void mouseMoveEvent(QMouseEvent *e)
            {
                if (screen->getStatus() == Screen::SELECT) {
                    screen->setEnd(e->pos());
                } else if (screen->getStatus() == Screen::MOV) {
                    QPoint p(e->x() - movPos.x(), e->y() - movPos.y());
                    screen->move(p);
                    movPos = e->pos();
                }
                this->update();
            }
            void mouseReleaseEvent(QMouseEvent *e)
            {
                if (screen->getStatus() == Screen::SELECT) {
                    screen->setStatus(Screen::MOV);
                } else if (screen->getStatus() == Screen::MOV) {
                    this->setCursor(Qt::ArrowCursor);
                }
            }
            void paintEvent(QPaintEvent *)
            {
                int x = screen->getLeftUp().x();
                int y = screen->getLeftUp().y();
                int w = screen->getRightDown().x() - x;
                int h = screen->getRightDown().y() - y;

                QPainter painter(this);
                QPen pen;
                pen.setColor(Qt::green);
                pen.setWidth(2);
                pen.setStyle(Qt::DotLine);
                painter.setPen(pen);
                painter.drawPixmap(0, 0, *bgScreen);

                if (w != 0 && h != 0) {
                    painter.drawPixmap(x, y, fullScreen->copy(x, y, w, h));
                }
                painter.drawRect(x, y, w, h);
                pen.setColor(Qt::yellow);
                painter.setPen(pen);
                painter.drawText(x + 2, y - 8, tr("截图范围:( %1 x %2 ) - ( %3 x %4 )  图片大小:( %5 x %6 )")
                                 .arg(x).arg(y).arg(x + w).arg(y + h).arg(w).arg(h));
            }
            void showEvent(QShowEvent *)
            {
                QPoint point(-1, -1);
                screen->setStart(point);
                screen->setEnd(point);

            #if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
                *fullScreen = fullScreen->grabWindow(QApplication::desktop()->winId(), 0, 0, screen->width(), screen->height());
            #else
                QScreen *pscreen = QApplication::primaryScreen();
                *fullScreen = pscreen->grabWindow(QApplication::desktop()->winId(), 0, 0, screen->width(), screen->height());
            #endif
                //设置透明度实现模糊背景
                QPixmap pix(screen->width(), screen->height());
                pix.fill((QColor(160, 160, 160, 200)));
                bgScreen = new QPixmap(*fullScreen);
                QPainter p(bgScreen);
                p.drawPixmap(0, 0, pix);
            }
        private slots:
            void saveScreen()
            {
                int x = screen->getLeftUp().x();
                int y = screen->getLeftUp().y();
                int w = screen->getRightDown().x() - x;
                int h = screen->getRightDown().y() - y;

                QString fileName = QString("%1/screen_%2.png").arg(qApp->applicationDirPath()).arg(STRDATETIME);
                fullScreen->copy(x, y, w, h).save(fileName, "png");
                close();
            }
            void saveFullScreen()
            {
                QString fileName = QString("%1/full_%2.png").arg(qApp->applicationDirPath()).arg(STRDATETIME);
                fullScreen->save(fileName, "png");
                close();
            }
            void saveScreenOther()
            {
                QString name = QString("%1.png").arg(STRDATETIME);
                QString fileName = QFileDialog::getSaveFileName(this, "保存图片", name, "png Files (*.png)");
                if (!fileName.endsWith(".png")) {
                    fileName += ".png";
                }

                if (fileName.length() > 0) {
                    int x = screen->getLeftUp().x();
                    int y = screen->getLeftUp().y();
                    int w = screen->getRightDown().x() - x;
                    int h = screen->getRightDown().y() - y;
                    fullScreen->copy(x, y, w, h).save(fileName, "png");
                    close();
                }
            }
            void saveFullOther()
            {
                QString name = QString("%1.png").arg(STRDATETIME);
                QString fileName = QFileDialog::getSaveFileName(this, "保存图片", name, "png Files (*.png)");
                if (!fileName.endsWith(".png")) {
                    fileName += ".png";
                }

                if (fileName.length() > 0) {
                    fullScreen->save(fileName, "png");
                    close();
                }
            }
        };
        //QScopedPointer<ScreenWidget> ScreenWidget::self;
    }

    namespace FlowLayout {
      // 2、流布局
      // 功能 : 如果软件界面窗口大小发生变化,布局里面的控件,进行自动换行
      // 使用 : 如下
            //auto layout = new wangchuan::FlowLayout::FlowLayout(ui->widget); // ui->widget:任意widget
            // layout->addWidget(new QPushButton("1"));
            // layout->addWidget(new QPushButton("2"));
            // layout->addWidget(new QPushButton("3"));
            // layout->addWidget(new QPushButton("5"));
            // layout->addWidget(new QPushButton("6"));
            // layout->addWidget(new QPushButton("7"));
        class FlowLayout : public QLayout
        {
        public:
            /*
             * 在构造函数中,我们调用setContentsMargins()来设置
             * 左、上、右和下边距。默认情况下,
             * QLayout使用当前样式提供的值(请参见QStyle::PixelMetric)。
            */
            FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1)
                : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
            {
                setContentsMargins(margin, margin, margin, margin);
            }
            FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1)
                : m_hSpace(hSpacing), m_vSpace(vSpacing)
            {
                setContentsMargins(margin, margin, margin, margin);
            }
            ~FlowLayout()
            {
                QLayoutItem *item;
                while ((item = takeAt(0)))
                    delete item;
            }


            /*
             * 在本例中,我们重新实现了addItem(),
             * 它是一个纯虚拟函数。使用addItem()时,
             * 布局项的所有权会转移到布局,因此布局有责任删除它们。
             *
             * addItem()用于将项添加到布局中。
            */
            void addItem(QLayoutItem *item)
            {
                itemList.append(item);
            }
            /*
             * 我们实现horizontalSpacing()和verticalSpacing。
             * 如果该值小于或等于0,则将使用该值。否则,将调用smartSpacing()来计算间距。
            */
            int horizontalSpacing() const
            {
                if (m_hSpace >= 0) {
                    return m_hSpace;
                } else {
                    return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
                }
            }
            int verticalSpacing() const
            {
                if (m_vSpace >= 0) {
                    return m_vSpace;
                } else {
                    return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
                }
            }

            /*
             * expandingDirections()返回Qt::Orientations,其中布局可以使用比其sizeHint()更多的空间。
            */
            Qt::Orientations expandingDirections() const
            {
                return 0;
            }

            /*
             * 为了适应高度取决于宽度的小部件,我们实现了heightForWidth()。
             * 函数hasHeightForWidth()用于测试此依赖关系,heightForWidth()将宽度传递给doLayout(),
             * doLayout又将宽度用作布局矩形的参数,即项目布局的边界。此矩形不包括布局边距()。
            */
            bool hasHeightForWidth() const
            {
                return true;
            }

            int heightForWidth(int width) const
            {
                int height = doLayout(QRect(0, 0, width, 0), true);
                return height;
            }

            /*
             * 然后我们实现count()来返回布局中的项数。为了浏览项目列表,
             * 我们使用itemAt()和takeAt()从列表中删除并返回项目。
             * 如果某个项目被删除,则其余项目将重新编号。这三个函数都是QLayout中的纯虚拟函数。
            */
            int count() const
            {
                return itemList.size();
            }

            QLayoutItem *itemAt(int index) const
            {
                return itemList.value(index);
            }

            QSize minimumSize() const
            {
                QSize size;
                QLayoutItem *item;
                foreach (item, itemList)
                size = size.expandedTo(item->minimumSize());

                size += QSize(2*margin(), 2*margin());
                return size;
            }

            /*
             * setGeometry()通常用于进行实际布局,即计算布局项的几何图形。
             * 在本例中,它调用doLayout()并传递布局rect。
             * sizeHint()返回布局的首选大小,minimumSize()返回版面的最小大小。
            */
            void setGeometry(const QRect &rect)
            {
                QLayout::setGeometry(rect);
                doLayout(rect, false);
            }

            QSize sizeHint() const
            {
                return minimumSize();
            }

            QLayoutItem *takeAt(int index)
            {
                if (index >= 0 && index < itemList.size())
                    return itemList.takeAt(index);
                else
                    return 0;
            }

        private:
            /*
             * 如果horizontalSpacing()或verticalSpacing)未返回默认值,doLayout()将处理布局。
             * 它使用getContentsMargins()来计算布局项可用的面积。
            */
            int doLayout(const QRect &rect, bool testOnly) const
            {
                int left, top, right, bottom;
                getContentsMargins(&left, &top, &right, &bottom);
                QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
                int x = effectiveRect.x();
                int y = effectiveRect.y();
                int lineHeight = 0;

                // 然后,它根据当前样式为布局中的每个小部件设置适当的间距。
                QLayoutItem *item;
                foreach (item, itemList)
                {
                    QWidget *wid = item->widget();
                    int spaceX = horizontalSpacing();
                    if (spaceX == -1)
                        spaceX = wid->style()->layoutSpacing(
                        QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
                    int spaceY = verticalSpacing();
                    if (spaceY == -1)
                        spaceY = wid->style()->layoutSpacing(
                        QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);

                    //然后通过将项目宽度和行高度添加到初始x和y坐标来计算布局中每个项目的位置。
                    //这反过来又让我们了解下一个项目是否适合当前行,或者是否必须向下移动到下一个。
                    //我们还根据窗口小部件的高度来查找当前行的高度。
                    int nextX = x + item->sizeHint().width() + spaceX;
                    if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
                        x = effectiveRect.x();
                        y = y + lineHeight + spaceY;
                        nextX = x + item->sizeHint().width() + spaceX;
                        lineHeight = 0;
                    }

                    if (!testOnly)
                        item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));

                    x = nextX;
                    lineHeight = qMax(lineHeight, item->sizeHint().height());
                }
                return y + lineHeight - rect.y() + bottom;
            }

            /*
             * smartSpacing()用于获取顶级布局或子布局的默认间距。
             * 当父布局是QWidget时,顶级布局的默认间距将通过查询样式来确定。
             * 当父布局是QLayout时,子布局的默认间距将通过查询父布局的间距来确定。
            */
            int smartSpacing(QStyle::PixelMetric pm) const
            {
                QObject *parent = this->parent();
                if (!parent) {
                    return -1;
                } else if (parent->isWidgetType()) {
                    QWidget *pw = static_cast<QWidget *>(parent);
                    return pw->style()->pixelMetric(pm, 0, pw);
                } else {
                    return static_cast<QLayout *>(parent)->spacing();
                }
            }
            QList<QLayoutItem *> itemList;
            int m_hSpace;
            int m_vSpace;
        };
    }

    namespace Messagebox {
        // 3、基本消息框
        // 功能:实现常用的消息输出框
        //     【0:question消息;1:information消息框 ;2:warning消息框;3:critical消息框;4:普通消息框】
        // 使用:在使用消息框的地方,实例化Message对象,在构造函数中:第一个参数是要使用的消息框的索引[0-4],
        //      第二个参数:标题,第三个参数内容,第四个参数父指针(默认为空指针)
        //      可以根据 execute函数返回的值,执行一些操作『双选:<确认:1,取消:0> ,单选:<0>』
        // eg:
        //    wangchuan::Messagebox::Message messge(0,(char*)"标题",(char*)"内容");
        //    int num =  messge.execute();
        class Message{
        private:
            QWidget* parent{};
             int& index;
             char* title{nullptr};
             char* text{nullptr};
        public:
             explicit Message(int ind, char* tit, char* tet,QWidget* pt = nullptr)
                :
                 index(ind)
                ,title(tit)
                ,text(tet)
                ,parent(pt)
            {
                if(!strcmp("",tit)||!strcmp("",tet))
                {
                    title = (char*)"弹窗标题";
                    text = (char*)"弹窗内容";
                }
            }

        public:
            int execute()
            {
                QMessageBox::ButtonRole result{};
                QMessageBox messbo;
                messbo.setParent(parent);
                messbo.setWindowFlags(Qt::Dialog);
                switch (index)
                {
                case 0:
                {
                    // question 疑问消息框
                    messbo.setIcon(QMessageBox::Question);
                    messbo.setWindowTitle(title);
                    messbo.setText(text);
                    messbo.addButton("取消", QMessageBox::NoRole);
                    messbo.addButton("确定",QMessageBox::YesRole);
                    result = (QMessageBox::ButtonRole)messbo.exec();
                }
                    break;
                case 1:
                    // information 提示消息框
                {
                    messbo.setIcon(QMessageBox::Information);
                    messbo.setWindowTitle(title);
                    messbo.setText(text);
                    messbo.addButton("确定",QMessageBox::YesRole);
                    result = (QMessageBox::ButtonRole)messbo.exec();
                }
                    break;
                case 2:
                    // warning 警告消息框
                {
                    messbo.setIcon(QMessageBox::Warning);
                    messbo.setWindowTitle(title);
                    messbo.setText(text);
                    messbo.addButton("取消", QMessageBox::NoRole);
                    result = (QMessageBox::ButtonRole)messbo.exec();
                }
                    break;
                case 3:
                    // critical  “操作错误”或“运行失败” 消息框
                {
                    messbo.setIcon(QMessageBox::Critical);
                    messbo.setWindowTitle(title);
                    messbo.setText(text);
                    messbo.addButton("关闭", QMessageBox::NoRole);
                    result = (QMessageBox::ButtonRole)messbo.exec();
                }
                    break;
                case 4:
                    // NoIcon  普通“没有图标” 消息框
                {
                    messbo.setIcon(QMessageBox::NoIcon);
                    messbo.setWindowTitle(title);
                    messbo.setText(text);
                    messbo.addButton("确认", QMessageBox::NoRole);
                    result = (QMessageBox::ButtonRole)messbo.exec();
                }
                    break;
                }
                return (int)result;
            }
        };
    }

    namespace RegExp {
        // 4、 正则表达式
        //
        // 功能:实现项目中用到的正则表达式
        //
        //      【1:限制输入空格、空值,getNullValueRegexp();】
        // 使用:在使用正则的地方实例化该对象,通过get方法获取到QRegExpValidator
        //
        // eg :
        //      wangchuan::RegExp::Regexp* regexp = new wangchuan::RegExp::Regexp();
        //      ui->lineedit->setValidator(regexp->getNullValueRegexp());
        class Regexp
        {
        public:
            Regexp() = default;
            Regexp(Regexp&) = delete;
            Regexp(const Regexp&) = delete;
            Regexp& operator=(const Regexp&) = delete;
        public:
            QRegExpValidator* getNullValueRegexp()
            {
                QRegExp rx("[^\\s]+$");
                QRegExpValidator *mNullValue = new QRegExpValidator(rx);
                return mNullValue;
            }
        };

        // 用于给表格设置正则表达式,
        // table视图 QTableView了
        // table模型 QStandardItemModel
        // 使用示例:
        //          wangchuan::RegExp::InputDelegate* inputDelegate = new wangchuan::RegExp::InputDelegate;
        //          m_tableview->setItemDelegateForColumn(0, inputDelegate); // 设置索引0列的输入正则表达式
        class InputDelegate:public QStyledItemDelegate
        {
        public:
            QWidget *createEditor(QWidget*parent,const QStyleOptionViewItem &option,const QModelIndex &index)const override
            {
                QLineEdit *editor =new QLineEdit(parent);
                QRegExp regex("[^\\s]+$"); // 可以替换为你想要的正则表达式
                QValidator *validator =new QRegExpValidator(regex,parent);
                editor->setValidator(validator);
                return editor;
            }
        };
    }

    namespace FileManage {
        // 5、 对文件操作
        //
        // 功能:
        //     【Qt:创建新目录、获取程序所在路经、枚举目录下所有文件、枚举目录下所有目录、清空目录】
        //     【c++:删除目录、创建目录、初始化目录u、获取程序所在目录、绝对路经、获取目录下的所有文件、一个文件覆盖另一个文件、删除文件、读取文件内容】
        //
        // 说明:纯c++对文件操作有的需要c++17,默认禁用c++17操作,如果开发环境支持c++17,关闭禁用,0——>1;
        //
        // 使用:
        //      引入头文件 通过命名空间进行调用
        // eg :
        //      std::string content = wangchuan::FileManage::StdFile::readFile("filepath");
        //
        using namespace std;
        class StdFile{
        public:
            StdFile() = delete;
#if 0
        // C++ 版本
            /** c++17
              * @brief 删除目录
              * @param path 路经
            */
            static void rmDir(const std::string &path)
            {
                if (filesystem::exists(path)) {
                    filesystem::remove_all(path);
                    filesystem::remove(path);
                }
            }
            /** c++17
              * @brief 创建目录
              * @param path 路经
            */
            static void mkDir(const std::string &path)
            {
                if (!filesystem::exists(path)) {
                    filesystem::create_directories(path);
                }
            }
            /** c++17
              * @brief 初始化目录
              * @param path 路经
            */
            static void initDir(const std::string &path)
            {
                if (filesystem::exists(path)) {
                    filesystem::remove_all(path);
                } else {
                    filesystem::create_directories(path);
                }
            }
            /** c++17
              * @brief 获取当前程序所在目录
              * @param
              * @return std::string 返回程序所在路经
            */
            static std::string curPath()
            {
            #if defined(_MSC_VER)
                return filesystem::current_path().string();
            #else
                return filesystem::current_path();
            #endif
            }
            /** c++17
              * @brief 绝对路经
              * @param path 路经
              * @return std::string
            */
            static std::string absolutePath(const std::string &path)
            {
            #if defined(_MSC_VER)
                return filesystem::canonical(path).string();
            #else
                return filesystem::canonical(path);
            #endif
            }
            /** c++17
              * @brief 获取目录下的所有文件
              * @param path 路经
              * @return std::vector<std::string> 返回所欧文件的vector
            */
            static std::vector<std::string> listFiles(const std::string &path)
            {
                vector<string> res;
                if (!filesystem::exists(path)) {
                    return res;
                }
                for (const auto &entry : filesystem::directory_iterator(path)) {
                    if (filesystem::is_regular_file(entry)) {
            #if defined(_MSC_VER)
                        string fileName = entry.path().stem().string();
                        string ext = entry.path().extension().string();
            #else
                        string fileName = entry.path().stem();
                        string ext = entry.path().extension();
            #endif
                        auto file = fileName + ext;
                        res.push_back(file);
                    }
                }
                return res;
            }
            /** c++17
              * @brief 拷贝文件(覆盖),覆盖后还使用旧文件名。
              * @param  要拷贝的文件, 被覆盖的文件
              * @return
            */
            static void copyFile(const std::string &from, const std::string &to)
            {
                filesystem::copy_file(from, to, filesystem::copy_options::overwrite_existing);
            }
            /** c++17
              * @brief 删除文件
              * @param path 文件路经
              * @return
            */
            static void rmFile(const std::string &file)
            {
                if (filesystem::exists(file)) {
                    filesystem::remove(file);
                }
            }
#endif
            /**
              * @brief 读取文件内容
              * @param path 文件路经
              * @return std::string 读取到的内容
            */
            static std::string readFile(const std::string &filePath)
            {
                string res{""};
                ifstream f;
                f.open(filePath, ios::in);
                if (f.is_open()) {
                    f.seekg(0, ios::end);
                    int len = f.tellg();
                    if (len > 0) {
                        f.seekg(0, ios::beg);
                        res.resize(len);
                        f.read((char *)res.data(), len);
                    }
                    f.close();
                }
                return res;
            }
      // Qt版
            /**
              * @brief 创建新目录
              * @param path 目录路经
              * @return
            */
            static void mkDir(const QString &path)
            {
                QDir dir{path};
                if (!dir.exists()) {
                    dir.mkpath(path);
                }
            }
            /**
              * @brief 获取程序工作目录
              * @param path 目录路径
              * @return
            */
            static QString workDir()
            {
                static QString path = "";
                if (path.length() <= 0) {
                    path = QApplication::applicationDirPath() + "/../data";
                    QDir dir{path};
                    path = dir.absolutePath();
                    mkDir(path);
                }
                return path;
            }
            /**
              * @brief 枚举目录下所有文件
              * @param dir 要枚举的目录
              * @return 符合条件的所有文件列表
            */
            static std::vector<QString> listFiles(const QString &dir)
            {
                vector<QString> res;
                QDir dd{dir};
                auto fl = dd.entryInfoList(QDir::Files);
                for (const auto &file : fl) {
                    if (file.isFile()) {
                        //res.push_back(file.absoluteFilePath());
                        res.push_back(file.fileName());
                    }
                }
                return res;
            }
            /**
              * @brief 枚举目录下所有目录
              * @param dir 要枚举的目录
              * @return 符合条件的所有目录列表
            */
            static std::vector<QString> listDirs(const QString &dir)
            {
                vector<QString> res;
                QDir dd{dir};
                auto fl = dd.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
                for (const auto &file : fl) {
                    if (file.isDir()) {
                        res.push_back(file.fileName());
                    }
                }
                return res;
            }
            /**
              * @brief 清空目录
              * @param path 要清空的目录
              * @return
            */
            static void clearDir(const QString &dir)
            {
                QDir dd{dir};
                auto fl = dd.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot);
                for (const auto &file : fl) {
                    auto path = file.absoluteFilePath();
                    if (file.isFile()) {
                        dd.remove(path);
                    } else {
                        clearDir(path);
                        dd.rmpath(path);
                    }
                }
            }
            /**
              * @brief 读取文件内容
              * @param path 文件路径
              * @return
            */
            static QString gReadFileAll(const QString& path, const QString& _type = "utf-8")
            {
                QString _allContent;
                QFile _file(path);
                if (!_file.open(QIODevice::ReadOnly | QIODevice::Text))
                    return _allContent;

                QTextStream _stream(&_file);
                _stream.setCodec(QTextCodec::codecForName(_type.toStdString().c_str()));
                _allContent = _stream.readAll();
                _file.close();

                return _allContent;
            }
            /**
              * @brief 往文件里写内容
              * @param path 文件路径, content 要写入的内容,  _type编码格式
              * @return
            */
            static void gWriteFile(const QString& path, const QString& content, const QString& _type = "utf-8")
            {
                QFile _file(path);
                if (!_file.open(QIODevice::Truncate | QIODevice::ReadWrite| QIODevice::Text))
                    return;
                QTextStream _stream(&_file);
                _stream.setCodec(QTextCodec::codecForName(_type.toStdString().c_str()));
                _stream << content;
                _file.close();
            }
            /**
              * @brief 拷贝目录到另一个目录中
              * @param _source 要拷贝的文件路径,_target拷贝到哪,couver bool是否覆盖,suffix 过滤指定格式的文件
              * @return
            */
            static void gCopyDirToDir(const QString& _source, const QString& _target, bool cover, const QString& suffix)
            {
                QDir dir(_source);
                //获取文件列表
                QFileInfoList list = dir.entryInfoList(QDir::Files | QDir::NoSymLinks);
                for (auto _info : list)
                {
                    if (!suffix.isEmpty() && suffix!= _info.suffix())
                    {
                        continue;
                    }
                    QString path = _info.absoluteFilePath();
                    //目标路径
                    QString toFile = _target;
                    toFile += "/";
                    toFile += _info.fileName();
                    if (cover)
                    {
                        gDeleteFile(toFile);
                    }

                    QFile tempFile(path);
                    tempFile.copy(toFile);
                    tempFile.close();
                }
            }
            /**
              * @brief 拷贝文件到目录
              * @param source 文件绝对路径,target 目录路径, cover bool是否进行覆盖
              * @return
            */
            static bool gCopyFileToDir(const QString& source, const QString& target, bool cover)
            {
                QFileInfo sourceInfo(source);

                if (!sourceInfo.exists())
                    return false;

                QString toFile = target;
                toFile += "/";
                toFile += sourceInfo.fileName();

                if (cover)
                {
                    gDeleteFile(toFile);
                }
                QFile tempFile(source);
                tempFile.copy(toFile);
                tempFile.close();
                return true;
            }
            /**
              * @brief 删除文件
              * @param path 文件绝对路径
              * @return
            */
            static void gDeleteFile(const QString& path)
            {
                QFileInfo toFileInfo(path);
                if (toFileInfo.exists())
                {
                    toFileInfo.dir().remove(toFileInfo.fileName());
                }
            }
            /**
              * @brief 删除目录
              * @param path 目录路径
              * @return
            */
            static void gDeleteDir(const QString& _path)
            {
                QDir _dir(_path);
                if (!_dir.exists())
                {
                    return;
                }
                _dir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot);
                QFileInfoList _fileList = _dir.entryInfoList();
                foreach(QFileInfo _file, _fileList)
                {
                    if (_file.isFile())
                    {
                        _file.dir().remove(_file.fileName());
                    }
                    else
                    {
                        gDeleteDir(_file.absoluteFilePath());
                    }
                }
                _dir.rmdir(_dir.absolutePath());
            }
            /**
              * @brief 删除目录
              * @param path 目录路径
              * @return
            */
            static QString gToJsonOfObject(const QJsonObject& object)
            {
                QJsonDocument jsonDocument;
                jsonDocument.setObject(object);

                return jsonDocument.toJson(QJsonDocument::Indented);
            }

            static void gDeleteSubString(QString& content, const QString& start, const QString& end)
            {
                int startIndex = content.indexOf(start);
                int endIndex = content.indexOf(end, startIndex);
                while (startIndex != -1 && endIndex != -1)
                {
                    content.remove(startIndex, endIndex - startIndex + end.length() + 1);

                    startIndex = content.indexOf(start);
                    endIndex = content.indexOf(end, startIndex);
                }
            }

            static void gDeleteSubString(QString& content, const QString& startFlag, const QString& ifFlag, const QString& endFlag)
            {
                int startIndex = content.indexOf(startFlag);
                int endIndex = content.indexOf(endFlag, startIndex);
                while (startIndex != -1 && endIndex != -1)
                {
                    int index = content.indexOf(ifFlag, startIndex);

                    if (index != -1 && endIndex > index)
                    {
                        index = content.indexOf(endFlag, index);
                        if (index != -1)
                        {
                            content.remove(startIndex, index - startIndex + endFlag.length() + 1);
                        }
                    }
                    startIndex = content.indexOf(startFlag, endIndex);
                    endIndex = content.indexOf(endFlag, startIndex);
                }
            }
        };
    }
#endif
}

#endif // WANGCHUAN_H

 

posted @ 2023-08-29 19:39  雾枫  阅读(34)  评论(0编辑  收藏  举报