前文链接:Qt实现思维导图功能2『UI设计』
思维导图文件导入与导出
本文主要涉及文件拖拽窗口的实现和CRC32校验码的生成方法
百度网盘体验地址:
链接:https://pan.baidu.com/s/1ZTPc7klASVXcx69Ekh0gdw
提取码:1v12
效果图
1、动态演示效果:
2、静态展示图片
新增文件导出功能如下
序号 | 简述 | 具体功能 |
---|---|---|
1 | 导出JPEG图片 | 脑图数据插入JPEG图片中,可导入 |
2 | 导出PNG图片 | 脑图数据插入PNG图片中(支持CRC32数据校验 ),可导入 |
3 | 导出PDF文件 | 无脑图数据,不可导入 |
4 | 导出SVG文件 | 无脑图数据,不可导入 |
5 | 导出WORD文件 | 待做 |
6 | 导出TXT文件 | 待做 |
7 | 导出XML文件 | 脑图数据以Xml格式导出,可导入 |
8 | 导出JSON文件 | 脑图数据以Json格式导出(采用jsoncpp解析,避免QJsonDocument导致数据自动排序),可导入 |
9 | 导出脑图文件 | 待做 |
新增文件导入功能如下
序号 | 简述 | 具体功能 |
---|---|---|
1 | 支持JPEG格式图片 | 根据JPEG文件格式,解析JPEG文件/JPG后缀的JPEG格式文件 ,提取脑图数据,展示脑图 |
2 | 支持PNG格式图片 | 根据PNG文件格式(支持CRC32数据校验 ),解析PNG文件 ,提取脑图数据,展示脑图 |
3 | 支持XML文件 | 解析XML文件 ,提取脑图数据,展示脑图 |
4 | 支持JSON文件 | 解析JSON文件(采用jsoncpp解析,避免QJsonDocument导致数据自动排序) ,提取脑图数据,展示脑图 |
核心代码
1、文件拖拽窗口(作为文件导入窗口的中心窗口)
#pragma once
/*
* 思维导图-文件拖放窗口
*/
#include
class DropFileWidget : public QWidget
{
Q_OBJECT
public:
DropFileWidget(QWidget *parent = nullptr);
~DropFileWidget();
// 清空数据
void clear();
// 获取文件名
QString getFileName();
protected:
void paintEvent(QPaintEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dragLeaveEvent(QDragLeaveEvent *event);
void dropEvent(QDropEvent *event);
private:
bool m_drag; // 是否拖拽
bool m_isMindFile; // 是否是导图文件(是否包含导图信息)
bool m_existMindFile; // 是否已拖入过导图文件
QString m_mindFileName; // 导图文件名
QColor m_bgColor; // 背景色
QColor m_mindFileColor; // 导图文件颜色
QColor m_otherFileColor; // 其他文件颜色
};
#include "DropFileWidget.h"
#include
#include
#include
#include
#include "Tool/MindFileUtility.h"
#pragma execution_character_set("UTF-8")
DropFileWidget::DropFileWidget(QWidget *parent/* = nullptr*/)
: QWidget(parent)
{
m_drag = false; // 是否拖拽
m_isMindFile = false; // 是否是导图文件(是否包含导图信息)
m_existMindFile = false; // 是否已拖入过导图文件
m_bgColor = QColor(243, 243, 243); // 背景色
m_mindFileColor = QColor(238, 244, 255); // 导图文件颜色
m_otherFileColor = QColor(255, 0, 0, 58); // 其他文件颜色
setAcceptDrops(true);
}
DropFileWidget::~DropFileWidget()
{
}
void DropFileWidget::clear()
{
m_drag = false; // 是否拖拽
m_isMindFile = false; // 是否是导图文件(是否包含导图信息)
m_existMindFile = false; // 是否已拖入过导图文件
m_mindFileName = "";
}
QString DropFileWidget::getFileName()
{
return m_mindFileName;
}
void DropFileWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
int width = this->width();
int height = this->height();
int size = qMin(width, height);
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
// 绘制背景
painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(m_isMindFile ? m_mindFileColor : (m_drag ? m_otherFileColor : m_bgColor)));
painter.drawRect(rect());
if (!m_existMindFile)
{
// 绘制文本
QFont font = painter.font();
font.setPixelSize(24);
painter.setFont(font);
painter.setPen(m_isMindFile ? Qt::green : (m_drag ? Qt::red : Qt::gray));
QString text = m_isMindFile ? "文件格式正确" : (m_drag ? "文件格式错误" : "拖放文件至此");
painter.drawText(rect(), Qt::AlignCenter, text);
}
else
{
QFileInfo fileInfo(m_mindFileName);
QString suffix = fileInfo.suffix().toUpper();
// 绘制图片
QRect pixmapRect(width / 2 - size * 0.3, size * 0.1, size * 0.6, size * 0.6);
painter.drawPixmap(pixmapRect, QPixmap(QString(":/QWHMindMap/Res/img/ExportMind/%1.png").arg(suffix)));
// 绘制文本
QRect textRect(0, size * 0.7, width, size * 0.2);
painter.setPen(Qt::black);
painter.drawText(textRect, Qt::AlignCenter, fileInfo.fileName());
}
}
void DropFileWidget::dragEnterEvent(QDragEnterEvent *event)
{
clear();
// 获取文件名,解析是否是导图文件
m_mindFileName = event->mimeData()->urls().first().toLocalFile();
m_isMindFile = MindFileUtility::isMindFile(m_mindFileName);
event->acceptProposedAction();
update();
}
void DropFileWidget::dragLeaveEvent(QDragLeaveEvent *event)
{
clear();
update();
}
void DropFileWidget::dropEvent(QDropEvent *event)
{
m_drag = false;
if (m_isMindFile)
m_existMindFile = true;
update();
}
2、生成CRC32校验码
#pragma once
/*
* 思维导图-CRC32工具类
* 对于data_len + data_type + data_content + data_crc结构的PNG数据
* CRC解析的是data_type + data_content部分,不需要data_len部分,当然更不会需要data_crc部分
*/
class CRC32
{
public:
// 码表生成,如:X32+X26+...X1+1, poly=(1<<26)|...|(1<<1)|(1<<0)
static void initCrc32Table(unsigned long poly);
// 获取CRC32校验码,crc默认初始值0xFFFFFFFF
static unsigned long crc32(unsigned char *input, int len);
// 生成多项式G(x) = x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
static unsigned long CRC32::poly; // 生成多项式代码
private:
// 位逆转
static unsigned long bitReverse(unsigned long input, int bw);
// 获取CRC32校验码
static unsigned long crc32(unsigned long crc, unsigned char *, int len);
private:
static unsigned long table[256]; // 校验码表
static unsigned long crc; // 初始值
};
#include "CRC32.h"
unsigned long CRC32::table[256] = {0}; // 校验码表
unsigned long CRC32::crc = 0xFFFFFFFF; // 初始值
unsigned long CRC32::poly = 0x4C11DB7; // 生成多项式代码,由G(x)演化而来
void CRC32::initCrc32Table(unsigned long poly)
{
unsigned long c;
poly = bitReverse(poly, 32);
for (int i = 0; i < 256; i++)
{
c = i;
for (int j = 0; j < 8; j++)
{
if (c & 1)
c = poly ^ (c >> 1);
else
c = c >> 1;
}
table[i] = c;
}
}
unsigned long CRC32::bitReverse(unsigned long input, int bw)
{
unsigned long var = 0;
for (int i = 0; i < bw; i++)
{
if (input & 0x01)
{
var |= 1 << (bw - 1 - i);
}
input >>= 1;
}
return var;
}
unsigned long CRC32::crc32(unsigned long crc, unsigned char *input, int len)
{
unsigned char index;
unsigned char *pch = input;
for (int i = 0; i < len; i++)
{
index = (unsigned char)(crc ^ *pch);
crc = (crc >> 8) ^ table[index];
pch++;
}
return crc;
}
unsigned long CRC32::crc32(unsigned char *input, int len)
{
return crc32(crc, input, len);
}