QT学习_log分析器程序
Posted Leslie X徐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QT学习_log分析器程序相关的知识,希望对你有一定的参考价值。
log分析器程序
需求
- 文本框显示行数,所在行显示高亮
- 实现拖拽加载,压缩包线程解析,加载log文件
- 查找关键字
实现
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日志系统