QT学习_log分析器程序

Posted Leslie X徐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QT学习_log分析器程序相关的知识,希望对你有一定的参考价值。

log分析器程序

需求

  1. 文本框显示行数,所在行显示高亮
  2. 实现拖拽加载,压缩包线程解析,加载log文件
  3. 查找关键字

实现

1.打开多个log文件,并按时间排序显示

//打开文件
void MainWindow::on_actionfile_triggered()
{
    ui->plainTextEdit->clear();
    QStringList fileNames = QFileDialog::getOpenFileNames(this,
                            QString("select log"),
                            QString(QDir::currentPath()),
                            QString("all(*.log *.zip);;log(*.log);;zip(*.zip)"));
    if(!fileNames.isEmpty()){
        fileNames.sort();//实现排序
        foreach(QString filename, fileNames){
            if(filename.contains(".log")){
               ui->plainTextEdit->handleLogFile(filename);
            }else if(filename.contains(".zip")){
               ui->plainTextEdit->handleZipFile(filename);
            }
        }
    }
}

2.添加zlib,quazip库

将需要的库等打包放入项目文件中,在pro中添加:

win32: LIBS += -L$$PWD/quazipPack/lib/ -lzdll

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/quazipPack/lib/ -lquazip
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/quazipPack/lib/ -lquazipd

INCLUDEPATH += $$PWD/quazipPack/include
DEPENDPATH += $$PWD/quazipPack/include

3.ZIP压缩解压进入线程工作

创建处理压缩包的线程类

//专门处理压缩的线程
#include <QThread>
#include <QObject>
#include <JlCompress.h>

class ZipThread : public QThread
{
    Q_OBJECT
public:
    explicit ZipThread(QObject *parent = nullptr);
    inline void setFilters(QStringList filters){
        this->filters = filters;
    }
    inline void setZipPath(QString zipPath){
        this->zipPath = zipPath;
    }

public: signals:
   void getFilenames(QStringList files);

    // QThread interface
protected:
    void run();

private:
    QString zipPath;
    QStringList filters;
};

void ZipThread::run()
{
    if(zipPath.isEmpty())quit();
    QString compressFile = zipPath;
    QString extractFile = zipPath.remove(".zip");
    //解压缩
    QStringList fileList = JlCompress::extractDir(compressFile.trimmed(),extractFile.trimmed());
    if(!filters.isEmpty())
    {
        foreach(QString i, filters){
            fileList = fileList.filter(i);
        }
    }
    QStringList logFiles = fileList;
    emit getFilenames(logFiles);
    quit();
}

使用:

void MyGCodeTextEdit::handleZipFile(QString fileName)
{
    th_zip->setZipPath(fileName);
    th_zip->setFilters(QStringList()<<"log/"<<".log");
    th_zip->start();
}

void MyGCodeTextEdit::onZipThdread(QStringList files)
{
    foreach(QString i, files){
        handleLogFile(i);
    }
}

4.鼠标点击时,显示实时行号

//加入信号连接
connect(ui->plainTextEdit,&QPlainTextEdit::cursorPositionChanged,
            this,&MainWindow::onGetCurLineNum);

//函数
void MainWindow::onGetCurLineNum()
{
    label->setText(QString("curLine: %1").arg(1 + ui->plainTextEdit->textCursor().blockNumber()));
}

5.将所有文件操作放入mytexteditor类做,重写dragEnterEvent和dropEvent

class MyGCodeTextEdit;
class LineNumberArea;

class MyGCodeTextEdit : public QPlainTextEdit{

    Q_OBJECT

public:
    MyGCodeTextEdit(QWidget *parent  = 0);
    int lineNumberAreaWidth();
    void lineNumberAreaPaintEvent(QPaintEvent *event);
    void FindAllString(QString findString);

//处理拖拽进入的文件
    void handleLogFile(QString fileName);
    void handleZipFile(QString fileName);
    void onZipThdread(QStringList files);

protected:
    void resizeEvent(QResizeEvent *event) override;

private slots:
    void updateLineNumberAreaWidth(int newBlockCount);
    void highlightCurrentLine();
    void updateLineNumberArea(const QRect &, int);

public slots:

private:
    QTextCursor curTextCursor;
    QRect curTextCursorRect;
    bool findflag=false;
    //显示行号
    QWidget *lineNumberArea;
    //处理ZIP文件
    ZipThread *th_zip;

    //重写拖拽事件
    // QWidget interface
public:
    virtual void dragEnterEvent(QDragEnterEvent *event) override;
    virtual void dropEvent(QDropEvent *event) override;

    //因为dragMoveEvent默认是ignore的所以需要重写需要accept()
    virtual void dragMoveEvent(QDragMoveEvent *event) override;
    virtual void dragLeaveEvent(QDragLeaveEvent *event) override;
};
void MyGCodeTextEdit::dragMoveEvent(QDragMoveEvent *event)
{
    event->accept();
}

void MyGCodeTextEdit::dragLeaveEvent(QDragLeaveEvent *event)
{
    event->accept();
}

void MyGCodeTextEdit::dragEnterEvent(QDragEnterEvent *event)
{
    event->accept();
    if(event->mimeData()->hasUrls()){
        //若是文件路径则允许拖拽
        event->acceptProposedAction();
    }
}

void MyGCodeTextEdit::dropEvent(QDropEvent *event)
{
    event->accept();
    this->clear();
    QList<QUrl> urls = event->mimeData()->urls();
    QStringList fileNames;

    if(urls.count()>0){
        foreach(QUrl url,urls){
            QString str = url.toLocalFile();
//            if(str.contains("robokit")) //如果只需要robokit开头的文件
            fileNames.append(str);
        }

        foreach(QString str, fileNames){
            if(str.contains(".zip")){
                handleZipFile(str);
            }
            else if (str.contains(".log")||str.contains(".txt")) {
                handleLogFile(str);
            }
        }
    }
}

//处理log文件
void MyGCodeTextEdit::handleLogFile(QString fileName)
{

    QFile file(fileName);
    if(file.exists()){
        file.open(QIODevice::ReadOnly);
    }else return;

    QTextStream stream(&file);
    stream.setCodec("UTF-8");

    this->appendPlainText(stream.readAll());
    file.close();

    this->moveCursor(QTextCursor::MoveOperation::Start);//移动光标到最开始
}

6.实现查找,实现findnext的自动连击

查找所有关键字,更改并保持其底色和字体颜色,查下一个关键字是撤销上一个关键字操作

void MyGCodeTextEdit::FindAllString(QString findString)
{
    {
        QString searchString = findString;
        QTextDocument *document = this->document();

        bool found = false;

        // undo previous change (if any)
        if(findflag)document->undo();
        findflag=true;

        if (searchString.isEmpty()) {
            QMessageBox::information(this, tr("Empty Search Field"),
                                     tr("The search field is empty. "
                                        "Please enter a word and click Find."));
        } else {
            QTextCursor highlightCursor(document);
            QTextCursor cursor(document);

            cursor.beginEditBlock(); //开始编辑文本块

            QTextCharFormat plainFormat(highlightCursor.charFormat());
            QTextCharFormat colorFormat = plainFormat;
            colorFormat.setForeground(Qt::red);
            colorFormat.setBackground(Qt::green);

            while (!highlightCursor.isNull() && !highlightCursor.atEnd()) {
                highlightCursor = document->find(searchString, highlightCursor,
                                                 QTextDocument::FindWholeWords);

                if (!highlightCursor.isNull()) {
                    found = true;
                    highlightCursor.movePosition(QTextCursor::WordRight,
                                                 QTextCursor::KeepAnchor);
                    highlightCursor.mergeCharFormat(colorFormat);
                }
            }

            cursor.endEditBlock();

            if (found == false) {
                QMessageBox::information(this, tr("Word Not Found"),
                                         tr("Sorry, the word cannot be found."));
            }
        }
    }
}

"查找下一个"按钮的自动连击

void MainWindow::on_pushButton_2_clicked()
{
    ui->pushButton_2->setAutoRepeat(true); //鼠标长按则自动重复点击
    QString str = ui->FindText->toPlainText();
    //向前查找
    if(ui->plainTextEdit->find(str,QTextDocument::FindFlag::FindWholeWords)==true){

        QPalette palette = ui->plainTextEdit->palette();
        palette.setColor(QPalette::Highlight,palette.color(QPalette::Active,QPalette::Highlight));
        ui->plainTextEdit->setPalette(palette);

    }else {
        QMessageBox::warning(this, tr("Find word"),
                            tr("touch bottom."),
                            QMessageBox::Cancel
                             );
    }
}

7.实现行号和高亮

高亮当前行

//绑定光标信号
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));

//实现高亮
void MyGCodeTextEdit::highlightCurrentLine()
{
    QList<QTextEdit::ExtraSelection> extraSelections;

//    if (!isReadOnly())
    {
        QTextEdit::ExtraSelection selection;

        QColor lineColor = QColor(Qt::yellow).lighter(160);

        selection.format.setBackground(lineColor);
        selection.format.setProperty(QTextFormat::FullWidthSelection, true);
        selection.cursor = textCursor();
        selection.cursor.clearSelection();
        extraSelections.append(selection);
    }

    setExtraSelections(extraSelections);
}

行号显示

行号类

//行号区域
class LineNumberArea : public QWidget
{

public:
    explicit LineNumberArea(MyGCodeTextEdit *editor): QWidget(editor)
    {
        gCodeTextEdit = editor;
        //setVisible(true);
    }

    QSize sizeHint() const override
    {
        return QSize(gCodeTextEdit->lineNumberAreaWidth(), 0);
    }

protected:
    void paintEvent(QPaintEvent *event) override
    {
        gCodeTextEdit->lineNumberAreaPaintEvent(event);
        //qDebug() << "gCodeTextEdit:" << __FUNCTION__;
    }

private:
    MyGCodeTextEdit *gCodeTextEdit;
};

//计算行宽
int MyGCodeTextEdit::lineNumberAreaWidth()
{
    int digits = 1;
    int max = qMax(1, blockCount());
    while (max >= 10)
    {
        max /= 10;
        ++digits;
    }

    int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;

    return space;
}

//
void MyGCodeTextEdit::resizeEvent(QResizeEvent *e)
{
    QPlainTextEdit::resizeEvent(e);
    QRect cr = contentsRect();
    lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
}

//重写绘制
void MyGCodeTextEdit::lineNumberAreaPaintEvent(QPaintEvent *event)
{
    QPainter painter(lineNumberArea);
    painter.fillRect(event->rect(), Qt::lightGray);

    QTextBlock block = firstVisibleBlock();
    int blockNumber = block.blockNumber();
    int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
    int bottom = top + (int) blockBoundingRect(block).height();

    while (block.isValid() && top <= event->rect().bottom())
    {
        if (block.isVisible() && bottom >= event->rect().top())
        {
            QString number = QString::number(blockNumber + 1); //获取行号
            painter.setPen(Qt::black);
            painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),
                             Qt::AlignRight, number);
        }

        block = block.next();
        top = bottom;
        bottom = top + (int) blockBoundingRect(block).height();
        ++blockNumber;
    }
}

//绑定文本块数量变化信号
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
//定义函数
void MyGCodeTextEdit::updateLineNumberAreaWidth(int /* newBlockCount */)
{
    setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
}


//绑定滚轮信号
connect(this, SIGNAL(updateRequest(QRectQt实现的Log日志系统

Qt学习

Qt (Creator) 与 WinSocks (ws2_32)

qt creator源码全方面分析(2-0)

QT学习_QT调用cmd指令

QT学习_QT常用事件