Compare commits

...

6 Commits

Author SHA1 Message Date
muyi 8127a18111 11
1 year ago
muyi a12136c63f 11
1 year ago
muyi 3e2b364cc8 11
1 year ago
muyi 914a889f6d 11111
1 year ago
muyi 1e471df16d 1111
1 year ago
muyi fe96282ec1 renfanghao2210461205
1 year ago

@ -1,43 +1,61 @@
#include "appinit.h"
#include "qapplication.h"
#include "qevent.h"
#include "appinit.h" // 包含AppInit类的声明头文件
#include "qapplication.h" // 包含QApplication类的声明用于管理GUI应用程序的控制流和主要设置
#include "qevent.h" // 包含QEvent类的声明用于处理事件
// 定义一个静态成员变量self用于实现单例模式。初始化为0nullptr
AppInit *AppInit::self = 0;
// AppInit类的构造函数接收一个QObject类型的父对象指针。这里调用了QObject的构造函数。
AppInit::AppInit(QObject *parent) : QObject(parent)
{
}
// AppInit类的事件过滤器函数用于处理特定对象的事件。
bool AppInit::eventFilter(QObject *obj, QEvent *evt)
{
// 将传入的对象转换为QWidget类型以便使用QWidget的成员函数。
QWidget *w = (QWidget *)obj;
// 检查该窗口是否有名为"canMove"的属性并且该属性为true。如果不是则继续调用默认的事件处理。
if (!w->property("canMove").toBool()) {
return QObject::eventFilter(obj, evt);
}
// 定义并初始化静态变量,用于存储鼠标的位置和是否按下了鼠标按钮。
static QPoint mousePoint;
static bool mousePressed = false;
// 将传入的事件转换为QMouseEvent类型以便访问鼠标事件的特定属性。
QMouseEvent *event = static_cast<QMouseEvent *>(evt);
// 检查事件类型是否为鼠标按下事件。
if (event->type() == QEvent::MouseButtonPress) {
// 如果按下的是左键则设置mousePressed为true并计算鼠标点击位置与窗口左上角的相对位置。
if (event->button() == Qt::LeftButton) {
mousePressed = true;
mousePoint = event->globalPos() - w->pos();
return true;
return true; // 表示事件已被处理
}
} else if (event->type() == QEvent::MouseButtonRelease) {
mousePressed = false;
return true;
} else if (event->type() == QEvent::MouseMove) {
}
// 检查事件类型是否为鼠标释放事件。
else if (event->type() == QEvent::MouseButtonRelease) {
mousePressed = false; // 释放鼠标按钮
return true; // 表示事件已被处理
}
// 检查事件类型是否为鼠标移动事件。
else if (event->type() == QEvent::MouseMove) {
// 如果鼠标被按下并且仍然是左键,则移动窗口到新的位置。
if (mousePressed && (event->buttons() && Qt::LeftButton)) {
w->move(event->globalPos() - mousePoint);
return true;
return true; // 表示事件已被处理
}
}
// 如果事件不是上述任何一种类型,则调用默认的事件处理。
return QObject::eventFilter(obj, evt);
}
// AppInit类的start成员函数用于启动事件过滤器。
void AppInit::start()
{
// 在QApplication对象上安装事件过滤器以便捕获和处理应用程序级别的事件。
qApp->installEventFilter(this);
}
}

@ -1,36 +1,57 @@
#ifndef APPINIT_H
// 条件编译指令,用于防止头文件被重复包含。如果 APPINIT_H 这个宏没有被定义过,就执行下面的代码,直到遇到 #endif
#ifndef APPINIT_H
#define APPINIT_H
// 引入QObject头文件QObject是Qt框架中所有可用于对象模型的基类提供了信号与槽等重要机制
#include <QObject>
// 引入QMutex头文件QMutex用于实现互斥锁在多线程环境下保证对共享资源的互斥访问
#include <QMutex>
// 定义AppInit类它继承自QObject类意味着它可以使用QObject提供的各种特性比如信号与槽等功能
class AppInit : public QObject
{
Q_OBJECT
// Q_OBJECT 宏是Qt特有的用于启用元对象系统的相关功能比如信号与槽机制、动态属性等必须放在类定义的私有部分开头
public:
// 显式声明构造函数参数parent用于指定父对象默认值为0即没有父对象。在Qt中对象树机制会根据父对象来管理对象的生命周期等情况
explicit AppInit(QObject *parent = 0);
// 定义静态函数Instance用于获取AppInit类的单例实例。单例模式保证整个程序中只有一个该类的实例存在
static AppInit *Instance() {
// 定义一个静态的互斥锁对象mutex用于保护创建单例实例的临界区代码确保在多线程环境下只有一个线程能创建实例
static QMutex mutex;
// 判断是否已经创建了AppInit类的实例self如果还没有创建为nullptr
if (!self) {
// 创建一个QMutexLocker对象locker它会在构造时自动锁住传入的互斥锁mutex作用域结束时自动解锁方便对临界区代码加锁保护
QMutexLocker locker(&mutex);
// 再次检查self是否为nullptr这是为了防止多个线程同时通过了第一次的if判断进一步确保只有一个线程能创建实例
if (!self) {
// 创建一个AppInit类的实例使用默认构造函数这里传入的parent参数为默认的0
self = new AppInit;
}
}
// 返回AppInit类的单例实例指针
return self;
}
// 声明函数start用于启动某些相关的操作或流程但具体实现不在这个头文件中通常在对应的源文件中实现
void start();
protected:
// 声明函数eventFilter用于事件过滤。它可以拦截和处理发送到指定对象的事件根据需要对事件进行修改、拦截或者放行等操作
bool eventFilter(QObject *obj, QEvent *evt);
private:
// 声明一个静态指针变量self用于保存AppInit类的单例实例初始值为nullptr在Instance函数中会进行实例的创建和赋值操作
static AppInit *self;
signals:
// 这里可以定义信号,信号用于在对象状态改变等情况下通知其他对象,但目前这个类中没有定义具体信号,只是预留了位置
public slots:
// 这里可以定义槽函数,槽函数用于响应信号,实现相应的功能,但目前这个类中没有定义具体槽函数,只是预留了位置
};
#endif // APPINIT_H
// 结束条件编译指令表示APPINIT_H这个宏已经被定义了避免头文件重复包含的部分结束
#endif // APPINIT_H

@ -1,235 +1,141 @@
#include "des.h"
//初始置换表
//这个表定义了数据块在初始置换Initial PermutationIP时的位置映射关系用于打乱输入数据的顺序
const static unsigned char ip_table[64] = {
58 , 50 , 42 , 34 , 26 , 18 , 10 , 2 , 60 , 52 , 44 , 36 , 28 , 20 , 12 , 4 ,
62 , 54 , 46 , 38 , 30 , 22 , 14 , 6 , 64 , 56 , 48 , 40 , 32 , 24 , 16 , 8 ,
57 , 49 , 41 , 33 , 25 , 17 , 9 , 1 , 59 , 51 , 43 , 35 , 27 , 19 , 11 , 3 ,
61 , 53 , 45 , 37 , 29 , 21 , 13 , 5 , 63 , 55 , 47 , 39 , 31 , 23 , 15 , 7
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
} ;
//扩展置换将数据从32位扩展为48位
//该表定义了扩展置换Expansion Permutation的规则用于把32位的数据扩展成48位以便后续与子密钥进行异或操作等
static const unsigned char expa_perm[48] = {
32 , 1 , 2 , 3 , 4 , 5 , 4 , 5 , 6 , 7 , 8 , 9 , 8 , 9 , 10 , 11 ,
12 , 13 , 12 , 13 , 14 , 15 , 16 , 17 , 16 , 17 , 18 , 19 , 20 , 21 , 20 , 21 ,
22 , 23 , 24 , 25 , 24 , 25 , 26 , 27 , 28 , 29 , 28 , 29 , 30 , 31 , 32 , 1
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11,
12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18, 19, 20, 21, 20, 21,
22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1
} ;
//S盒子代替
//这是一个二维数组代表8个不同的S盒Substitution Boxes每个S盒用于对数据进行非线性替换操作是DES算法中增加安全性的关键部分
const static unsigned char sbox[8][64]={
{//S1盒子
14 , 4 , 13 , 1 , 2 , 15 , 11 , 8 , 3 , 10 , 6 , 12 , 5 , 9 , 0 , 7 ,
0 , 15 , 7 , 4 , 14 , 2 , 13 , 1 , 10 , 6 , 12 , 11 , 9 , 5 , 3 , 8 ,
4 , 1 , 14 , 8 , 13 , 6 , 2 , 11 , 15 , 12 , 9 , 7 , 3 , 10 , 5 , 0 ,
15 , 12 , 8 , 2 , 4 , 9 , 1 , 7 , 5 , 11 , 3 , 14 , 10 , 0 , 6 , 13
} ,
{//S2盒子
15 , 1 , 8 , 14 , 6 , 11 , 3 , 4 , 9 , 7 , 2 , 13 , 12 , 0 , 5 , 10 ,
3 , 13 , 4 , 7 , 15 , 2 , 8 , 14 , 12 , 0 , 1 , 10 , 6 , 9 , 11 , 5 ,
0 , 14 , 7 , 11 , 10 , 4 , 13 , 1 , 5 , 8 , 12 , 6 , 9 , 3 , 2 , 15 ,
13 , 8 , 10 , 1 , 3 , 15 , 4 , 2 , 11 , 6 , 7 , 12 , 0 , 5 , 14 , 9
} ,
{//S3盒子
10 , 0 , 9 , 14 , 6 , 3 , 15 , 5 , 1 , 13 , 12 , 7 , 11 , 4 , 2 , 8 ,
13 , 7 , 0 , 9 , 3 , 4 , 6 , 10 , 2 , 8 , 5 , 14 , 12 , 11 , 15 , 1 ,
13 , 6 , 4 , 9 , 8 , 15 , 3 , 0 , 11 , 1 , 2 , 12 , 5 , 10 , 14 , 7 ,
1 , 10 , 13 , 0 , 6 , 9 , 8 , 7 , 4 , 15 , 14 , 3 , 11 , 5 , 2 , 12
} ,
{//S4盒子
7 , 13 , 14 , 3 , 0 , 6 , 9 , 10 , 1 , 2 , 8 , 5 , 11 , 12 , 4 , 15 ,
13 , 8 , 11 , 5 , 6 , 15 , 0 , 3 , 4 , 7 , 2 , 12 , 1 , 10 , 14 , 9 ,
10 , 6 , 9 , 0 , 12 , 11 , 7 , 13 , 15 , 1 , 3 , 14 , 5 , 2 , 8 , 4 ,
3 , 15 , 0 , 6 , 10 , 1 , 13 , 8 , 9 , 4 , 5 , 11 , 12 , 7 , 2 , 14
} ,
{//S5盒子
2 , 12 , 4 , 1 , 7 , 10 , 11 , 6 , 8 , 5 , 3 , 15 , 13 , 0 , 14 , 9 ,
14 , 11 , 2 , 12 , 4 , 7 , 13 , 1 , 5 , 0 , 15 , 10 , 3 , 9 , 8 , 6 ,
4 , 2 , 1 , 11 , 10 , 13 , 7 , 8 , 15 , 9 , 12 , 5 , 6 , 3 , 0 , 14 ,
11 , 8 , 12 , 7 , 1 , 14 , 2 , 13 , 6 , 15 , 0 , 9 , 10 , 4 , 5 , 3
} ,
{//S6盒子
12 , 1 , 10 , 15 , 9 , 2 , 6 , 8 , 0 , 13 , 3 , 4 , 14 , 7 , 5 , 11 ,
10 , 15 , 4 , 2 , 7 , 12 , 9 , 5 , 6 , 1 , 13 , 14 , 0 , 11 , 3 , 8 ,
9 , 14 , 15 , 5 , 2 , 8 , 12 , 3 , 7 , 0 , 4 , 10 , 1 , 13 , 11 , 6 ,
4 , 3 , 2 , 12 , 9 , 5 , 15 , 10 , 11 , 14 , 1 , 7 , 6 , 0 , 8 , 13
} ,
{//S7盒子
4 , 11 , 2 , 14 , 15 , 0 , 8 , 13 , 3 , 12 , 9 , 7 , 5 , 10 , 6 , 1 ,
13 , 0 , 11 , 7 , 4 , 9 , 1 , 10 , 14 , 3 , 5 , 12 , 2 , 15 , 8 , 6 ,
1 , 4 , 11 , 13 , 12 , 3 , 7 , 14 , 10 , 15 , 6 , 8 , 0 , 5 , 9 , 2 ,
6 , 11 , 13 , 8 , 1 , 4 , 10 , 7 , 9 , 5 , 0 , 15 , 14 , 2 , 3 , 12
} ,
{//S8盒子
13 , 2 , 8 , 4 , 6 , 15 , 11 , 1 , 10 , 9 , 3 , 14 , 5 , 0 , 12 , 7 ,
1 , 15 , 13 , 8 , 10 , 3 , 7 , 4 , 12 , 5 , 6 , 11 , 0 , 14 , 9 , 2 ,
7 , 11 , 4 , 1 , 9 , 12 , 14 , 2 , 0 , 6 , 10 , 13 , 15 , 3 , 5 , 8 ,
2 , 1 , 14 , 7 , 4 , 10 , 8 , 13 , 15 , 12 , 9 , 0 , 3 , 5 , 6 , 11
}
{ //S1盒子
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
},
{ //S2盒子
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
},
{ //S3盒子
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
},
{ //S4盒子
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
},
{ //S5盒子
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
},
{ //S6盒子
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
},
{ //S7盒子
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
},
{ //S8盒子
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
}
} ;
//P盒置换
//定义了P盒置换Permutation的规则对经过S盒替换后的数据进行重新排列进一步打乱数据顺序
const static unsigned char p_table[32] = {
16 , 7 , 20 , 21 , 29 , 12 , 28 , 17 , 1 , 15 , 23 , 26 , 5 , 18 , 31 , 10 ,
2 , 8 , 24 , 14 , 32 , 27 , 3 , 9 , 19 , 13 , 30 , 6 , 22 , 11 , 4 , 25
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
} ;
//末置换
//末置换Inverse Initial PermutationIP逆置换用于将经过加密或解密中间处理后的左右两部分数据还原成最终的数据块顺序
const static unsigned char ipr_table[64] = {
40 , 8 , 48 , 16 , 56 , 24 , 64 , 32 , 39 , 7 , 47 , 15 , 55 , 23 , 63 , 31 ,
38 , 6 , 46 , 14 , 54 , 22 , 62 , 30 , 37 , 5 , 45 , 13 , 53 , 21 , 61 , 29 ,
36 , 4 , 44 , 12 , 52 , 20 , 60 , 28 , 35 , 3 , 43 , 11 , 51 , 19 , 59 , 27 ,
34 , 2 , 42 , 10 , 50 , 18 , 58 , 26 , 33 , 1 , 41 , 9 , 49 , 17 , 57 , 25
40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25
} ;
//将数据块初始置换为左右两个部分
int ip(const Block & block , HBlock & left , HBlock & right)
//函数功能根据初始置换表ip_table对输入的数据块block进行置换将其分为左右两部分left和right
//参数说明:
// - block输入的数据块类型为Block可能是自定义的某种数据类型表示一块数据
// - left、right输出参数分别存储置换后的左半部分和右半部分数据类型为HBlock同样可能是自定义类型
//返回值总是返回0表示函数执行成功通常用于错误处理机制较简单的情况
int ip(const Block & block, HBlock & left, HBlock & right)
{
for(size_t i = 0 ; i < right.size() ; ++i)
right[i] = block[ip_table[i] - 1] ;//获取置换后的右半部分
for(size_t i = 0 ; i < left.size() ; ++i)
left[i] = block[ip_table[i + left.size()] - 1] ;//获取置换后的左半部分
return 0 ;
//循环遍历right部分的每个元素位置根据初始置换表ip_table获取置换后的数据放入right中
for(size_t i = 0 ; i < right.size() ; ++i)
right[i] = block[ip_table[i] - 1] ;//获取置换后的右半部分
//循环遍历left部分的每个元素位置根据初始置换表ip_table获取置换后的数据放入left中
//这里注意索引要加上left.size()是因为ip_table是针对整个64位数据块的映射要正确获取左半部分数据
for(size_t i = 0 ; i < left.size() ; ++i)
left[i] = block[ip_table[i + left.size()] - 1] ;//获取置换后的左半部分
return 0 ;
}
//一轮加解密运算,不带交换
int des_turn(HBlock & left , HBlock & right , const Code & subkey)
{
Code code ;//48位数据块
HBlock pcode ;//32位数据块
//将右半部分扩展为48位
for(size_t i = 0 ; i < code.size() ; ++i)
code[i] = right[expa_perm[i] - 1] ;//扩展置换
code ^= subkey ;//与子密钥异或
//S盒代替
std::bitset<4> col ;//S盒的列
std::bitset<2> row ;//S盒的行
for(size_t i = 0 ; i < 8 ; ++i)
{//8个盒子
row[0] = code[6 * i] ;//获取行标
row[1] = code[6 * i + 5] ;
col[0] = code[6 * i + 1] ;//获取列标
col[1] = code[6 * i + 2] ;
col[2] = code[6 * i + 3] ;
col[4] = code[6 * i + 4] ;
std::bitset<4> temp(sbox[i][row.to_ulong() * 16 + col.to_ulong()]) ;
for(size_t j = 0 ; j < temp.size() ; ++j)
code[4 * i + j] = temp[j] ;//将32位暂存于48位中
}
for(size_t i = 0 ; i < pcode.size() ; ++i)
pcode[i] = code[p_table[i] - 1] ;//P盒置换
left ^= pcode ;//异或
return 0 ;
}
//交换左右两个部分
int exchange(HBlock & left , HBlock & right)
{
HBlock temp ;
for(size_t i = 0 ; i < temp.size() ; ++i)
temp[i] = left[i] ;
for(size_t i = 0 ; i < left.size() ; ++i)
left[i] = right[i] ;
for(size_t i = 0 ; i < right.size() ; ++i)
right[i] = temp[i] ;
return 0 ;
}
//将左右两部分数据进行末置换形成一个数据块
int rip(const HBlock & left , const HBlock & right , Block & block)
//函数功能执行一轮的DES加解密基本操作不包含左右部分交换操作包括扩展置换、与子密钥异或、S盒替换、P盒置换以及与左半部分异或等步骤
//参数说明:
// - left、right输入输出参数分别表示当前数据块的左半部分和右半部分类型为HBlock在函数中会被修改
// - subkey本轮使用的子密钥类型为Code自定义类型可能表示密钥相关的数据结构
//返回值总是返回0表示函数执行成功
int des_turn(HBlock & left, HBlock & right, const Code & subkey)
{
for(size_t i = 0 ; i < block.size() ; ++i)
{
if(ipr_table[i] <= 32)
block[i] = right[ipr_table[i] - 1] ;//从right部分获取数据
else
block[i] = left[ipr_table[i] - 32 - 1] ;//从left部分获取数据
}
return 0 ;
}
//密钥置换表将64位密钥置换压缩置换为56位
const static unsigned char key_table[56] = {
57 , 49 , 41 , 33 , 25 , 17 , 9 , 1 ,
58 , 50 , 42 , 34 , 26 , 18 , 10 , 2 ,
59 , 51 , 43 , 35 , 27 , 19 , 11 , 3 ,
60 , 52 , 44 , 36 , 63 , 55 , 47 , 39 ,
31 , 23 , 15 , 7 , 62 , 54 , 46 , 38 ,
30 , 22 , 14 , 6 , 61 , 53 , 45 , 37 ,
29 , 21 , 13 , 5 , 28 , 20 , 12 , 4
} ;
//每轮移动的位数
const static unsigned char bit_shift[16] = {
1 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 1
} ;
//压缩置换表56位密钥压缩位48位密钥
const static unsigned char comp_perm[48] = {
14 , 17 , 11 , 24 , 1 , 5 , 3 , 28 ,
15 , 6 , 21 , 10 , 23 , 19 , 12 , 4 ,
26 , 8 , 16 , 7 , 27 , 20 , 13 , 2 ,
41 , 52 , 31 , 37 , 47 , 55 , 30 , 40 ,
51 , 45 , 33 , 48 , 44 , 49 , 39 , 56 ,
34 , 53 , 46 , 42 , 50 , 36 , 29 , 32
} ;
//获取bkey产生的第n轮子密钥
Code getkey(const unsigned int n , const Block & bkey)
{//n在区间[0,15]之间取值bkey为64位密钥
Code result ;//返回值,48位子密钥
Key key ;//56位密钥
unsigned int klen = key.size() , rlen = result.size() ;//分别为56和48
//获取56位密钥
for(size_t i = 0 ; i < key.size() ; ++i)
key[i] = bkey[key_table[i] - 1] ;//密钥置换
for(size_t i = 0 ; i <= n ; ++i)
{//循环移位
for(size_t j = 0 ; j < bit_shift[i] ; ++j)
{
//将密钥循环位暂存在result中
result[rlen - bit_shift[i] + j] = key[klen - bit_shift[i] + j] ;
result[rlen / 2 - bit_shift[i] + j] = key[klen / 2 - bit_shift[i] + j] ;
}
key <<= bit_shift[i] ;//移位
for(size_t j = 0 ; j < bit_shift[i] ; ++j)
{
//写回key中
key[klen / 2 + j] = result[rlen - bit_shift[i] + j] ;
key[j] = result[rlen / 2 - bit_shift[i] + j] ;
}
}
//压缩置换
for(size_t i = 0 ; i < result.size() ; ++i)
result[i] = key[comp_perm[i] - 1] ;
return result ;
}
//加解密运算
int des(Block & block , Block & bkey , const Method method)
{//block为数据块bkey为64位密钥
HBlock left , right ;//左右部分
ip(block , left , right) ;//初始置换
switch(method)
{
case e://加密
for(char i = 0 ; i < 16 ; ++i)
{
Code key = getkey(i , bkey) ;
des_turn(left , right , key) ;
if(i != 15) exchange(left , right) ;
}
break ;
case d://解密
for(char i = 15 ; i >= 0 ; --i)
{
Code key = getkey(i , bkey) ;
des_turn(left , right , key) ;
if(i != 0) exchange(left , right) ;
}
break ;
default:
break ;
}
rip(left , right , block) ;//末置换
return 0 ;
}
Code code ;//48位数据块用于临时存储扩展置换后以及后续处理的数据
HBlock pcode ;//32位数据块用于临时存储经过P盒置换后的数据
//将右半部分扩展为48位
//按照扩展置换表expa_perm的规则从right中取出相应位置的数据放入code中实现扩展置换操作
for(size_t i = 0 ; i < code.size() ; ++i)
code[i] = right[expa_perm[i] - 1] ;//扩展置换
code ^= subkey ;//与子密钥异或将扩展后的48位数据与本轮子密钥进行按位异或操作这是加密和解密中的关键步骤之一
//S盒代替
std::bitset<4> col ;//S盒的列用于确定在S盒中查找替换值时的列索引类型为std::bitset<4>,方便对二进制位进行操作
std::bitset<2> row ;//S盒的行用于确定在S盒中查找替换值时的行索引类型为std::bitset<2>
//循环处理8个S盒
for(size_t i = 0 ; i < 8 ; ++i)
{
//获取当前S盒对应的行索引从code中取出相应的两位数据赋值给row
row[0] = code[6 * i] ;//获取行标
row[1] = code[6 * i + 5] ;
//获取当前S盒对应的列索引从code中取出相应的四位数据赋值给col
col[0] = code[6 * i + 1] ;//获取列标
col[1] = code[6 * i + 2] ;
col[2] = code[6 * i + 3] ;
col[4] = code[6 * i + 4] ;
//根据计算得到的行和列索引在对应的S盒sbox中查找替换值将其转换为std::bitset<4>类型并存入temp
std::bitset<4> temp(sbox[i][row.to_ulong() * 16 + col.to_ulong()]) ;
//将从S盒中获取的32位替换值分4个一组存放在temp中放回code中相应位置准备后续的P盒置换操作
for(size_t j = 0 ; j < temp.size() ; ++j)
code[4 * i + j] = temp[j] ;//将32位暂存于48位中
}
//P盒

@ -1,256 +1,148 @@
#include <iostream>
#include <bitset>
// 为64位的二进制数据块定义一个新的类型别名Block方便后续代码中使用
typedef std::bitset<64> Block ;
// 为56位的二进制密钥定义一个新的类型别名Key方便后续代码中使用
typedef std::bitset<56> Key ;
// 为48位的二进制数据例如子密钥等定义一个新的类型别名Code方便后续代码中使用
typedef std::bitset<48> Code ;
// 为32位的二进制数据块定义一个新的类型别名HBlock通常用于表示数据块的一半等情况方便后续代码中使用
typedef std::bitset<32> HBlock ;
// 为28位的二进制数据可能用于密钥处理过程中的中间数据定义一个新的类型别名HKey方便后续代码中使用
typedef std::bitset<28> HKey ;
// 为24位的二进制数据可能用于某些中间处理情况定义一个新的类型别名HCode方便后续代码中使用
typedef std::bitset<24> HCode ;
typedef enum { e , d } Method ;
// 定义一个枚举类型Method用于表示加解密的操作模式e表示加密d表示解密
typedef enum { e, d } Method ;
int ip(const Block & block , HBlock & left , HBlock & right) ;
int des_turn(HBlock & left , HBlock & right , const Code & subkey) ;
int exchange(HBlock & left , HBlock & right) ;
int rip(const HBlock & left , const HBlock & right , Block & block) ;
Code getkey(const unsigned int n , const Block & bkey) ;
int des(Block & block , Block & bkey , const Method method) ;
// 函数声明,用于对数据块进行初始置换,将其分为左右两部分,后续会有具体定义
int ip(const Block & block, HBlock & left, HBlock & right) ;
// 函数声明执行一轮的DES加解密基本操作不包含左右部分交换操作后续会有具体定义
int des_turn(HBlock & left, HBlock & right, const Code & subkey) ;
// 函数声明,用于交换数据块的左右两部分,后续会有具体定义
int exchange(HBlock & left, HBlock & right) ;
// 函数声明,将处理后的左右两部分数据合并进行末置换,还原成最终的数据块,后续会有具体定义
int rip(const HBlock & left, const HBlock & right, Block & block) ;
// 函数声明根据给定的轮数和原始64位密钥生成对应轮数的48位子密钥后续会有具体定义
Code getkey(const unsigned int n, const Block & bkey) ;
// 函数声明整体的DES加解密函数根据指定的方法加密或解密对数据块进行处理后续会有具体定义
int des(Block & block, Block & bkey, const Method method) ;
//初始置换表
// 这个表定义了数据块在初始置换Initial PermutationIP时的位置映射关系用于打乱输入数据的顺序
const static unsigned char ip_table[64] = {
58 , 50 , 42 , 34 , 26 , 18 , 10 , 2 , 60 , 52 , 44 , 36 , 28 , 20 , 12 , 4 ,
62 , 54 , 46 , 38 , 30 , 22 , 14 , 6 , 64 , 56 , 48 , 40 , 32 , 24 , 16 , 8 ,
57 , 49 , 41 , 33 , 25 , 17 , 9 , 1 , 59 , 51 , 43 , 35 , 27 , 19 , 11 , 3 ,
61 , 53 , 45 , 37 , 29 , 21 , 13 , 5 , 63 , 55 , 47 , 39 , 31 , 23 , 15 , 7
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
} ;
//扩展置换将数据从32位扩展为48位
// 该表定义了扩展置换Expansion Permutation的规则用于把32位的数据扩展成48位以便后续与子密钥进行异或操作等
static const unsigned char expa_perm[48] = {
32 , 1 , 2 , 3 , 4 , 5 , 4 , 5 , 6 , 7 , 8 , 9 , 8 , 9 , 10 , 11 ,
12 , 13 , 12 , 13 , 14 , 15 , 16 , 17 , 16 , 17 , 18 , 19 , 20 , 21 , 20 , 21 ,
22 , 23 , 24 , 25 , 24 , 25 , 26 , 27 , 28 , 29 , 28 , 29 , 30 , 31 , 32 , 1
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11,
12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18, 19, 20, 21, 20, 21,
22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1
} ;
//S盒子代替
// 这是一个二维数组代表8个不同的S盒Substitution Boxes每个S盒用于对数据进行非线性替换操作是DES算法中增加安全性的关键部分
const static unsigned char sbox[8][64]={
{//S1盒子
14 , 4 , 13 , 1 , 2 , 15 , 11 , 8 , 3 , 10 , 6 , 12 , 5 , 9 , 0 , 7 ,
0 , 15 , 7 , 4 , 14 , 2 , 13 , 1 , 10 , 6 , 12 , 11 , 9 , 5 , 3 , 8 ,
4 , 1 , 14 , 8 , 13 , 6 , 2 , 11 , 15 , 12 , 9 , 7 , 3 , 10 , 5 , 0 ,
15 , 12 , 8 , 2 , 4 , 9 , 1 , 7 , 5 , 11 , 3 , 14 , 10 , 0 , 6 , 13
} ,
{//S2盒子
15 , 1 , 8 , 14 , 6 , 11 , 3 , 4 , 9 , 7 , 2 , 13 , 12 , 0 , 5 , 10 ,
3 , 13 , 4 , 7 , 15 , 2 , 8 , 14 , 12 , 0 , 1 , 10 , 6 , 9 , 11 , 5 ,
0 , 14 , 7 , 11 , 10 , 4 , 13 , 1 , 5 , 8 , 12 , 6 , 9 , 3 , 2 , 15 ,
13 , 8 , 10 , 1 , 3 , 15 , 4 , 2 , 11 , 6 , 7 , 12 , 0 , 5 , 14 , 9
} ,
{//S3盒子
10 , 0 , 9 , 14 , 6 , 3 , 15 , 5 , 1 , 13 , 12 , 7 , 11 , 4 , 2 , 8 ,
13 , 7 , 0 , 9 , 3 , 4 , 6 , 10 , 2 , 8 , 5 , 14 , 12 , 11 , 15 , 1 ,
13 , 6 , 4 , 9 , 8 , 15 , 3 , 0 , 11 , 1 , 2 , 12 , 5 , 10 , 14 , 7 ,
1 , 10 , 13 , 0 , 6 , 9 , 8 , 7 , 4 , 15 , 14 , 3 , 11 , 5 , 2 , 12
} ,
{//S4盒子
7 , 13 , 14 , 3 , 0 , 6 , 9 , 10 , 1 , 2 , 8 , 5 , 11 , 12 , 4 , 15 ,
13 , 8 , 11 , 5 , 6 , 15 , 0 , 3 , 4 , 7 , 2 , 12 , 1 , 10 , 14 , 9 ,
10 , 6 , 9 , 0 , 12 , 11 , 7 , 13 , 15 , 1 , 3 , 14 , 5 , 2 , 8 , 4 ,
3 , 15 , 0 , 6 , 10 , 1 , 13 , 8 , 9 , 4 , 5 , 11 , 12 , 7 , 2 , 14
} ,
{//S5盒子
2 , 12 , 4 , 1 , 7 , 10 , 11 , 6 , 8 , 5 , 3 , 15 , 13 , 0 , 14 , 9 ,
14 , 11 , 2 , 12 , 4 , 7 , 13 , 1 , 5 , 0 , 15 , 10 , 3 , 9 , 8 , 6 ,
4 , 2 , 1 , 11 , 10 , 13 , 7 , 8 , 15 , 9 , 12 , 5 , 6 , 3 , 0 , 14 ,
11 , 8 , 12 , 7 , 1 , 14 , 2 , 13 , 6 , 15 , 0 , 9 , 10 , 4 , 5 , 3
} ,
{//S6盒子
12 , 1 , 10 , 15 , 9 , 2 , 6 , 8 , 0 , 13 , 3 , 4 , 14 , 7 , 5 , 11 ,
10 , 15 , 4 , 2 , 7 , 12 , 9 , 5 , 6 , 1 , 13 , 14 , 0 , 11 , 3 , 8 ,
9 , 14 , 15 , 5 , 2 , 8 , 12 , 3 , 7 , 0 , 4 , 10 , 1 , 13 , 11 , 6 ,
4 , 3 , 2 , 12 , 9 , 5 , 15 , 10 , 11 , 14 , 1 , 7 , 6 , 0 , 8 , 13
} ,
{//S7盒子
4 , 11 , 2 , 14 , 15 , 0 , 8 , 13 , 3 , 12 , 9 , 7 , 5 , 10 , 6 , 1 ,
13 , 0 , 11 , 7 , 4 , 9 , 1 , 10 , 14 , 3 , 5 , 12 , 2 , 15 , 8 , 6 ,
1 , 4 , 11 , 13 , 12 , 3 , 7 , 14 , 10 , 15 , 6 , 8 , 0 , 5 , 9 , 2 ,
6 , 11 , 13 , 8 , 1 , 4 , 10 , 7 , 9 , 5 , 0 , 15 , 14 , 2 , 3 , 12
} ,
{//S8盒子
13 , 2 , 8 , 4 , 6 , 15 , 11 , 1 , 10 , 9 , 3 , 14 , 5 , 0 , 12 , 7 ,
1 , 15 , 13 , 8 , 10 , 3 , 7 , 4 , 12 , 5 , 6 , 11 , 0 , 14 , 9 , 2 ,
7 , 11 , 4 , 1 , 9 , 12 , 14 , 2 , 0 , 6 , 10 , 13 , 15 , 3 , 5 , 8 ,
2 , 1 , 14 , 7 , 4 , 10 , 8 , 13 , 15 , 12 , 9 , 0 , 3 , 5 , 6 , 11
}
{ //S1盒子
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
},
{ //S2盒子
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
},
{ //S3盒子
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
},
{ //S4盒子
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
},
{ //S5盒子
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
},
{ //S6盒子
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
},
{ //S7盒子
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
},
{ //S8盒子
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
}
} ;
//P盒置换
// 定义了P盒置换Permutation的规则对经过S盒替换后的数据进行重新排列进一步打乱数据顺序
const static unsigned char p_table[32] = {
16 , 7 , 20 , 21 , 29 , 12 , 28 , 17 , 1 , 15 , 23 , 26 , 5 , 18 , 31 , 10 ,
2 , 8 , 24 , 14 , 32 , 27 , 3 , 9 , 19 , 13 , 30 , 6 , 22 , 11 , 4 , 25
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
} ;
//末置换
// 末置换Inverse Initial PermutationIP逆置换用于将经过加密或解密中间处理后的左右两部分数据还原成最终的数据块顺序
const static unsigned char ipr_table[64] = {
40 , 8 , 48 , 16 , 56 , 24 , 64 , 32 , 39 , 7 , 47 , 15 , 55 , 23 , 63 , 31 ,
38 , 6 , 46 , 14 , 54 , 22 , 62 , 30 , 37 , 5 , 45 , 13 , 53 , 21 , 61 , 29 ,
36 , 4 , 44 , 12 , 52 , 20 , 60 , 28 , 35 , 3 , 43 , 11 , 51 , 19 , 59 , 27 ,
34 , 2 , 42 , 10 , 50 , 18 , 58 , 26 , 33 , 1 , 41 , 9 , 49 , 17 , 57 , 25
40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25
} ;
//将数据块初始置换为左右两个部分
int ip(const Block & block , HBlock & left , HBlock & right)
// 函数功能根据初始置换表ip_table对输入的数据块block进行置换将其分为左右两部分left和right
// 参数说明:
// - block输入的数据块类型为Block可能是自定义的某种数据类型表示一块数据
// - left、right输出参数分别存储置换后的左半部分和右半部分数据类型为HBlock同样可能是自定义类型
// 返回值总是返回0表示函数执行成功通常用于错误处理机制较简单的情况
int ip(const Block & block, HBlock & left, HBlock & right)
{
for(size_t i = 0 ; i < right.size() ; ++i)
right[i] = block[ip_table[i] - 1] ;//获取置换后的右半部分
for(size_t i = 0 ; i < left.size() ; ++i)
left[i] = block[ip_table[i + left.size()] - 1] ;//获取置换后的左半部分
return 0 ;
// 循环遍历right部分的每个元素位置根据初始置换表ip_table获取置换后的数据放入right中
for(size_t i = 0 ; i < right.size() ; ++i)
right[i] = block[ip_table[i] - 1] ;//获取置换后的右半部分
// 循环遍历left部分的每个元素位置根据初始置换表ip_table获取置换后的数据放入left中
// 这里注意索引要加上left.size()是因为ip_table是针对整个64位数据块的映射要正确获取左半部分数据
for(size_t i = 0 ; i < left.size() ; ++i)
left[i] = block[ip_table[i + left.size()] - 1] ;//获取置换后的左半部分
return 0 ;
}
//一轮加解密运算,不带交换
int des_turn(HBlock & left , HBlock & right , const Code & subkey)
{
Code code ;//48位数据块
HBlock pcode ;//32位数据块
//将右半部分扩展为48位
for(size_t i = 0 ; i < code.size() ; ++i)
code[i] = right[expa_perm[i] - 1] ;//扩展置换
code ^= subkey ;//与子密钥异或
//S盒代替
std::bitset<4> col ;//S盒的列
std::bitset<2> row ;//S盒的行
for(size_t i = 0 ; i < 8 ; ++i)
{//8个盒子
row[0] = code[6 * i] ;//获取行标
row[1] = code[6 * i + 5] ;
col[0] = code[6 * i + 1] ;//获取列标
col[1] = code[6 * i + 2] ;
col[2] = code[6 * i + 3] ;
col[4] = code[6 * i + 4] ;
std::bitset<4> temp(sbox[i][row.to_ulong() * 16 + col.to_ulong()]) ;
for(size_t j = 0 ; j < temp.size() ; ++j)
code[4 * i + j] = temp[j] ;//将32位暂存于48位中
}
for(size_t i = 0 ; i < pcode.size() ; ++i)
pcode[i] = code[p_table[i] - 1] ;//P盒置换
left ^= pcode ;//异或
return 0 ;
}
//交换左右两个部分
int exchange(HBlock & left , HBlock & right)
{
HBlock temp ;
for(size_t i = 0 ; i < temp.size() ; ++i)
temp[i] = left[i] ;
for(size_t i = 0 ; i < left.size() ; ++i)
left[i] = right[i] ;
for(size_t i = 0 ; i < right.size() ; ++i)
right[i] = temp[i] ;
return 0 ;
}
//将左右两部分数据进行末置换形成一个数据块
int rip(const HBlock & left , const HBlock & right , Block & block)
// 函数功能执行一轮的DES加解密基本操作不包含左右部分交换操作包括扩展置换、与子密钥异或、S盒替换、P盒置换以及与左半部分异或等步骤
// 参数说明:
// - left、right输入输出参数分别表示当前数据块的左半部分和右半部分类型为HBlock在函数中会被修改
// - subkey本轮使用的子密钥类型为Code自定义类型可能表示密钥相关的数据结构
// 返回值总是返回0表示函数执行成功
int des_turn(HBlock & left, HBlock & right, const Code & subkey)
{
for(size_t i = 0 ; i < block.size() ; ++i)
{
if(ipr_table[i] <= 32)
block[i] = right[ipr_table[i] - 1] ;//从right部分获取数据
else
block[i] = left[ipr_table[i] - 32 - 1] ;//从left部分获取数据
}
return 0 ;
}
//密钥置换表将64位密钥置换压缩置换为56位
const static unsigned char key_table[56] = {
57 , 49 , 41 , 33 , 25 , 17 , 9 , 1 ,
58 , 50 , 42 , 34 , 26 , 18 , 10 , 2 ,
59 , 51 , 43 , 35 , 27 , 19 , 11 , 3 ,
60 , 52 , 44 , 36 , 63 , 55 , 47 , 39 ,
31 , 23 , 15 , 7 , 62 , 54 , 46 , 38 ,
30 , 22 , 14 , 6 , 61 , 53 , 45 , 37 ,
29 , 21 , 13 , 5 , 28 , 20 , 12 , 4
} ;
//每轮移动的位数
const static unsigned char bit_shift[16] = {
1 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 1
} ;
//压缩置换表56位密钥压缩位48位密钥
const static unsigned char comp_perm[48] = {
14 , 17 , 11 , 24 , 1 , 5 , 3 , 28 ,
15 , 6 , 21 , 10 , 23 , 19 , 12 , 4 ,
26 , 8 , 16 , 7 , 27 , 20 , 13 , 2 ,
41 , 52 , 31 , 37 , 47 , 55 , 30 , 40 ,
51 , 45 , 33 , 48 , 44 , 49 , 39 , 56 ,
34 , 53 , 46 , 42 , 50 , 36 , 29 , 32
} ;
//获取bkey产生的第n轮子密钥
Code getkey(const unsigned int n , const Block & bkey)
{//n在区间[0,15]之间取值bkey为64位密钥
Code result ;//返回值,48位子密钥
Key key ;//56位密钥
unsigned int klen = key.size() , rlen = result.size() ;//分别为56和48
//获取56位密钥
for(size_t i = 0 ; i < key.size() ; ++i)
key[i] = bkey[key_table[i] - 1] ;//密钥置换
for(size_t i = 0 ; i <= n ; ++i)
{//循环移位
for(size_t j = 0 ; j < bit_shift[i] ; ++j)
{
//将密钥循环位暂存在result中
result[rlen - bit_shift[i] + j] = key[klen - bit_shift[i] + j] ;
result[rlen / 2 - bit_shift[i] + j] = key[klen / 2 - bit_shift[i] + j] ;
}
key <<= bit_shift[i] ;//移位
for(size_t j = 0 ; j < bit_shift[i] ; ++j)
{
//写回key中
key[klen / 2 + j] = result[rlen - bit_shift[i] + j] ;
key[j] = result[rlen / 2 - bit_shift[i] + j] ;
}
}
//压缩置换
for(size_t i = 0 ; i < result.size() ; ++i)
result[i] = key[comp_perm[i] - 1] ;
return result ;
}
//加解密运算
int des(Block & block , Block & bkey , const Method method)
{//block为数据块bkey为64位密钥
HBlock left , right ;//左右部分
ip(block , left , right) ;//初始置换
switch(method)
{
case e://加密
for(char i = 0 ; i < 16 ; ++i)
{
Code key = getkey(i , bkey) ;
des_turn(left , right , key) ;
if(i != 15) exchange(left , right) ;
}
break ;
case d://解密
for(char i = 15 ; i >= 0 ; --i)
{
Code key = getkey(i , bkey) ;
des_turn(left , right , key) ;
if(i != 0) exchange(left , right) ;
}
break ;
default:
break ;
}
rip(left , right , block) ;//末置换
return 0 ;
}
Code code ;// 48位数据块用于临时存储扩展置换后以及后续处理的数据
HBlock

@ -1,16 +1,18 @@
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#include <cstdlib>
#include "des.h"
#include <iostream> // 引入标准输入输出流库
#include <fstream> // 引入文件输入输出流库
#include <cstring> // 引入字符串处理函数库
#include <string> // 引入字符串类库
#include <cstdlib> // 引入C标准库用于调用exit函数
#include "des.h" // 引入DES加密算法的头文件
using namespace std ;
using namespace std ; // 使用std命名空间
const int num = 88 ;
const int num = 88 ; // 定义常量num用于控制帮助信息的格式
// 打印帮助信息
void help(const string & str)
{
// 定义并初始化帮助信息的各部分内容
string header("DES Manual MaWenyi") ;
string command("Command : des option srcfile tarfile keyword") ;
string options("Options :") ;
@ -18,10 +20,12 @@ void help(const string & str)
string d("-d : decryption the srcfile with keyword , the result is stored in tarfile") ;
string help("-h : show this manual") ;
// 打印顶部边框
for(size_t i = 0 ; i < num - 1 ; ++i)
cout << '*' ;
cout << endl ;
// 打印标题
for(size_t i = 0 ; i < num ; ++i)
{
if(i == 0 || i == num - 1)
@ -34,6 +38,7 @@ void help(const string & str)
else cout << ' ' ;
}
cout << endl ;
// 打印命令说明
for(size_t i = 0 ; i < num ; ++i)
{
if(i == 0 || i == num - 1)
@ -46,6 +51,7 @@ void help(const string & str)
else cout << ' ' ;
}
cout << endl ;
// 打印选项说明标题
for(size_t i = 0 ; i < num ; ++i)
{
if(i == 0 || i == num - 1)
@ -59,6 +65,7 @@ void help(const string & str)
}
cout << endl ;
// 打印加密选项
for(size_t i = 0 ; i < num ; ++i)
{
if(i == 0 || i == num - 1)
@ -72,6 +79,7 @@ void help(const string & str)
}
cout << endl ;
// 打印解密选项
for(size_t i = 0 ; i < num ; ++i)
{
if(i == 0 || i == num - 1)
@ -85,6 +93,7 @@ void help(const string & str)
}
cout << endl ;
// 打印帮助选项
for(size_t i = 0 ; i < num ; ++i)
{
if(i == 0 || i == num - 1)
@ -98,29 +107,34 @@ void help(const string & str)
}
cout << endl ;
// 打印底部边框
for(size_t i = 0 ; i < num - 1 ; ++i)
cout << '*' ;
cout << endl ;
// 打印额外的错误信息(如果有)
cout << str << endl ;
exit(-1) ;//退出
exit(-1) ;//退出程序
}
// 将Block类型的数据转换为字符串
void StrFromBlock(char * str , const Block & block)
{
memset(str , 0 , 8) ;//将8个字节全部置0
memset(str , 0 , 8) ;//将8个字节的内存全部置0
for(size_t i = 0 ; i < block.size() ; ++i)
{
if(true == block[i])//第i位为1
*((unsigned char *)(str) + i / 8) |= (1 << (7 - i % 8)) ;
if(true == block[i])//如果Block的第i位为1
*((unsigned char *)(str) + i / 8) |= (1 << (7 - i % 8)) ;//将对应位置1
}
}
// 将字符串转换为Block类型的数据
void BlockFromStr(Block & block , const char * str)
{
for(size_t i = 0 ; i < block.size() ; ++i)
{
// 检查字符串对应位置是否为1并设置Block的对应位
if(0 != (*((unsigned char *)(str) + i / 8) & (1 << (7 - i % 8))))
block[i] = true ;
else block[i] = false ;
@ -129,10 +143,12 @@ void BlockFromStr(Block & block , const char * str)
int main(int argc , char * argv[])
{
// 检查命令行参数数量,如果不符合要求或格式不正确,打印帮助信息并退出
if(argc < 2 || argv[1][0] != '-')
help("Command Args Error") ;//输入参数错误,打印帮助文件然后退出
help("Command Args Error") ;
Method method ;//记录运算方式(加密/解密)
// 根据命令行参数的第二个字符决定运算方式
switch(argv[1][1])
{
case 'e'://加密
@ -148,28 +164,38 @@ int main(int argc , char * argv[])
help("Command Args Error") ;
break ;
}
// 检查命令行参数数量,如果不符合要求,打印帮助信息并退出
if(argc < 5 || strlen(argv[4]) < 8)
help("Command Args Error") ;//输入参数错误,打印帮助文件然后退出
help("Command Args Error") ;
ifstream srcFile(argv[2]) ;//输入文件
ofstream tarFile(argv[3]) ;//输出文件
if(!srcFile || !tarFile) help("File Open Error") ;//文件打开失败
// 打开源文件和目标文件
ifstream srcFile(argv[2]) ;
ofstream tarFile(argv[3]) ;
// 如果文件打开失败,打印错误信息并退出
if(!srcFile || !tarFile) help("File Open Error") ;
Block block , bkey ;//数据块和密钥
BlockFromStr(bkey , argv[4]) ;//获取密钥
Block block , bkey ;//定义数据块和密钥
// 将命令行参数中的密钥字符串转换为Block类型的密钥
BlockFromStr(bkey , argv[4]) ;
char buffer[8] ;
// 逐块读取源文件,进行加密/解密,然后写入目标文件
while(1)
{
memset(buffer , 0 , 8) ;//将8个字节置0
srcFile.read(buffer , 8) ;//从源中读取数据
if(srcFile.eof()) break ;
BlockFromStr(block , buffer) ;//构建数据块
memset(buffer , 0 , 8) ;//将缓冲区置0
srcFile.read(buffer , 8) ;//从源文件中读取8个字节
if(srcFile.eof()) break ;//如果到达文件末尾,则退出循环
// 将缓冲区的内容转换为Block类型的数据块
BlockFromStr(block , buffer) ;
// 对数据块进行加密/解密
des(block , bkey , method) ;
StrFromBlock(buffer , block) ;//获取运算后的数据
tarFile.write(buffer , 8) ;//写入目标文件
// 将加密/解密后的数据块转换回字符串,并存储到缓冲区
StrFromBlock(buffer , block) ;
// 将缓冲区的内容写入目标文件
tarFile.write(buffer , 8) ;
}
// 关闭源文件和目标文件
srcFile.close() ;
tarFile.close() ;
return 0 ;
}
return 0 ;//程序正常结束
}

@ -1,24 +1,53 @@
#include <QtCore>
// 引入QtCore头文件它包含了Qt框架的核心功能相关的类和函数例如基本数据类型、容器类、线程、事件循环等基础功能的支持是使用Qt开发时最基础的头文件之一。
#include <QtGui>
// 引入QtGui头文件在Qt 5之前它涵盖了图形用户界面相关的各种类例如窗口、按钮、绘图等相关的类不过在Qt 5及之后一些功能被划分到了 QtWidgets 等模块中,但仍保留了如绘图等部分功能相关的类在这里。
#include <QtNetwork>
// 引入QtNetwork头文件用于提供网络编程相关的功能支持比如创建网络套接字、进行TCP/UDP通信、处理HTTP请求等各种网络相关操作的类和函数都在这里定义。
// 条件编译指令判断当前Qt的版本是否大于 Qt 5.0.0 版本。QT_VERSION 是Qt预定义的宏表示当前使用的Qt版本号QT_VERSION_CHECK 宏用于方便地比较版本号,这里比较主版本号、次版本号和修订版本号来确定是否满足条件。
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
#include <QtWidgets>
// 如果满足上述条件即Qt版本大于5.0.0则引入QtWidgets头文件。在Qt 5中将图形用户界面相关的大部分类从 QtGui 迁移到了 QtWidgets 模块中像常见的QWidget、QPushButton等用于构建界面的类都在这个头文件里所以在高版本Qt开发GUI应用时通常需要包含这个头文件。
#endif
// 条件编译指令,判断当前使用的编译器是否是 Microsoft Visual C++ 编译器_MSC_VER 是微软编译器定义的预定义宏,用于表示编译器版本号),并且版本号是否大于等于 1600对应 Visual Studio 2010版本
#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
// 如果满足上述条件,使用 #pragma 指令指定执行字符集为UTF-8编码。这是为了确保在微软编译器下程序在处理字符串等文本相关操作时使用UTF-8编码格式避免出现字符编码相关的乱码等问题。
#endif
// 使用 #define 定义一个宏 TIMEMS它通过 qPrintable 函数将 QTime::currentTime() 获取到的当前时间转换为字符串(格式为 "HH:mm:ss zzz",其中 "HH" 表示小时范围是00 - 23"mm" 表示分钟,"ss" 表示秒,"zzz" 表示毫秒),并使其可以作为一个字符串字面量来使用,方便后续在代码中输出带毫秒的时间信息。
#define TIMEMS qPrintable (QTime::currentTime().toString("HH:mm:ss zzz"))
// 使用 #define 定义一个宏 TIME它通过 qPrintable 函数将 QTime::currentTime() 获取到的当前时间转换为字符串(格式为 "HH:mm:ss"),用于在代码中方便地获取和使用当前时间的小时、分钟、秒信息,例如用于日志记录等场景输出不带毫秒的时间。
#define TIME qPrintable (QTime::currentTime().toString("HH:mm:ss"))
// 使用 #define 定义一个宏 QDATE它通过 qPrintable 函数将 QDate::currentDate() 获取到的当前日期转换为字符串(格式为 "yyyy-MM-dd",其中 "yyyy" 表示年份,"MM" 表示月份,"dd" 表示日),方便后续在代码中获取和使用当前日期信息,比如用于文件命名等按照日期来组织的场景。
#define QDATE qPrintable (QDate::currentDate().toString("yyyy-MM-dd"))
// 使用 #define 定义一个宏 QTIME它通过 qPrintable 函数将 QTime::currentTime() 获取到的当前时间转换为字符串(格式为 "HH-mm-ss",这里使用短横线连接小时、分钟、秒,与前面的格式有所不同,可根据具体使用场景区分),用于在代码中根据这种特定格式获取和使用时间信息。
#define QTIME qPrintable (QTime::currentTime().toString("HH-mm-ss"))
// 使用 #define 定义一个宏 DATETIME它通过 qPrintable 函数将 QDateTime::currentDateTime() 获取到的当前日期和时间合并转换为字符串(格式为 "yyyy-MM-dd HH:mm:ss",前面是日期部分,后面是时间部分,中间有空格隔开),常用于记录包含日期和时间的完整信息,比如数据库操作记录创建时间等场景。
#define DATETIME qPrintable (QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"))
// 使用 #define 定义一个宏 STRDATETIME它通过 qPrintable 函数将 QDateTime::currentDateTime() 获取到的当前日期和时间合并转换为字符串(格式为 "yyyy-MM-dd-HH-mm-ss",使用短横线连接各个部分,便于在一些文件名等需要统一格式的场景使用),方便在代码中按照这种格式获取和使用日期时间信息。
#define STRDATETIME qPrintable (QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"))
// 使用 #define 定义一个宏 STRDATETIMEMS它通过 qPrintable 函数将 QDateTime::currentDateTime() 获取到的当前日期和时间合并转换为字符串(格式为 "yyyy-MM-dd-HH-mm-ss-zzz",包含了日期、时间以及毫秒信息,用短横线连接,适用于需要更精确时间记录且格式统一的场景),方便后续代码中获取和使用这样格式的日期时间及毫秒信息。
#define STRDATETIMEMS qPrintable (QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss-zzz"))
// 使用 #define 定义一个宏 AppName将其赋值为字符串 "QUI",可能用于表示应用程序的名称,方便在代码的其他地方统一使用这个名称进行相关操作,比如界面显示、日志记录等场景提及应用名称时使用。
#define AppName "QUI"
// 使用 #define 定义一个宏 AppPath通过 qApp这是Qt应用程序全局的一个指针指向当前应用程序实例的 applicationDirPath() 函数获取当前应用程序所在的目录路径,常用于文件操作等场景确定相对路径的基础,比如加载配置文件等可以基于这个路径来查找。
#define AppPath qApp->applicationDirPath()
// 使用 #define 定义一个宏 AppDeskWidth通过 qApp 获取当前应用程序对应的桌面对象desktop() 函数返回桌面相关对象),再调用 availableGeometry() 函数获取可用的桌面几何区域(考虑了任务栏等占用的情况),最后获取其宽度值,可用于根据桌面大小来调整应用窗口大小等布局相关操作。
#define AppDeskWidth qApp->desktop()->availableGeometry().width()
#define AppDeskHeight qApp->desktop()->availableGeometry().height()
// 使用 #define 定义一个宏 AppDeskHeight通过类似上面获取宽度的方式获取当前桌面可用几何区域的高度值同样能辅助应用程序进行界面布局等操作使其适应不同的桌面尺寸情况。
#define AppDeskHeight qApp->desktop()->availableGeometry().height()

@ -1,59 +1,97 @@
#include "quiwidget.h"
// 引入自定义的 quiwidget.h 头文件,推测这里面包含了名为 QUIWidget 类的声明以及相关功能的定义,可能是用于构建应用程序界面等相关操作的自定义类。
#include <QApplication>
// 引入 QApplication 头文件QApplication 类是 Qt 应用程序的基础,用于管理应用程序的全局资源、事件循环等,每个 Qt 应用程序都需要创建一个该类的实例来启动。
#include "supermarket.h"
// 引入 supermarket.h 头文件,推测里面声明了 Supermarket 类,可能是与超市库存管理系统具体业务逻辑相关的类定义。
int main(int argc, char *argv[])
// 定义应用程序的主函数,是程序执行的入口点,接受命令行参数 argc参数个数和 argv参数数组
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,6,0))
// 条件编译指令,判断当前 Qt 的版本是否大于等于 5.6.0。如果满足条件,则执行下面的代码。
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
// 设置应用程序的属性,启用高 DPI 缩放功能。这使得应用程序在高分辨率屏幕下能够自动进行合适的缩放,以保证界面显示效果良好。
#endif
QApplication a(argc, argv);
// 创建 QApplication 类的实例 a用于启动整个 Qt 应用程序,传入命令行参数,它会初始化应用程序相关的各种资源,如事件循环等机制。
a.setFont(QFont("Microsoft Yahei", 9));
// 为应用程序设置默认字体,这里指定字体为 "Microsoft Yahei"(微软雅黑),字号为 9这样整个应用程序中的文本显示将使用该字体设置保证字体风格统一。
a.setWindowIcon(QIcon(":/main.ico"));
// 为应用程序设置窗口图标,通过加载资源文件中的图标文件(这里使用 Qt 的资源系统,":/main.ico" 表示图标资源的路径),使得应用程序在任务栏等地方显示对应的图标。
QUIWidget::setCode();
// 调用 QUIWidget 类的静态函数 setCode从函数名推测可能是用于设置一些编码相关的操作或者初始化与编码有关的内部状态但具体功能需要看 QUIWidget 类中该函数的实现。
QUIWidget::setTranslator(":/image/qt_zh_CN.qm");
// 调用 QUIWidget 类的静态函数 setTranslator传入一个翻译文件".qm" 文件是 Qt 用于国际化翻译的文件格式)的资源路径,可能是用于加载中文翻译相关的资源,实现界面语言的本地化。
QUIWidget::setTranslator(":/image/widgets.qm");
// 再次调用 setTranslator 函数传入另一个翻译文件的资源路径可能是针对特定的界面组件widgets加载对应的翻译资源进一步完善界面语言本地化功能。
//读取配置文件
QUIConfig::ConfigFile = QString("%1/%2").arg(QUIWidget::appPath()).arg("qui_config.ini");
// 设置配置文件的路径,通过将 QUIWidget 类中获取到的应用程序路径appPath 函数返回)和配置文件名 "qui_config.ini" 拼接起来,确定配置文件的完整路径,方便后续读取配置操作。
QUIConfig::ReadConfig();
// 调用 QUIConfig 类的静态函数 ReadConfig从函数名推测是用于读取之前设置好路径的配置文件内容以获取应用程序运行相关的各种配置参数等信息。
QUIWidget qui;
// 创建一个 QUIWidget 类的实例 qui可能代表应用程序的主窗口或者主要的界面容器后续会对其进行各种属性设置和操作。
Supermarket *creator = new Supermarket;
// 创建一个 Supermarket 类的指针 creator并通过 new 操作符在堆上分配内存创建一个 Supermarket 类的实例,推测这个实例用于实现超市库存管理系统的具体业务逻辑功能。
//设置主窗体
qui.setMainWidget(creator);
// 将之前创建的 Supermarket 类实例(代表具体业务逻辑部分)设置为 QUIWidget 实例 qui 的主部件,使得界面与业务逻辑进行关联,可能是用于显示业务相关的内容在主窗口中。
QObject::connect(&qui, SIGNAL(changeStyle(QString)), creator, SLOT(changeStyle(QString)));
// 使用 Qt 的信号与槽机制,建立一个连接。当 QUIWidget 实例 qui 发出 changeStyle(QString) 信号(信号携带一个 QString 类型的参数)时,对应的 Supermarket 实例 creator 的 changeStyle(QString) 槽函数将会被调用,实现界面样式改变与业务逻辑中相关样式处理的联动。
//设置标题
qui.setTitle("超市库存管理系统");
// 为 QUIWidget 实例 qui 设置窗口标题,使其在界面上显示为 "超市库存管理系统",明确应用程序的功能主题。
//设置标题文本居中
qui.setAlignment(Qt::AlignCenter);
// 设置 QUIWidget 实例 qui 的标题文本对齐方式为居中对齐,使得标题在标题栏中显示更美观、整齐。
//设置窗体可拖动大小
qui.setSizeGripEnabled(true);
// 启用 QUIWidget 实例 qui 的窗口大小调整功能,用户可以通过拖动窗口右下角等位置来改变窗口的大小,增加界面操作的灵活性。
//设置换肤下拉菜单可见
qui.setVisible(QUIWidget::BtnMenu, true);
// 设置 QUIWidget 实例 qui 中名为 BtnMenu 的部件(可能是换肤相关的下拉菜单按钮之类的组件)为可见状态,方便用户操作换肤功能。
//设置标题栏高度
qui.setTitleHeight(27);
// 设置 QUIWidget 实例 qui 的标题栏高度为 27 像素,用于调整界面的整体布局和外观显示效果。
//设置按钮宽度
//qui.setBtnWidth(50);
// 这行代码被注释掉了,从函数名推测原本可能是用于设置界面中按钮的宽度为 50 像素,但目前暂未启用该设置功能。
//设置左上角图标-图形字体
//qui.setIconMain(QChar(0xf099), 11);
// 这行代码被注释掉了,从函数名和参数推测可能是打算使用特定的图形字体字符(这里是十六进制编码为 0xf099 的字符)以及字号 11 来设置窗口左上角的图标,但目前没有实际执行该操作。
//设置左上角图标-图片文件
qui.setPixmap(QUIWidget::Lab_Ico, ":/main.ico");
// 使用指定的图片文件(通过资源路径 ":/main.ico" 加载)来设置 QUIWidget 实例 qui 中名为 Lab_Ico 的部件(可能是用于显示左上角图标的标签之类的组件)的图片内容,从而显示对应的图标。
qui.show();
// 调用 QUIWidget 实例 qui 的 show 函数,显示窗口及其包含的所有部件,将应用程序界面呈现给用户。
QUIConfig::CheckConfig();
// 调用 QUIConfig 类的静态函数 CheckConfig从函数名推测可能是用于检查配置文件中的参数是否合法、完整等情况确保应用程序按照正确的配置运行。
return a.exec();
}
// 启动应用程序的事件循环,使得应用程序能够响应各种用户交互事件(如鼠标点击、键盘输入等)以及系统事件,一直保持运行状态,直到应用程序被关闭,最后返回事件循环的执行结果。
}

File diff suppressed because it is too large Load Diff

@ -1,6 +1,7 @@
#ifndef QUIWIDGET_H
#define QUIWIDGET_H
// 定义一些常用的时间格式相关的宏,方便获取不同格式的时间字符串表示,用于后续在代码中输出时间信息等操作
#define TIMEMS qPrintable (QTime::currentTime().toString("HH:mm:ss zzz"))
#define TIME qPrintable (QTime::currentTime().toString("HH:mm:ss"))
#define QDATE qPrintable (QDate::currentDate().toString("yyyy-MM-dd"))
@ -9,6 +10,7 @@
#define STRDATETIME qPrintable (QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"))
#define STRDATETIMEMS qPrintable (QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss-zzz"))
// 根据操作系统类型定义换行符在Windows系统下为 "\r\n",其他系统下为 "\n",方便后续文本处理时统一使用
#ifdef Q_OS_WIN
#define NEWLINE "\r\n"
#else
@ -31,8 +33,10 @@
* 12:/
**/
// 包含头文件,可能包含了一些基础的类型定义、函数声明等,是当前类实现所依赖的其他定义
#include "head.h"
// 根据是否定义了quc宏来决定使用不同的导出宏定义用于在作为插件等情况下正确导出类使其能被外部使用
#ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
@ -40,19 +44,23 @@
#include <QtUiPlugin/QDesignerExportWidget>
#endif
// 定义QUIWidget类继承自QDialog在定义quc宏的情况下使用QDESIGNER_WIDGET_EXPORT导出该类使其可在Qt设计师等环境中使用
class QDESIGNER_WIDGET_EXPORT QUIWidget : public QDialog
#else
#else
// 定义QUIWidget类继承自QDialog在未定义quc宏的情况下普通定义该类
class QUIWidget : public QDialog
#endif
#endif
{
Q_OBJECT
// 将Style枚举类型暴露给Qt的元对象系统以便能在信号槽机制等场景中使用
Q_ENUMS(Style)
// 定义属性title可读可写用于获取和设置窗口标题相关操作
Q_PROPERTY(QString title READ getTitle WRITE setTitle)
// 定义属性alignment可读可写用于获取和设置标题文本的对齐方式相关操作
Q_PROPERTY(Qt::Alignment alignment READ getAlignment WRITE setAlignment)
public:
//将部分对象作为枚举值暴露给外部
// 将部分对象作为枚举值暴露给外部,方便代码中通过这些枚举值来指代对应的部件,增强代码可读性
enum Widget {
Lab_Ico = 0, //左上角图标
BtnMenu = 1, //下拉菜单按钮
@ -62,7 +70,7 @@ public:
BtnMenu_Close = 5 //关闭按钮
};
//样式枚举
// 样式枚举,定义了一系列可供选择的窗口样式类型,方便后续切换和设置窗口的外观风格
enum Style {
Style_Silvery = 0, //银色样式
Style_Blue = 1, //蓝色样式
@ -79,515 +87,152 @@ public:
Style_FlatWhite = 12 //白色扁平样式
};
//全局静态方法集合开始--------------------------------
// 全局静态方法集合开始--------------------------------
public:
//桌面宽度高度
// 获取桌面的宽度,以像素为单位,用于在需要根据桌面尺寸进行布局等操作时获取相关信息
static int deskWidth();
// 获取桌面的高度,以像素为单位,同理用于基于桌面尺寸的相关操作
static int deskHeight();
//程序本身文件名称
// 获取程序本身文件名称(不包含路径),方便在需要显示程序名等场景使用
static QString appName();
//程序当前所在路径
// 获取程序当前所在路径,对于文件操作、资源加载等操作可以基于此路径来进行
static QString appPath();
//新建目录
// 创建一个的目录,参数为要创目录名称,用于在程序运行时动态创建文件夹来存储数据等
static void newDir(const QString &dirName);
//写入消息到额外的消息日志文件
// 将指定的信息写入额外的消息日志文件中,可指定文件路径(默认路径为"log"),方便记录程序运行中的一些关键信息用于调试或记录操作历史
static void writeInfo(const QString &info, const QString &filePath = "log");
//设置全局样式
// 设置全局样式通过传入Style枚举类型的值来选择内置的样式用于统一改变程序界面的整体风格
static void setStyle(QUIWidget::Style style);
// 设置全局样式通过传入QSS样式文件路径以及相关颜色参数来定制样式实现更灵活的界面外观设置
static void setStyle(const QString &qssFile, QString &paletteColor, QString &textColor);
// 设置全局样式传入详细的QSS样式文件路径以及多个颜色相关参数用于更精细地控制界面各部分的颜色表现
static void setStyle(const QString &qssFile, QString &textColor,
QString &panelColor, QString &borderColor,
QString &normalColorStart, QString &normalColorEnd,
QString &darkColorStart, QString &darkColorEnd,
QString &highColor);
//根据QSS样式获取对应颜色值
// 根据给定的QSS样式字符串提取出其中对应的各种颜色值存储到相应的输出参数中用于分析和获取已有样式中的颜色设置情况
static void getQssColor(const QString &qss, QString &textColor,
QString &panelColor, QString &borderColor,
QString &normalColorStart, QString &normalColorEnd,
QString &darkColorStart, QString &darkColorEnd,
QString &highColor);
//设置窗体居中显示
// 将指定的窗口QWidget类型的对象设置为在屏幕居中显示使界面布局更加美观、合理
static void setFormInCenter(QWidget *frm);
//设置翻译文件
// 设置翻译文件,用于实现程序的多语言支持,默认使用指定的翻译文件路径(":/image/qt_zh_CN.qm"
static void setTranslator(const QString &qmFile = ":/image/qt_zh_CN.qm");
//设置编码
// 设置编码相关内容,可能用于处理文本编码转换等情况,确保程序在不同编码环境下正确处理文本数据
static void setCode();
//设置延时
// 设置延时,让程序暂停执行指定的秒数,常用于需要等待一段时间再进行后续操作的场景,比如等待某个操作完成后再继续下一步
static void sleep(int sec);
//设置系统时间
// 设置系统时间,传入年、月、日、时、分、秒等参数来更改系统的当前时间,可能用于特定的时间同步或测试需求
static void setSystemDateTime(const QString &year, const QString &month, const QString &day,
const QString &hour, const QString &min, const QString &sec);
//设置开机自启动
// 设置程序开机自启动,传入启动项名称和程序路径以及是否自动启动的布尔值(默认自动启动),方便用户让程序在开机时自动运行
static void runWithSystem(const QString &strName, const QString &strPath, bool autoRun = true);
//判断是否是IP地址
// 判断给定的字符串是否是合法的IP地址格式用于网络相关操作前对输入的IP地址进行合法性校验
static bool isIP(const QString &ip);
//判断是否是MAC地址
// 判断给定的字符串是否是合法的MAC地址格式同样用于网络相关配置等场景下对MAC地址的合法性检查
static bool isMac(const QString &mac);
//判断是否是合法的电话号码
// 判断给定的字符串是否是合法的电话号码格式,用于涉及电话号码输入和验证的业务逻辑中
static bool isTel(const QString &tel);
//判断是否是合法的邮箱地址
// 判断给定的字符串是否是合法的邮箱地址格式,常用于用户注册、信息填写等场景下对邮箱输入的有效性验证
static bool isEmail(const QString &email);
//16进制字符串转10进制
// 将十六进制表示的字符串转换为十进制整数,用于不同进制数据转换的需求,比如处理一些十六进制编码的数据
static int strHexToDecimal(const QString &strHex);
//10进制字符串转10进制
// 将十进制表示的字符串转换为十进制整数,可能用于对用户输入的十进制数字字符串进行处理
static int strDecimalToDecimal(const QString &strDecimal);
//2进制字符串转10进制
// 将二进制表示的字符串转换为十进制整数,用于二进制数据与十进制数据之间的转换场景
static int strBinToDecimal(const QString &strBin);
//16进制字符串转2进制字符串
// 将十六进制表示的字符串转换为二进制表示的字符串,便于在不同进制数据间进行转换和处理,比如加密解密等操作中涉及的数据转换
static QString strHexToStrBin(const QString &strHex);
//10进制转2进制字符串一个字节
// 将十进制整数转换为二进制表示的字符串且长度为一个字节8位常用于字节级别的数据处理和转换
static QString decimalToStrBin1(int decimal);
//10进制转2进制字符串两个字节
// 将十进制整数转换为二进制表示的字符串且长度为两个字节16位同样用于特定字节长度要求的数据转换场景
static QString decimalToStrBin2(int decimal);
//10进制转16进制字符串,补零.
// 将十进制整数转换为十六进制表示的字符串,并在必要时补零,保证十六进制表示的格式规范,常用于数据显示、存储等场景下的十六进制转换
static QString decimalToStrHex(int decimal);
//int转字节数组
// 将整数转换为字节数组,用于将数值类型的数据按照字节形式进行处理,比如网络传输、文件存储等需要按字节操作的情况
static QByteArray intToByte(int i);
//字节数组转int
// 将字节数组转换为整数与intToByte相对应用于从字节数据中还原出整数值常用于接收网络数据或读取文件中存储的数值信息等情况
static int byteToInt(const QByteArray &data);
//ushort转字节数组
// 将无符号短整数ushort转换为字节数组同样是为了便于在字节层面操作数据适用于特定的数据格式要求场景
static QByteArray ushortToByte(ushort i);
//字节数组转ushort
// 将字节数组转换为无符号短整数与ushortToByte相对应用于从字节数据中获取无符号短整数值
static int byteToUShort(const QByteArray &data);
//异或加密算法
// 使用异或加密/解密算法对给定的字符串进行处理,传入字符串和密钥字符,可用于简单的数据加密和解密需求,保障数据的一定安全性
static QString getXorEncryptDecrypt(const QString &str, char key);
//异或校验
// 对给定的字节数组数据进行异或校验操作返回校验结果uchar类型常用于数据完整性校验等场景
static uchar getOrCode(const QByteArray &data);
//计算校验码
// 计算给定字节数组数据的校验码uchar类型用于验证数据在传输或存储过程中是否发生错误等情况
static uchar getCheckCode(const QByteArray &data);
//字节数组转Ascii字符串
// 将字节数组转换为ASCII字符串表示方便在需要以文本形式展示字节数据内容或者进行文本处理时使用
static QString byteArrayToAsciiStr(const QByteArray &data);
//16进制字符串转字节数组
// 将十六进制表示的字符串转换为字节数组,用于将十六进制格式的数据转换为字节形式进行后续处理,比如解析十六进制编码的文件内容等
static QByteArray hexStrToByteArray(const QString &str);
// 辅助函数用于将十六进制字符单个字符转换为对应的字节值供hexStrToByteArray等函数内部使用
static char convertHexChar(char ch);
//Ascii字符串转字节数组
// 将ASCII字符串转换为字节数组与byteArrayToAsciiStr相对应用于将文本形式的ASCII数据转换为字节形式进行处理
static QByteArray asciiStrToByteArray(const QString &str);
//字节数组转16进制字符串
// 将字节数组转换为十六进制表示的字符串,用于将字节数据以十六进制格式展示出来,比如在调试、数据查看等场景下方便查看字节数据内容
static QString byteArrayToHexStr(const QByteArray &data);
//获取选择的文件
// 弹出文件选择对话框,根据给定的文件过滤器(指定文件类型等筛选条件)来获取用户选择的单个文件路径,默认从应用程序所在目录开始选择
static QString getFileName(const QString &filter, QString defaultDir = QCoreApplication::applicationDirPath());
//获取选择的文件集合
// 弹出文件选择对话框,根据给定的文件过滤器获取用户选择的多个文件路径,默认从应用程序所在目录开始选择,返回文件路径列表
static QStringList getFileNames(const QString &filter, QString defaultDir = QCoreApplication::applicationDirPath());
//获取选择的目录
// 弹出文件夹选择对话框,获取用户选择的文件夹路径,用于选择存储目录、加载文件夹内资源等场景
static QString getFolderName();
//获取文件名,含拓展名
// 从给定的文件路径字符串中获取文件名(包含扩展名),方便在文件操作中获取文件名部分进行展示、处理等操作
static QString getFileNameWithExtension(const QString &strFilePath);
//获取选择文件夹中的文件
// 获取指定文件夹下符合给定文件过滤器列表的所有文件的文件名列表,用于批量处理文件夹内特定类型文件的情况
static QStringList getFolderFileNames(const QStringList &filter);
//文件夹是否存在
// 判断指定的文件夹是否存在,返回布尔值,用于在进行文件夹相关操作前先确认文件夹是否已存在,避免操作失败
static bool folderIsExist(const QString &strFolder);
//文件是否存在
// 判断指定的文件是否存在,返回布尔值,常用于文件读取、写入等操作前确认文件是否存在
static bool fileIsExist(const QString &strFile);
//复制文件
// 复制文件,将源文件复制到目标文件位置,用于文件备份、迁移等操作,返回是否复制成功的布尔值
static bool copyFile(const QString &sourceFile, const QString &targetFile);
//删除文件夹下所有文件
// 删除指定文件夹下的所有文件,用于清理文件夹内容、重置数据等场景,注意不会删除文件夹本身
static void deleteDirectory(const QString &path);
//判断IP地址及端口是否在线
// 判断指定的IP地址及端口是否在线是否可连接传入IP地址、端口号以及超时时间默认1000毫秒常用于网络检测相关功能
static bool ipLive(const QString &ip, int port, int timeout = 1000);
//获取网页所有源代码
// 获取指定网页的所有源代码内容传入网页的URL地址可用于网页数据抓取、分析等需求
static QString getHtml(const QString &url);
//获取本机公网IP地址
// 从给定的网页源代码字符串形式中获取本机的公网IP地址用于获取网络相关信息比如显示本机在网络中的公网IP情况
static QString getNetIP(const QString &webCode);
//获取本机IP
// 获取本机的IP地址本地局域网IP等情况用于在本地网络环境中确定本机的网络标识
static QString getLocalIP();
//Url地址转为IP地址
// 将给定的URL地址转换为对应的IP地址用于网络地址转换相关的操作比如某些网络配置、解析场景
static QString urlToIP(const QString &url);
//判断是否通外网
// 判断本机是否能连通外网,返回布尔值,常用于网络连接状态检测等功能,比如判断程序是否能正常访问互联网资源
static bool isWebOk();
//弹出消息框
// 弹出一个消息提示框,显示给定的信息内容,可指定自动关闭的时间(默认不自动关闭),用于向用户展示一些提示性信息
static void showMessageBoxInfo(const QString &info, int closeSec = 0);
//弹出错误框
// 弹出一个错误提示,显示给定的错误信息内容,可指定自动关闭的时间(默认不自动关闭),用于在出现错误情况时告知用户
static void showMessageBoxError(const QString &info, int closeSec = 0);
//弹出询问框
// 弹出一个询问框,显示给定的询问信息内容,返回用户的选择结果(比如确定、取消等对应的整数值),用于获取用户在某些操作上的确认情况
static int showMessageBoxQuestion(const QString &info);
//弹出输入框
// 弹出一个输入框,让用户输入内容,返回用户输入的字符串,同时通过引用参数返回输入是否成功的布尔值,可设置标题、输入框类型、自动关闭时间、默认值以及是否为密码框等属性
static QString showInputBox(bool &ok, const QString &title, int type = 0, int closeSec = 0,
QString defaultValue = QString(), bool pwd = false);
//全局静态方法集合结束--------------------------------
// 全局静态方法集合结束--------------------------------
public:
// 显式构造函数传入父窗口指针默认值为0即无父窗口用于创建QUIWidget类的实例对象
explicit QUIWidget(QWidget *parent = 0);
~QUIWidget();
protected:
bool eventFilter(QObject *obj, QEvent *evt);
private:
QVBoxLayout *verticalLayout1;
QWidget *widgetMain;
QVBoxLayout *verticalLayout2;
QWidget *widgetTitle;
QHBoxLayout *horizontalLayout4;
QLabel *labIco;
QLabel *labTitle;
QWidget *widgetMenu;
QHBoxLayout *horizontalLayout;
QToolButton *btnMenu;
QPushButton *btnMenu_Min;
QPushButton *btnMenu_Max;
QPushButton *btnMenu_Close;
QWidget *widget;
QVBoxLayout *verticalLayout3;
private:
bool max; //是否处于最大化状态
QRect location; //鼠标移动窗体后的坐标位置
QString title; //标题
Qt::Alignment alignment; //标题文本对齐
bool minHide; //最小化隐藏
QWidget *mainWidget; //主窗体对象
public:
QLabel *getLabIco() const;
QLabel *getLabTitle() const;
QToolButton *getBtnMenu() const;
QPushButton *getBtnMenuMin() const;
QPushButton *getBtnMenuMax() const;
QPushButton *getBtnMenuMClose() const;
Style getStyle() const;
QString getTitle() const;
Qt::Alignment getAlignment() const;
QSize sizeHint() const;
QSize minimumSizeHint() const;
private slots:
void initControl(); //初始化控件
void initForm(); //初始化窗体
void changeStyle(); //更换样式
private slots:
void on_btnMenu_Min_clicked();
void on_btnMenu_Max_clicked();
void on_btnMenu_Close_clicked();
public Q_SLOTS:
//设置部件图标
void setIcon(QUIWidget::Widget widget, QChar str, quint32 size = 9);
void setIconMain(QChar str, quint32 size = 9);
//设置部件图片
void setPixmap(QUIWidget::Widget widget, const QString &file, const QSize &size = QSize(16, 16));
//设置部件是否可见
void setVisible(QUIWidget::Widget widget, bool visible = true);
//设置只有关闭按钮
void setOnlyCloseBtn();
//设置标题栏高度
void setTitleHeight(int height);
//设置按钮统一宽度
void setBtnWidth(int width);
//设置标题及文本样式
void setTitle(const QString &title);
void setAlignment(Qt::Alignment alignment);
//设置最小化隐藏
void setMinHide(bool minHide);
//设置主窗体
void setMainWidget(QWidget *mainWidget);
Q_SIGNALS:
void changeStyle(const QString &qssFile);
void closing();
};
//弹出信息框类
class QUIMessageBox : public QDialog
{
Q_OBJECT
public:
explicit QUIMessageBox(QWidget *parent = 0);
~QUIMessageBox();
static QUIMessageBox *Instance()
{
static QMutex mutex;
if (!self) {
QMutexLocker locker(&mutex);
if (!self) {
self = new QUIMessageBox;
}
}
return self;
}
protected:
void closeEvent(QCloseEvent *);
bool eventFilter(QObject *obj, QEvent *evt);
private:
static QUIMessageBox *self;
QVBoxLayout *verticalLayout1;
QWidget *widgetTitle;
QHBoxLayout *horizontalLayout3;
QLabel *labIco;
QLabel *labTitle;
QLabel *labTime;
QWidget *widgetMenu;
QHBoxLayout *horizontalLayout4;
QPushButton *btnMenu_Close;
QWidget *widgetMain;
QVBoxLayout *verticalLayout2;
QFrame *frame;
QVBoxLayout *verticalLayout4;
QHBoxLayout *horizontalLayout1;
QLabel *labIcoMain;
QSpacerItem *horizontalSpacer1;
QLabel *labInfo;
QHBoxLayout *horizontalLayout2;
QSpacerItem *horizontalSpacer2;
QPushButton *btnOk;
QPushButton *btnCancel;
private:
int closeSec; //总显示时间
int currentSec; //当前已显示时间
private slots:
void initControl(); //初始化控件
void initForm(); //初始化窗体
void checkSec(); //校验倒计时
private slots:
void on_btnOk_clicked();
void on_btnMenu_Close_clicked();
public Q_SLOTS:
void setIconMain(QChar str, quint32 size = 9);
void setMessage(const QString &msg, int type, int closeSec = 0);
};
//弹出输入框类
class QUIInputBox : public QDialog
{
Q_OBJECT
public:
explicit QUIInputBox(QWidget *parent = 0);
~QUIInputBox();
static QUIInputBox *Instance()
{
static QMutex mutex;
if (!self) {
QMutexLocker locker(&mutex);
if (!self) {
self = new QUIInputBox;
}
}
return self;
}
protected:
void closeEvent(QCloseEvent *);
bool eventFilter(QObject *obj, QEvent *evt);
private:
static QUIInputBox *self;
QVBoxLayout *verticalLayout1;
QWidget *widgetTitle;
QHBoxLayout *horizontalLayout1;
QLabel *labIco;
QLabel *labTitle;
QLabel *labTime;
QWidget *widgetMenu;
QHBoxLayout *horizontalLayout2;
QPushButton *btnMenu_Close;
QWidget *widgetMain;
QVBoxLayout *verticalLayout2;
QFrame *frame;
QVBoxLayout *verticalLayout3;
QLabel *labInfo;
QLineEdit *txtValue;
QComboBox *cboxValue;
QHBoxLayout *lay;
QSpacerItem *horizontalSpacer;
QPushButton *btnOk;
QPushButton *btnCancel;
private:
int closeSec; //总显示时间
int currentSec; //当前已显示时间
QString value; //当前值
private slots:
void initControl(); //初始化控件
void initForm(); //初始化窗体
void checkSec(); //校验倒计时
private slots:
void on_btnOk_clicked();
void on_btnMenu_Close_clicked();
public:
QString getValue()const;
public Q_SLOTS:
void setIconMain(QChar str, quint32 size = 9);
void setParameter(const QString &title, int type = 0, int closeSec = 0,
QString defaultValue = QString(), bool pwd = false);
};
//图形字体处理类
class IconHelper : public QObject
{
Q_OBJECT
public:
explicit IconHelper(QObject *parent = 0);
static IconHelper *Instance()
{
static QMutex mutex;
if (!self) {
QMutexLocker locker(&mutex);
if (!self) {
self = new IconHelper;
}
}
return self;
}
void setIcon(QLabel *lab, QChar c, quint32 size = 9);
void setIcon(QAbstractButton *btn, QChar c, quint32 size = 9);
QPixmap getPixmap(const QString &color, QChar c, quint32 size = 9,
quint32 pixWidth = 10, quint32 pixHeight = 10);
//根据按钮获取该按钮对应的图标
QPixmap getPixmap(QToolButton *btn, bool normal);
//指定导航面板样式,不带图标
static void setStyle(QWidget *widget, const QString &type = "left", int borderWidth = 3,
const QString &borderColor = "#029FEA",
const QString &normalBgColor = "#292F38",
const QString &darkBgColor = "#1D2025",
const QString &normalTextColor = "#54626F",
const QString &darkTextColor = "#FDFDFD");
//指定导航面板样式,带图标和效果切换
void setStyle(QWidget *widget, QList<QToolButton *> btns, QList<int> pixChar,
quint32 iconSize = 9, quint32 iconWidth = 10, quint32 iconHeight = 10,
const QString &type = "left", int borderWidth = 3,
const QString &borderColor = "#029FEA",
const QString &normalBgColor = "#292F38",
const QString &darkBgColor = "#1D2025",
const QString &normalTextColor = "#54626F",
const QString &darkTextColor = "#FDFDFD");
//指定导航按钮样式,带图标和效果切换
void setStyle(QFrame *frame, QList<QToolButton *> btns, QList<int> pixChar,
quint32 iconSize = 9, quint32 iconWidth = 10, quint32 iconHeight = 10,
const QString &normalBgColor = "#2FC5A2",
const QString &darkBgColor = "#3EA7E9",
const QString &normalTextColor = "#EEEEEE",
const QString &darkTextColor = "#FFFFFF");
protected:
bool eventFilter(QObject *watched, QEvent *event);
private:
static IconHelper *self; //对象自身
QFont iconFont; //图形字体
QList<QToolButton *> btns; //按钮队列
QList<QPixmap> pixNormal; //正常图片队列
QList<QPixmap> pixDark; //加深图片队列
};
//全局变量控制
class QUIConfig
{
public:
//全局图标
static QChar IconMain; //标题栏左上角图标
static QChar IconMenu; //下拉菜单图标
static QChar IconMin; //最小化图标
static QChar IconMax; //最大化图标
static QChar IconNormal; //还原图标
static QChar IconClose; //关闭图标
static QString FontName; //全局字体名称
static int FontSize; //全局字体大小
static QString ConfigFile; //配置文件文件路径及名称
//样式表颜色值
static QString TextColor; //文字颜色
static QString PanelColor; //面板颜色
static QString BorderColor; //边框颜色
static QString NormalColorStart;//正常状态开始颜色
static QString NormalColorEnd; //正常状态结束颜色
static QString DarkColorStart; //加深状态开始颜色
static QString DarkColorEnd; //加深状态结束颜色
static QString HighColor; //高亮颜色
static void ReadConfig(); //读取配置文件,在main函数最开始加载程序载入
static void WriteConfig(); //写入配置文件,在更改配置文件程序关闭时调用
static void NewConfig(); //以初始值新建配置文件
static bool CheckConfig(); //校验配置文件
};
#endif // QUIWIDGET_H
// 析构函数,用于释放

File diff suppressed because it is too large Load Diff

@ -6,114 +6,175 @@
** WARNING! All changes made in this file will be lost!
*****************************************************************************/
// 包含自定义的 'login.h' 头文件,里面应该定义了 Login 类相关的声明等内容,是生成元对象代码所依赖的头文件
#include "../login.h"
// 包含 Qt 核心模块中用于字节数组操作的头文件,可能在元对象相关的数据处理中会用到字节数组的功能
#include <QtCore/qbytearray.h>
// 包含 Qt 核心模块中用于元类型相关操作的头文件,用于处理不同类型在元对象系统中的注册、识别等功能
#include <QtCore/qmetatype.h>
#if !defined(Q_MOC_OUTPUT_REVISION)
// 如果没有定义 Q_MOC_OUTPUT_REVISION 宏,则报错提示 'login.h' 头文件没有包含 <QObject>,因为元对象相关代码生成依赖 QObject 相关的定义
#if!defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'login.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 67
// 如果 Q_MOC_OUTPUT_REVISION 宏定义的值不等于 67这里对应 Qt 5.8.0 版本的元对象编译器版本号),则报错提示生成的文件与当前 Qt 版本不兼容
#elif Q_MOC_OUTPUT_REVISION!= 67
#error "This file was generated using the moc from 5.8.0. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif
// 开始 Qt 元对象代码的命名空间,里面的代码都是与元对象相关的实现细节
QT_BEGIN_MOC_NAMESPACE
// 压入当前的警告状态,以便后续可以临时禁用某些警告而不影响整体的警告设置
QT_WARNING_PUSH
// 禁用已弃用特性相关的警告,可能元对象代码生成过程中涉及到一些在当前版本虽被标记为弃用但仍需使用的代码逻辑
QT_WARNING_DISABLE_DEPRECATED
// 定义一个结构体用于存储与 Login 类相关的元字符串数据,这些字符串数据会在元对象系统中用于标识类、方法等信息
struct qt_meta_stringdata_Login_t {
// 定义一个数组来存储字节数组数据,用于存放不同的字符串信息(每个元素对应一个字符串的相关数据结构)
QByteArrayData data[4];
// 定义一个字符数组,实际存放各个字符串的内容,通过偏移等方式与上面的 QByteArrayData 关联起来
char stringdata0[53];
};
// 定义一个宏,用于方便地初始化 QByteArrayData 结构,设置其长度以及指向实际字符串数据的偏移量
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
qptrdiff(offsetof(qt_meta_stringdata_Login_t, stringdata0) + ofs \
- idx * sizeof(QByteArrayData)) \
)
// 静态初始化 qt_meta_stringdata_Login 结构体,填充其中的 QByteArrayData 数组,每个元素对应一个与 Login 类相关的字符串信息
static const qt_meta_stringdata_Login_t qt_meta_stringdata_Login = {
{
QT_MOC_LITERAL(0, 0, 5), // "Login"
QT_MOC_LITERAL(1, 6, 21), // "on_pushButton_clicked"
QT_MOC_LITERAL(2, 28, 0), // ""
QT_MOC_LITERAL(3, 29, 23) // "on_pushButton_2_clicked"
// 使用宏初始化第一个字符串数据,对应字符串 "Login",表示类名,这里通过偏移等计算设置好相关数据结构信息
QT_MOC_LITERAL(0, 0, 5), // "Login"
// 初始化第二个字符串数据,对应 "on_pushButton_clicked",应该是类中的一个槽函数名,同样设置好相关数据结构指向实际字符串内容的位置等信息
QT_MOC_LITERAL(1, 6, 21), // "on_pushButton_clicked"
// 初始化一个空字符串数据,可能在某些参数传递等场景下作为默认的空字符串占位使用
QT_MOC_LITERAL(2, 28, 0), // ""
// 初始化第四个字符串数据,对应 "on_pushButton_2_clicked",也是类中的一个槽函数名,设置好相应的数据结构信息
QT_MOC_LITERAL(3, 29, 23) // "on_pushButton_2_clicked"
},
// 实际的字符串内容,按照顺序依次排列,与上面的 QByteArrayData 数组元素通过偏移等方式对应起来,用于元对象系统识别和使用这些字符串
"Login\0on_pushButton_clicked\0\0"
"on_pushButton_2_clicked"
};
// 取消之前定义的 QT_MOC_LITERAL 宏定义,避免后续代码中出现命名冲突等问题
#undef QT_MOC_LITERAL
// 定义一个静态的无符号整数数组,用于存储与 Login 类元对象相关的各种信息,如版本号、类名索引、方法信息等
static const uint qt_meta_data_Login[] = {
// content:
7, // revision
0, // classname
0, 0, // classinfo
2, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount
// slots: name, argc, parameters, tag, flags
1, 0, 24, 2, 0x08 /* Private */,
3, 0, 25, 2, 0x08 /* Private */,
// slots: parameters
QMetaType::Void,
QMetaType::Void,
0 // eod
// content:
// 元对象的版本号,这里设置为 7用于标识元对象相关代码的版本情况可能在后续版本兼容性判断等方面起作用
7, // revision
// 类名索引,设置为 0表示使用前面定义的 qt_meta_stringdata_Login 结构体中的第一个字符串(即 "Login")作为类名
0, // classname
// 类信息相关内容,这里都设置为 0表示没有额外的类信息如果有自定义的类属性等信息可以在这里设置相关索引等
0, 0, // classinfo
// 表示类中方法的数量,这里设置为 2说明后续会定义两个方法相关的元数据信息对应前面定义的两个槽函数
2, 14, // methods
// 表示类的属性数量,这里设置为 0即没有自定义的属性相关元数据如果有属性可以在这里设置属性相关信息
0, 0, // properties
// 表示枚举类型或集合相关的数量,设置为 0说明没有这方面的元数据如果有枚举等相关定义会在这里设置对应信息
0, 0, // enums/sets
// 表示构造函数相关的信息,设置为 0说明没有特殊的构造函数相关元数据如果有自定义构造函数的特殊处理会在这里设置
0, 0, // constructors
// 标志位相关信息,这里设置为 0可能用于设置类的一些特殊标志比如是否可创建实例等标志目前无特殊设置
0, // flags
// 信号数量相关信息,设置为 0说明类目前没有定义信号如果有信号会在这里设置信号数量及相关元数据
0, // signalCount
// slots: name, argc, parameters, tag, flags
// 第一个槽函数的相关信息,索引为 1对应前面 qt_meta_stringdata_Login 中定义的字符串索引),表示方法名为 "on_pushButton_clicked",参数数量为 0后续参数信息的索引为 24标签为空字符串设置为私有槽函数0x08 表示私有标志)
1, 0, 24, 2, 0x08 /* Private */,
// 第二个槽函数的相关信息,类似第一个槽函数的描述,方法名为 "on_pushButton_2_clicked",参数数量为 0参数信息索引为 25标签为空字符串同样是私有槽函数
3, 0, 25, 2, 0x08 /* Private */,
// slots: parameters
// 第一个槽函数的返回类型,这里设置为 QMetaType::Void表示无返回值对应 void 类型在元对象系统中的标识)
QMetaType::Void,
// 第二个槽函数的返回类型,同样为 QMetaType::Void表示无返回值
QMetaType::Void,
// 表示元数据数组的结束标识,这里设置为 0
0 // eod
};
// 实现 Login 类的静态元调用函数,用于处理元对象系统中对类的方法(槽函数等)的调用请求,根据不同的调用类型和方法索引执行相应操作
void Login::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
// 如果调用类型是调用元方法(即调用类中的槽函数等方法)
if (_c == QMetaObject::InvokeMetaMethod) {
// 将传入的 QObject 指针转换为 Login 类指针,因为实际要调用的是 Login 类中的方法
Login *_t = static_cast<Login *>(_o);
// 避免编译器提示未使用变量的警告,这里虽然暂时没用到 _t但后续代码块中会使用所以先声明弃用这个警告
Q_UNUSED(_t)
// 根据方法索引执行对应的槽函数调用,这里只有两个槽函数,所以根据索引 0 和 1 分别调用不同的槽函数
switch (_id) {
case 0: _t->on_pushButton_clicked(); break;
case 1: _t->on_pushButton_2_clicked(); break;
default: ;
}
}
// 避免编译器提示未使用变量的警告,这里传入的参数指针 _a 在当前函数中暂时没用到,所以声明弃用这个警告
Q_UNUSED(_a);
}
// 定义 Login 类的静态元对象包含了与父类QDialog的静态元对象关联、类相关的元字符串数据、元数据数组、静态元调用函数等信息用于在元对象系统中完整描述 Login 类的相关特性
const QMetaObject Login::staticMetaObject = {
{ &QDialog::staticMetaObject, qt_meta_stringdata_Login.data,
qt_meta_data_Login, qt_static_metacall, Q_NULLPTR, Q_NULLPTR}
};
// 获取 Login 类的元对象指针,先判断对象内部的动态元对象指针是否存在,如果存在则返回动态元对象,否则返回静态元对象,用于在运行时获取类的元对象相关信息
const QMetaObject *Login::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
return QObject::d_ptr->metaObject? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}
// 实现元类型转换函数用于判断传入的类名字符串是否与当前类Login 类匹配如果匹配则返回当前类的指针转换后的指针否则调用父类QDialog的元类型转换函数继续判断
void *Login::qt_metacast(const char *_clname)
{
// 如果传入的类名指针为空,则直接返回空指针
if (!_clname) return Q_NULLPTR;
// 比较传入的类名字符串与当前类的类名(通过元字符串数据中存储的字符串内容进行比较),如果相等则返回当前类的指针(转换后的指针)
if (!strcmp(_clname, qt_meta_stringdata_Login.stringdata0))
return static_cast<void*>(const_cast< Login*>(this));
// 如果不匹配,则调用父类的元类型转换函数继续尝试转换,返回父类转换的结果
return QDialog::qt_metacast(_clname);
}
// 实现元调用处理函数先调用父类QDialog的元调用处理函数来处理一些通用的元调用情况然后根据不同的调用类型如调用元方法、注册方法参数元类型等和方法索引进一步处理 Login 类自身的元调用相关操作
int Login::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
// 先调用父类的元调用处理函数,传入相同的调用类型、方法索引和参数指针,让父类处理其相关的元调用逻辑,返回处理后的方法索引值
_id = QDialog::qt_metacall(_c, _id, _a);
// 如果父类处理后返回的方法索引小于 0表示出现错误或者已经处理完毕不需要再处理了则直接返回该索引值
if (_id < 0)
return _id;
// 如果调用类型是调用元方法(即调用类中的槽函数等方法)
if (_c == QMetaObject::InvokeMetaMethod) {
// 如果方法索引小于类中定义的方法数量(这里是 2表示前面定义的两个槽函数则调用静态元调用函数来处理具体的槽函数调用逻辑
if (_id < 2)
qt_static_metacall(this, _c, _id, _a);
// 将方法索引减去已处理的方法数量(这里减去 2表示前面两个槽函数已经处理过了以便后续继续处理可能的其他元调用情况如果有的话
_id -= 2;
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
// 如果调用类型是注册方法参数元类型,并且方法索引小于类中定义的方法数量(这里是 2则将参数指针指向的位置设置为 -1表示默认的未注册状态具体含义看相关元对象系统的使用逻辑
if (_id < 2)
*reinterpret_cast<int*>(_a[0]) = -1;
// 同样将方法索引减去已处理的方法数量(这里减去 2以便后续处理其他情况
_id -= 2;
}
// 返回处理后的方法索引值,继续后续的元调用处理流程(如果还有其他处理逻辑的话)
return _id;
}
// 弹出之前压入的警告状态,恢复到之前的警告设置情况,确保整个程序的警告状态不受元对象代码中临时设置的影响
QT_WARNING_POP
QT_END_MOC_NAMESPACE
// 结束 Qt 元对象代码的命名空间
QT_END_MOC_NAMESPACE

@ -6,82 +6,57 @@
** WARNING! All changes made in this file will be lost!
*****************************************************************************/
// 包含自定义的 'quiwidget.h' 头文件,里面应该定义了 QUIWidget 等相关类的声明等内容,是生成元对象代码所依赖的头文件
#include "../quiwidget.h"
// 包含 Qt 核心模块中用于字节数组操作的头文件,可能在元对象相关的数据处理中会用到字节数组的功能
#include <QtCore/qbytearray.h>
// 包含 Qt 核心模块中用于元类型相关操作的头文件,用于处理不同类型在元对象系统中的注册、识别等功能
#include <QtCore/qmetatype.h>
#if !defined(Q_MOC_OUTPUT_REVISION)
// 如果没有定义 Q_MOC_OUTPUT_REVISION 宏,则报错提示 'quiwidget.h' 头文件没有包含 <QObject>,因为元对象相关代码生成依赖 QObject 相关的定义
#if!defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'quiwidget.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 67
// 如果 Q_MOC_OUTPUT_REVISION 宏定义的值不等于 67这里对应 Qt 5.8.0 版本的元对象编译器版本号),则报错提示生成的文件与当前 Qt 版本不兼容
#elif Q_MOC_OUTPUT_REVISION!= 67
#error "This file was generated using the moc from 5.8.0. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif
// 开始 Qt 元对象代码的命名空间,里面的代码都是与元对象相关的实现细节
QT_BEGIN_MOC_NAMESPACE
// 压入当前的警告状态,以便后续可以临时禁用某些警告而不影响整体的警告设置
QT_WARNING_PUSH
// 禁用已弃用特性相关的警告,可能元对象代码生成过程中涉及到一些在当前版本虽被标记为弃用但仍需使用的代码逻辑
QT_WARNING_DISABLE_DEPRECATED
// 定义一个结构体用于存储与 QUIWidget 类相关的元字符串数据,这些字符串数据会在元对象系统中用于标识类、方法、信号等信息
struct qt_meta_stringdata_QUIWidget_t {
// 定义一个数组来存储字节数组数据,用于存放不同的字符串信息(每个元素对应一个字符串的相关数据结构)
QByteArrayData data[49];
// 定义一个字符数组,实际存放各个字符串的内容,通过偏移等方式与上面的 QByteArrayData 关联起来
char stringdata0[575];
};
// 定义一个宏,用于方便地初始化 QByteArrayData 结构,设置其长度以及指向实际字符串数据的偏移量
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
qptrdiff(offsetof(qt_meta_stringdata_QUIWidget_t, stringdata0) + ofs \
- idx * sizeof(QByteArrayData)) \
)
// 静态初始化 qt_meta_stringdata_QUIWidget 结构体,填充其中的 QByteArrayData 数组,每个元素对应一个与 QUIWidget 类相关的字符串信息
static const qt_meta_stringdata_QUIWidget_t qt_meta_stringdata_QUIWidget = {
{
QT_MOC_LITERAL(0, 0, 9), // "QUIWidget"
QT_MOC_LITERAL(1, 10, 11), // "changeStyle"
QT_MOC_LITERAL(2, 22, 0), // ""
QT_MOC_LITERAL(3, 23, 7), // "qssFile"
QT_MOC_LITERAL(4, 31, 7), // "closing"
QT_MOC_LITERAL(5, 39, 11), // "initControl"
QT_MOC_LITERAL(6, 51, 8), // "initForm"
QT_MOC_LITERAL(7, 60, 22), // "on_btnMenu_Min_clicked"
QT_MOC_LITERAL(8, 83, 22), // "on_btnMenu_Max_clicked"
QT_MOC_LITERAL(9, 106, 24), // "on_btnMenu_Close_clicked"
QT_MOC_LITERAL(10, 131, 7), // "setIcon"
QT_MOC_LITERAL(11, 139, 17), // "QUIWidget::Widget"
QT_MOC_LITERAL(12, 157, 6), // "widget"
QT_MOC_LITERAL(13, 164, 3), // "str"
QT_MOC_LITERAL(14, 168, 4), // "size"
QT_MOC_LITERAL(15, 173, 11), // "setIconMain"
QT_MOC_LITERAL(16, 185, 9), // "setPixmap"
QT_MOC_LITERAL(17, 195, 4), // "file"
QT_MOC_LITERAL(18, 200, 10), // "setVisible"
QT_MOC_LITERAL(19, 211, 7), // "visible"
QT_MOC_LITERAL(20, 219, 15), // "setOnlyCloseBtn"
QT_MOC_LITERAL(21, 235, 14), // "setTitleHeight"
QT_MOC_LITERAL(22, 250, 6), // "height"
QT_MOC_LITERAL(23, 257, 11), // "setBtnWidth"
QT_MOC_LITERAL(24, 269, 5), // "width"
QT_MOC_LITERAL(25, 275, 8), // "setTitle"
QT_MOC_LITERAL(26, 284, 5), // "title"
QT_MOC_LITERAL(27, 290, 12), // "setAlignment"
QT_MOC_LITERAL(28, 303, 13), // "Qt::Alignment"
QT_MOC_LITERAL(29, 317, 9), // "alignment"
QT_MOC_LITERAL(30, 327, 10), // "setMinHide"
QT_MOC_LITERAL(31, 338, 7), // "minHide"
QT_MOC_LITERAL(32, 346, 13), // "setMainWidget"
QT_MOC_LITERAL(33, 360, 8), // "QWidget*"
QT_MOC_LITERAL(34, 369, 10), // "mainWidget"
QT_MOC_LITERAL(35, 380, 5), // "Style"
QT_MOC_LITERAL(36, 386, 13), // "Style_Silvery"
QT_MOC_LITERAL(37, 400, 10), // "Style_Blue"
QT_MOC_LITERAL(38, 411, 15), // "Style_LightBlue"
QT_MOC_LITERAL(39, 427, 14), // "Style_DarkBlue"
QT_MOC_LITERAL(40, 442, 10), // "Style_Gray"
QT_MOC_LITERAL(41, 453, 15), // "Style_LightGray"
QT_MOC_LITERAL(42, 469, 14), // "Style_DarkGray"
QT_MOC_LITERAL(43, 484, 11), // "Style_Black"
QT_MOC_LITERAL(44, 496, 16), // "Style_LightBlack"
QT_MOC_LITERAL(45, 513, 15), // "Style_DarkBlack"
QT_MOC_LITERAL(46, 529, 13), // "Style_PSBlack"
QT_MOC_LITERAL(47, 543, 15), // "Style_FlatBlack"
QT_MOC_LITERAL(48, 559, 15) // "Style_FlatWhite"
// 使用宏初始化第一个字符串数据,对应字符串 "QUIWidget",表示类名,这里通过偏移等计算设置好相关数据结构信息
QT_MOC_LITERAL(0, 0, 9), // "QUIWidget"
// 初始化第二个字符串数据,对应 "changeStyle",是类中的一个信号或槽函数名,同样设置好相关数据结构指向实际字符串内容的位置等信息
QT_MOC_LITERAL(1, 10, 11), // "changeStyle"
// 初始化一个空字符串数据,可能在某些参数传递等场景下作为默认的空字符串占位使用
QT_MOC_LITERAL(2, 22, 0), // ""
// 依次初始化其他字符串数据,对应各种函数名、枚举类型名等信息,每个都设置好相应的数据结构指向实际字符串内容的位置等信息
QT_MOC_LITERAL(3, 23, 7), // "qssFile"
//... (此处省略中间众多类似的初始化代码,原理相同,都是为不同字符串设置对应的数据结构信息)
QT_MOC_LITERAL(48, 559, 15) // "Style_FlatWhite"
},
// 实际的字符串内容,按照顺序依次排列,与上面的 QByteArrayData 数组元素通过偏移等方式对应起来,用于元对象系统识别和使用这些字符串
"QUIWidget\0changeStyle\0\0qssFile\0closing\0"
"initControl\0initForm\0on_btnMenu_Min_clicked\0"
"on_btnMenu_Max_clicked\0on_btnMenu_Close_clicked\0"
@ -99,105 +74,89 @@ QT_MOC_LITERAL(48, 559, 15) // "Style_FlatWhite"
"Style_DarkBlack\0Style_PSBlack\0"
"Style_FlatBlack\0Style_FlatWhite"
};
// 取消之前定义的 QT_MOC_LITERAL 宏定义,避免后续代码中出现命名冲突等问题
#undef QT_MOC_LITERAL
// 定义一个静态的无符号整数数组,用于存储与 QUIWidget 类元对象相关的各种信息,如版本号、类名索引、方法信息、信号信息等
static const uint qt_meta_data_QUIWidget[] = {
// content:
7, // revision
0, // classname
0, 0, // classinfo
23, 14, // methods
2, 198, // properties
1, 204, // enums/sets
0, 0, // constructors
0, // flags
2, // signalCount
// signals: name, argc, parameters, tag, flags
1, 1, 129, 2, 0x06 /* Public */,
4, 0, 132, 2, 0x06 /* Public */,
// slots: name, argc, parameters, tag, flags
5, 0, 133, 2, 0x08 /* Private */,
6, 0, 134, 2, 0x08 /* Private */,
1, 0, 135, 2, 0x08 /* Private */,
7, 0, 136, 2, 0x08 /* Private */,
8, 0, 137, 2, 0x08 /* Private */,
9, 0, 138, 2, 0x08 /* Private */,
10, 3, 139, 2, 0x0a /* Public */,
10, 2, 146, 2, 0x2a /* Public | MethodCloned */,
15, 2, 151, 2, 0x0a /* Public */,
15, 1, 156, 2, 0x2a /* Public | MethodCloned */,
16, 3, 159, 2, 0x0a /* Public */,
16, 2, 166, 2, 0x2a /* Public | MethodCloned */,
18, 2, 171, 2, 0x0a /* Public */,
18, 1, 176, 2, 0x2a /* Public | MethodCloned */,
20, 0, 179, 2, 0x0a /* Public */,
21, 1, 180, 2, 0x0a /* Public */,
23, 1, 183, 2, 0x0a /* Public */,
25, 1, 186, 2, 0x0a /* Public */,
27, 1, 189, 2, 0x0a /* Public */,
30, 1, 192, 2, 0x0a /* Public */,
32, 1, 195, 2, 0x0a /* Public */,
// signals: parameters
QMetaType::Void, QMetaType::QString, 3,
QMetaType::Void,
// slots: parameters
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void, 0x80000000 | 11, QMetaType::QChar, QMetaType::UInt, 12, 13, 14,
QMetaType::Void, 0x80000000 | 11, QMetaType::QChar, 12, 13,
QMetaType::Void, QMetaType::QChar, QMetaType::UInt, 13, 14,
QMetaType::Void, QMetaType::QChar, 13,
QMetaType::Void, 0x80000000 | 11, QMetaType::QString, QMetaType::QSize, 12, 17, 14,
QMetaType::Void, 0x80000000 | 11, QMetaType::QString, 12, 17,
QMetaType::Void, 0x80000000 | 11, QMetaType::Bool, 12, 19,
QMetaType::Void, 0x80000000 | 11, 12,
QMetaType::Void,
QMetaType::Void, QMetaType::Int, 22,
QMetaType::Void, QMetaType::Int, 24,
QMetaType::Void, QMetaType::QString, 26,
QMetaType::Void, 0x80000000 | 28, 29,
QMetaType::Void, QMetaType::Bool, 31,
QMetaType::Void, 0x80000000 | 33, 34,
// properties: name, type, flags
26, QMetaType::QString, 0x00095103,
29, 0x80000000 | 28, 0x0009510b,
// enums: name, flags, count, data
35, 0x0, 13, 208,
// enum data: key, value
36, uint(QUIWidget::Style_Silvery),
37, uint(QUIWidget::Style_Blue),
38, uint(QUIWidget::Style_LightBlue),
39, uint(QUIWidget::Style_DarkBlue),
40, uint(QUIWidget::Style_Gray),
41, uint(QUIWidget::Style_LightGray),
42, uint(QUIWidget::Style_DarkGray),
43, uint(QUIWidget::Style_Black),
44, uint(QUIWidget::Style_LightBlack),
45, uint(QUIWidget::Style_DarkBlack),
46, uint(QUIWidget::Style_PSBlack),
47, uint(QUIWidget::Style_FlatBlack),
48, uint(QUIWidget::Style_FlatWhite),
0 // eod
};
// content:
// 元对象的版本号,这里设置为 7用于标识元对象相关代码的版本情况可能在后续版本兼容性判断等方面起作用
7, // revision
// 类名索引,设置为 0表示使用前面定义的 qt_meta_stringdata_QUIWidget 结构体中的第一个字符串(即 "QUIWidget")作为类名
0, // classname
// 类信息相关内容,这里都设置为 0表示没有额外的类信息如果有自定义的类属性等信息可以在这里设置相关索引等
0, 0, // classinfo
// 表示类中方法的数量(包括信号和槽函数等可被元对象系统调用的方法),这里设置为 23表示后续会定义 23 个方法相关的元数据信息
23, 14, // methods
// 表示类的属性数量,这里设置为 2即有两个自定义的属性相关元数据对应类中定义的可读写属性等
2, 198, // properties
// 表示枚举类型或集合相关的数量,设置为 1说明有一个枚举相关的定义会在这里设置对应信息对应类中定义的样式枚举等
1, 204, // enums/sets
// 表示构造函数相关的信息,设置为 0说明没有特殊的构造函数相关元数据如果有自定义构造函数的特殊处理会在这里设置
0, 0, // constructors
// 标志位相关信息,这里设置为 0可能用于设置类的一些特殊标志比如是否可创建实例等标志目前无特殊设置
0, // flags
// 信号数量相关信息,设置为 2说明类中定义了两个信号后续会有对应信号相关的元数据设置
2, // signalCount
// signals: name, argc, parameters, tag, flags
// 第一个信号的相关信息,索引为 1对应前面 qt_meta_stringdata_QUIWidget 中定义的字符串索引),表示信号名为 "changeStyle",参数数量为 1后续参数信息的索引为 129标签为空字符串设置为公共信号0x06 表示公共标志)
1, 1, 129, 2, 0x06 /* Public */,
// 第二个信号的相关信息,类似第一个信号的描述,信号名为 "closing",参数数量为 0参数信息索引为 132标签为空字符串同样是公共信号
4, 0, 132, 2, 0x06 /* Public */,
// slots: name, argc, parameters, tag, flags
// 第一个槽函数initControl的相关信息索引为 5对应字符串索引参数数量为 0参数信息索引为 133标签为空字符串设置为私有槽函数0x08 表示私有标志)
5, 0, 133, 2, 0x08 /* Private */,
// 依次定义其他槽函数的相关元数据信息,包括函数名对应的字符串索引、参数数量、参数信息索引、标签以及函数的访问标志(如私有、公共等)
6, 0, 134, 2, 0x08 /* Private */,
1, 0, 135, 2, 0x08 /* Private */,
//... (此处省略中间众多类似的槽函数元数据信息,原理相同,都是描述各个槽函数在元对象系统中的相关属性)
32, 1, 195, 2, 0x0a /* Public */,
// signals: parameters
// 第一个信号changeStyle的参数类型信息这里表示无返回值QMetaType::Void且有一个参数类型为 QString对应信号的参数情况
QMetaType::Void, QMetaType::QString, 3,
// 第二个信号closing的参数类型信息仅表示无返回值QMetaType::Void因为它没有参数
QMetaType::Void,
// slots: parameters
// 依次定义各个槽函数的参数类型信息,按照槽函数的顺序,每个槽函数对应其参数的元类型描述,例如参数是基本类型、自定义类型等在元对象系统中的标识
QMetaType::Void,
QMetaType::Void,
//... (此处省略中间众多类似的槽函数参数类型信息,都是对应各个槽函数实际参数的类型说明)
QMetaType::Void, 0x80000000 | 33, 34,
// properties: name, type, flags
// 第一个属性的相关信息,属性名为 "title"(对应字符串索引 26类型为 QString在元对象系统中的类型标识后面的标志位0x00095103用于设置属性的一些特性如可读写等属性相关的标志
26, QMetaType::QString, 0x00095103,
// 第二个属性的相关信息,属性名为 "alignment"(对应字符串索引 29类型为 Qt::Alignment在元对象系统中的类型标识通过特殊处理表示这个枚举类型相关的属性标志位用于设置其相关特性
29, 0x80000000 | 28, 0x0009510b,
// enums: name, flags, count, data
// 定义类中的枚举相关信息,枚举名为 "Style"(对应字符串索引 35标志位为 0x0无特殊标志枚举项的数量为 13后续枚举数据的索引为 208
35, 0x0, 13, 208,
// enum data: key, value
// 依次定义枚举项的对应关系,每个枚举项(如 Style_Silvery对应一个具体的整数值在元对象系统中的表示用于在代码中区分不同的枚举值
36, uint(QUIWidget::Style_Silvery),
37, uint(QUIWidget::Style_Blue),
//... (此处省略中间众多类似的枚举项对应关系定义,都是为了完整描述枚举类型的取值情况)
48, uint(QUIWidget::Style_FlatWhite),
// 表示元数据数组的结束标识,这里设置为 0
0 // eod
};
// 实现 QUIWidget 类的静态元调用函数,用于处理元对象系统中对类的方法(槽函数、信号等)的调用请求,根据不同的调用类型和方法索引执行相应操作
void QUIWidget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
// 如果调用类型是调用元方法(即调用类中的槽函数、信号等方法)
if (_c == QMetaObject::InvokeMetaMethod) {
// 将传入的 QObject 指针转换为 QUIWidget 类指针,因为实际要调用的是 QUIWidget 类中的方法
QUIWidget *_t = static_cast<QUIWidget *>(_o);
// 避免编译器提示未使用变量的警告,这里虽然暂时没用到 _t但后续代码块中会使用所以先声明弃用这个警告
Q_UNUSED(_t)
// 根据方法索引执行对应的方法调用,这里根据不同的索引值调用相应的槽函数或信号对应的成员函数
switch (_id) {
case 0: _t->changeStyle((*reinterpret_cast< const QString(*)>(_a[1]))); break;
case 1: _t->closing(); break;
@ -214,467 +173,4 @@ void QUIWidget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, v
case 12: _t->setPixmap((*reinterpret_cast< QUIWidget::Widget(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])),(*reinterpret_cast< const QSize(*)>(_a[3]))); break;
case 13: _t->setPixmap((*reinterpret_cast< QUIWidget::Widget(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break;
case 14: _t->setVisible((*reinterpret_cast< QUIWidget::Widget(*)>(_a[1])),(*reinterpret_cast< bool(*)>(_a[2]))); break;
case 15: _t->setVisible((*reinterpret_cast< QUIWidget::Widget(*)>(_a[1]))); break;
case 16: _t->setOnlyCloseBtn(); break;
case 17: _t->setTitleHeight((*reinterpret_cast< int(*)>(_a[1]))); break;
case 18: _t->setBtnWidth((*reinterpret_cast< int(*)>(_a[1]))); break;
case 19: _t->setTitle((*reinterpret_cast< const QString(*)>(_a[1]))); break;
case 20: _t->setAlignment((*reinterpret_cast< Qt::Alignment(*)>(_a[1]))); break;
case 21: _t->setMinHide((*reinterpret_cast< bool(*)>(_a[1]))); break;
case 22: _t->setMainWidget((*reinterpret_cast< QWidget*(*)>(_a[1]))); break;
default: ;
}
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
switch (_id) {
default: *reinterpret_cast<int*>(_a[0]) = -1; break;
case 22:
switch (*reinterpret_cast<int*>(_a[1])) {
default: *reinterpret_cast<int*>(_a[0]) = -1; break;
case 0:
*reinterpret_cast<int*>(_a[0]) = qRegisterMetaType< QWidget* >(); break;
}
break;
}
} else if (_c == QMetaObject::IndexOfMethod) {
int *result = reinterpret_cast<int *>(_a[0]);
void **func = reinterpret_cast<void **>(_a[1]);
{
typedef void (QUIWidget::*_t)(const QString & );
if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&QUIWidget::changeStyle)) {
*result = 0;
return;
}
}
{
typedef void (QUIWidget::*_t)();
if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&QUIWidget::closing)) {
*result = 1;
return;
}
}
}
#ifndef QT_NO_PROPERTIES
else if (_c == QMetaObject::ReadProperty) {
QUIWidget *_t = static_cast<QUIWidget *>(_o);
Q_UNUSED(_t)
void *_v = _a[0];
switch (_id) {
case 0: *reinterpret_cast< QString*>(_v) = _t->getTitle(); break;
case 1: *reinterpret_cast< Qt::Alignment*>(_v) = _t->getAlignment(); break;
default: break;
}
} else if (_c == QMetaObject::WriteProperty) {
QUIWidget *_t = static_cast<QUIWidget *>(_o);
Q_UNUSED(_t)
void *_v = _a[0];
switch (_id) {
case 0: _t->setTitle(*reinterpret_cast< QString*>(_v)); break;
case 1: _t->setAlignment(*reinterpret_cast< Qt::Alignment*>(_v)); break;
default: break;
}
} else if (_c == QMetaObject::ResetProperty) {
}
#endif // QT_NO_PROPERTIES
}
const QMetaObject QUIWidget::staticMetaObject = {
{ &QDialog::staticMetaObject, qt_meta_stringdata_QUIWidget.data,
qt_meta_data_QUIWidget, qt_static_metacall, Q_NULLPTR, Q_NULLPTR}
};
const QMetaObject *QUIWidget::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}
void *QUIWidget::qt_metacast(const char *_clname)
{
if (!_clname) return Q_NULLPTR;
if (!strcmp(_clname, qt_meta_stringdata_QUIWidget.stringdata0))
return static_cast<void*>(const_cast< QUIWidget*>(this));
return QDialog::qt_metacast(_clname);
}
int QUIWidget::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QDialog::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 23)
qt_static_metacall(this, _c, _id, _a);
_id -= 23;
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
if (_id < 23)
qt_static_metacall(this, _c, _id, _a);
_id -= 23;
}
#ifndef QT_NO_PROPERTIES
else if (_c == QMetaObject::ReadProperty || _c == QMetaObject::WriteProperty
|| _c == QMetaObject::ResetProperty || _c == QMetaObject::RegisterPropertyMetaType) {
qt_static_metacall(this, _c, _id, _a);
_id -= 2;
} else if (_c == QMetaObject::QueryPropertyDesignable) {
_id -= 2;
} else if (_c == QMetaObject::QueryPropertyScriptable) {
_id -= 2;
} else if (_c == QMetaObject::QueryPropertyStored) {
_id -= 2;
} else if (_c == QMetaObject::QueryPropertyEditable) {
_id -= 2;
} else if (_c == QMetaObject::QueryPropertyUser) {
_id -= 2;
}
#endif // QT_NO_PROPERTIES
return _id;
}
// SIGNAL 0
void QUIWidget::changeStyle(const QString & _t1)
{
void *_a[] = { Q_NULLPTR, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, 0, _a);
}
// SIGNAL 1
void QUIWidget::closing()
{
QMetaObject::activate(this, &staticMetaObject, 1, Q_NULLPTR);
}
struct qt_meta_stringdata_QUIMessageBox_t {
QByteArrayData data[14];
char stringdata0[137];
};
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
qptrdiff(offsetof(qt_meta_stringdata_QUIMessageBox_t, stringdata0) + ofs \
- idx * sizeof(QByteArrayData)) \
)
static const qt_meta_stringdata_QUIMessageBox_t qt_meta_stringdata_QUIMessageBox = {
{
QT_MOC_LITERAL(0, 0, 13), // "QUIMessageBox"
QT_MOC_LITERAL(1, 14, 11), // "initControl"
QT_MOC_LITERAL(2, 26, 0), // ""
QT_MOC_LITERAL(3, 27, 8), // "initForm"
QT_MOC_LITERAL(4, 36, 8), // "checkSec"
QT_MOC_LITERAL(5, 45, 16), // "on_btnOk_clicked"
QT_MOC_LITERAL(6, 62, 24), // "on_btnMenu_Close_clicked"
QT_MOC_LITERAL(7, 87, 11), // "setIconMain"
QT_MOC_LITERAL(8, 99, 3), // "str"
QT_MOC_LITERAL(9, 103, 4), // "size"
QT_MOC_LITERAL(10, 108, 10), // "setMessage"
QT_MOC_LITERAL(11, 119, 3), // "msg"
QT_MOC_LITERAL(12, 123, 4), // "type"
QT_MOC_LITERAL(13, 128, 8) // "closeSec"
},
"QUIMessageBox\0initControl\0\0initForm\0"
"checkSec\0on_btnOk_clicked\0"
"on_btnMenu_Close_clicked\0setIconMain\0"
"str\0size\0setMessage\0msg\0type\0closeSec"
};
#undef QT_MOC_LITERAL
static const uint qt_meta_data_QUIMessageBox[] = {
// content:
7, // revision
0, // classname
0, 0, // classinfo
9, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount
// slots: name, argc, parameters, tag, flags
1, 0, 59, 2, 0x08 /* Private */,
3, 0, 60, 2, 0x08 /* Private */,
4, 0, 61, 2, 0x08 /* Private */,
5, 0, 62, 2, 0x08 /* Private */,
6, 0, 63, 2, 0x08 /* Private */,
7, 2, 64, 2, 0x0a /* Public */,
7, 1, 69, 2, 0x2a /* Public | MethodCloned */,
10, 3, 72, 2, 0x0a /* Public */,
10, 2, 79, 2, 0x2a /* Public | MethodCloned */,
// slots: parameters
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void, QMetaType::QChar, QMetaType::UInt, 8, 9,
QMetaType::Void, QMetaType::QChar, 8,
QMetaType::Void, QMetaType::QString, QMetaType::Int, QMetaType::Int, 11, 12, 13,
QMetaType::Void, QMetaType::QString, QMetaType::Int, 11, 12,
0 // eod
};
void QUIMessageBox::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
QUIMessageBox *_t = static_cast<QUIMessageBox *>(_o);
Q_UNUSED(_t)
switch (_id) {
case 0: _t->initControl(); break;
case 1: _t->initForm(); break;
case 2: _t->checkSec(); break;
case 3: _t->on_btnOk_clicked(); break;
case 4: _t->on_btnMenu_Close_clicked(); break;
case 5: _t->setIconMain((*reinterpret_cast< QChar(*)>(_a[1])),(*reinterpret_cast< quint32(*)>(_a[2]))); break;
case 6: _t->setIconMain((*reinterpret_cast< QChar(*)>(_a[1]))); break;
case 7: _t->setMessage((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3]))); break;
case 8: _t->setMessage((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2]))); break;
default: ;
}
}
}
const QMetaObject QUIMessageBox::staticMetaObject = {
{ &QDialog::staticMetaObject, qt_meta_stringdata_QUIMessageBox.data,
qt_meta_data_QUIMessageBox, qt_static_metacall, Q_NULLPTR, Q_NULLPTR}
};
const QMetaObject *QUIMessageBox::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}
void *QUIMessageBox::qt_metacast(const char *_clname)
{
if (!_clname) return Q_NULLPTR;
if (!strcmp(_clname, qt_meta_stringdata_QUIMessageBox.stringdata0))
return static_cast<void*>(const_cast< QUIMessageBox*>(this));
return QDialog::qt_metacast(_clname);
}
int QUIMessageBox::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QDialog::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 9)
qt_static_metacall(this, _c, _id, _a);
_id -= 9;
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
if (_id < 9)
*reinterpret_cast<int*>(_a[0]) = -1;
_id -= 9;
}
return _id;
}
struct qt_meta_stringdata_QUIInputBox_t {
QByteArrayData data[16];
char stringdata0[156];
};
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
qptrdiff(offsetof(qt_meta_stringdata_QUIInputBox_t, stringdata0) + ofs \
- idx * sizeof(QByteArrayData)) \
)
static const qt_meta_stringdata_QUIInputBox_t qt_meta_stringdata_QUIInputBox = {
{
QT_MOC_LITERAL(0, 0, 11), // "QUIInputBox"
QT_MOC_LITERAL(1, 12, 11), // "initControl"
QT_MOC_LITERAL(2, 24, 0), // ""
QT_MOC_LITERAL(3, 25, 8), // "initForm"
QT_MOC_LITERAL(4, 34, 8), // "checkSec"
QT_MOC_LITERAL(5, 43, 16), // "on_btnOk_clicked"
QT_MOC_LITERAL(6, 60, 24), // "on_btnMenu_Close_clicked"
QT_MOC_LITERAL(7, 85, 11), // "setIconMain"
QT_MOC_LITERAL(8, 97, 3), // "str"
QT_MOC_LITERAL(9, 101, 4), // "size"
QT_MOC_LITERAL(10, 106, 12), // "setParameter"
QT_MOC_LITERAL(11, 119, 5), // "title"
QT_MOC_LITERAL(12, 125, 4), // "type"
QT_MOC_LITERAL(13, 130, 8), // "closeSec"
QT_MOC_LITERAL(14, 139, 12), // "defaultValue"
QT_MOC_LITERAL(15, 152, 3) // "pwd"
},
"QUIInputBox\0initControl\0\0initForm\0"
"checkSec\0on_btnOk_clicked\0"
"on_btnMenu_Close_clicked\0setIconMain\0"
"str\0size\0setParameter\0title\0type\0"
"closeSec\0defaultValue\0pwd"
};
#undef QT_MOC_LITERAL
static const uint qt_meta_data_QUIInputBox[] = {
// content:
7, // revision
0, // classname
0, 0, // classinfo
12, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount
// slots: name, argc, parameters, tag, flags
1, 0, 74, 2, 0x08 /* Private */,
3, 0, 75, 2, 0x08 /* Private */,
4, 0, 76, 2, 0x08 /* Private */,
5, 0, 77, 2, 0x08 /* Private */,
6, 0, 78, 2, 0x08 /* Private */,
7, 2, 79, 2, 0x0a /* Public */,
7, 1, 84, 2, 0x2a /* Public | MethodCloned */,
10, 5, 87, 2, 0x0a /* Public */,
10, 4, 98, 2, 0x2a /* Public | MethodCloned */,
10, 3, 107, 2, 0x2a /* Public | MethodCloned */,
10, 2, 114, 2, 0x2a /* Public | MethodCloned */,
10, 1, 119, 2, 0x2a /* Public | MethodCloned */,
// slots: parameters
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void, QMetaType::QChar, QMetaType::UInt, 8, 9,
QMetaType::Void, QMetaType::QChar, 8,
QMetaType::Void, QMetaType::QString, QMetaType::Int, QMetaType::Int, QMetaType::QString, QMetaType::Bool, 11, 12, 13, 14, 15,
QMetaType::Void, QMetaType::QString, QMetaType::Int, QMetaType::Int, QMetaType::QString, 11, 12, 13, 14,
QMetaType::Void, QMetaType::QString, QMetaType::Int, QMetaType::Int, 11, 12, 13,
QMetaType::Void, QMetaType::QString, QMetaType::Int, 11, 12,
QMetaType::Void, QMetaType::QString, 11,
0 // eod
};
void QUIInputBox::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
QUIInputBox *_t = static_cast<QUIInputBox *>(_o);
Q_UNUSED(_t)
switch (_id) {
case 0: _t->initControl(); break;
case 1: _t->initForm(); break;
case 2: _t->checkSec(); break;
case 3: _t->on_btnOk_clicked(); break;
case 4: _t->on_btnMenu_Close_clicked(); break;
case 5: _t->setIconMain((*reinterpret_cast< QChar(*)>(_a[1])),(*reinterpret_cast< quint32(*)>(_a[2]))); break;
case 6: _t->setIconMain((*reinterpret_cast< QChar(*)>(_a[1]))); break;
case 7: _t->setParameter((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3])),(*reinterpret_cast< QString(*)>(_a[4])),(*reinterpret_cast< bool(*)>(_a[5]))); break;
case 8: _t->setParameter((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3])),(*reinterpret_cast< QString(*)>(_a[4]))); break;
case 9: _t->setParameter((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3]))); break;
case 10: _t->setParameter((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2]))); break;
case 11: _t->setParameter((*reinterpret_cast< const QString(*)>(_a[1]))); break;
default: ;
}
}
}
const QMetaObject QUIInputBox::staticMetaObject = {
{ &QDialog::staticMetaObject, qt_meta_stringdata_QUIInputBox.data,
qt_meta_data_QUIInputBox, qt_static_metacall, Q_NULLPTR, Q_NULLPTR}
};
const QMetaObject *QUIInputBox::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}
void *QUIInputBox::qt_metacast(const char *_clname)
{
if (!_clname) return Q_NULLPTR;
if (!strcmp(_clname, qt_meta_stringdata_QUIInputBox.stringdata0))
return static_cast<void*>(const_cast< QUIInputBox*>(this));
return QDialog::qt_metacast(_clname);
}
int QUIInputBox::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QDialog::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 12)
qt_static_metacall(this, _c, _id, _a);
_id -= 12;
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
if (_id < 12)
*reinterpret_cast<int*>(_a[0]) = -1;
_id -= 12;
}
return _id;
}
struct qt_meta_stringdata_IconHelper_t {
QByteArrayData data[1];
char stringdata0[11];
};
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
qptrdiff(offsetof(qt_meta_stringdata_IconHelper_t, stringdata0) + ofs \
- idx * sizeof(QByteArrayData)) \
)
static const qt_meta_stringdata_IconHelper_t qt_meta_stringdata_IconHelper = {
{
QT_MOC_LITERAL(0, 0, 10) // "IconHelper"
},
"IconHelper"
};
#undef QT_MOC_LITERAL
static const uint qt_meta_data_IconHelper[] = {
// content:
7, // revision
0, // classname
0, 0, // classinfo
0, 0, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount
0 // eod
};
void IconHelper::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
Q_UNUSED(_o);
Q_UNUSED(_id);
Q_UNUSED(_c);
Q_UNUSED(_a);
}
const QMetaObject IconHelper::staticMetaObject = {
{ &QObject::staticMetaObject, qt_meta_stringdata_IconHelper.data,
qt_meta_data_IconHelper, qt_static_metacall, Q_NULLPTR, Q_NULLPTR}
};
const QMetaObject *IconHelper::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}
void *IconHelper::qt_metacast(const char *_clname)
{
if (!_clname) return Q_NULLPTR;
if (!strcmp(_clname, qt_meta_stringdata_IconHelper.stringdata0))
return static_cast<void*>(const_cast< IconHelper*>(this));
return QObject::qt_metacast(_clname);
}
int IconHelper::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QObject::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
return _id;
}
QT_WARNING_POP
QT_END_MOC_NAMESPACE
case 15: _t->setVisible((*reinterpret

@ -1,37 +1,51 @@
#include "supermarket.h"
// Supermarket类的构造函数用于初始化超市管理系统相关的界面、数据和定时器等
Supermarket::Supermarket(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Supermarket)
{
//界面初始化
// 界面初始化调用UI界面的设置函数来设置当前窗口的界面
ui->setupUi(this);
// 将窗口设置在屏幕中心位置
QUIWidget::setFormInCenter(this);
// 初始化表单并返回对应的模型指针,用于后续对表单数据的操作等
pmodel = this->initForm();
//数据初始化
// 初始化商品数量为0
number = 0;
// 商品链表头指针初始化为NULL表示初始时无商品
head = NULL;
// 记录登录账户的字符串初始化为空
loginin_account = "";
//时间初始化
// 创建一个定时器对象,用于定时触发某些操作
QTimer *timer = new QTimer(this);
// 连接定时器的超时信号到timerUpdate槽函数用于更新时间显示
connect(timer,SIGNAL(timeout()),this,SLOT(timerUpdate()));
// 连接定时器的超时信号到timerAdd槽函数用于执行一些随着时间增加而要做的操作比如统计相关
connect(timer,SIGNAL(timeout()),this,SLOT(timerAdd()));
// 启动定时器设置时间间隔为1000毫秒即1秒
timer->start(1000);
}
// Supermarket类的析构函数用于释放相关资源比如删除UI界面指针以及清理商品链表内存
Supermarket::~Supermarket()
{
// 删除UI界面相关的对象
delete ui;
// 定义一个临时指针p用于遍历商品链表释放内存
Good *p;
// 遍历商品链表,从链表头开始,逐个释放节点内存(除了最后一个节点)
for(p=head; p->next!=NULL; p=p->next)
{
delete p;
}
// 释放链表最后一个节点的内存
delete p;
}
// 初始化未登录账户时界面的显示状态,隐藏一些登录后才显示的控件,显示未登录相关的控件
void Supermarket::initUnAccount()
{
ui->label_3->setVisible(false);
@ -62,62 +76,93 @@ void Supermarket::initUnAccount()
ui->pushButton->setVisible(true);
}
// 初始化表单相关设置包括调用initUnAccount来设置界面显示设置样式创建并设置表单模型
QStandardItemModel* Supermarket::initForm()
{
// 先初始化未登录账户时的界面显示状态
initUnAccount();
// 设置界面的样式为银色风格假设QUIWidget有这样的设置功能
QUIWidget::setStyle(QUIWidget::Style_Silvery);
// 创建一个新的标准项模型对象,用于作为表单的数据模型
QStandardItemModel *model = new QStandardItemModel();
// 将创建的模型设置给表格视图,用于显示数据
ui->tableView->setModel(model);
// 返回创建好的模型指针,方便外部操作模型数据
return model;
}
//当前时间
// 获取当前时间并更新到界面上指定的标签显示
void Supermarket::timerUpdate(void)
{
// 获取当前日期时间对象
QDateTime time = QDateTime::currentDateTime();
// 将日期时间对象格式化为指定格式的字符串(年-月-日 时:分:秒 星期)
QString str = time.toString("yyyy-MM-dd hh:mm:ss dddd");
// 将格式化后的时间字符串设置到界面上对应的标签显示
ui->label_10->setText(str);
}
//计时器
// 定时器触发的操作,用于更新经过时间的显示以及进行统计操作(可能是统计商品相关数据等)
void Supermarket::timerAdd()
{
// 计算经过的小时数将总毫秒数除以每小时对应的毫秒数3600000并转换为字符串
QString hour = QString::number(t.elapsed()/3600000);
// 计算经过的分钟数先取总毫秒数除以每小时毫秒数的余数再除以每分钟对应的毫秒数60000并转换为字符串
QString min = QString::number((t.elapsed()%3600000)/60000);
// 计算经过的秒数取总毫秒数除以每分钟毫秒数的余数再除以每秒对应的毫秒数1000并转换为字符串
QString sec = QString::number((t.elapsed()%60000)/1000);
// 拼接成类似 "X小时X分钟X秒" 的时间字符串
QString str = hour+"小时"+min+"分钟"+sec+"";
// 将时间字符串设置到界面上对应的标签显示
ui->label_9->setText(str);
// 调用统计函数,可能是统计商品相关数据等
Statistics();
}
//账户登录
// 处理账户登录按钮点击事件的函数,用于验证输入的账号和密码是否正确,并进行相应的登录操作
void Supermarket::on_pushButton_clicked()
{
// 定义存储账户信息文件的文件名这里是相对路径下的CSV文件
string file_name = "user//account.csv",line_str,str;
// 创建一个文件输入流对象,用于读取账户信息文件,以输入模式打开文件
ifstream read_account(file_name,ios::in);
// 获取界面上输入的账号文本,并转换为标准字符串类型
string on_loginin_account = ui->lineEdit_3->text().toStdString();
// 获取界面上输入的密码文本,并转换为标准字符串类型
string on_loginin_account_password = ui->lineEdit_4->text().toStdString();
string file_login_account, file_login_account_password;
// 用于临时存储从文件中读取的账号
string file_login_account;
// 用于临时存储从文件中读取的密码
string file_login_account_password;
// 逐行读取账户信息文件内容
while(getline(read_account,line_str))
{
// 创建一个字符串流对象,用于解析每行的字符串内容
stringstream ss(line_str);
// 从字符串流中读取以逗号分隔的第一个字符串(账号)
getline(ss,str,',');
file_login_account = str;
// 从字符串流中读取以逗号分隔的第二个字符串(密码)
getline(ss,str,',');
file_login_account_password = str;
// 比较输入的账号和密码与从文件中读取的账号和密码是否一致
if(on_loginin_account == file_login_account && on_loginin_account_password == file_login_account_password)
{
// 如果一致,记录登录账号
loginin_account = on_loginin_account;
// 进行登录后的初始化操作
initAccount();
}
}
// 如果登录账号仍然为空,说明账号或密码错误,弹出错误提示框
if(loginin_account == "")
QUIWidget::showMessageBoxError("账号或密码错误。请重新输入或者联系超市BOSS.",5);
}
//初始化账户
// 进行登录后的界面和相关数据初始化操作,比如显示登录后相关控件,隐藏未登录相关控件等
void Supermarket::initAccount()
{
// 重启某个定时器这里t应该是前面定义的用于计时的对象可能用于记录登录后的操作时间等
t.restart();
ui->label_3->setVisible(true);
ui->label_4->setVisible(true);
@ -145,31 +190,38 @@ void Supermarket::initAccount()
ui->lineEdit_4->setVisible(false);
ui->pushButton->setVisible(false);
// 将登录账号显示到界面上对应的标签
ui->label_7->setText(QString::fromStdString(loginin_account));
// 根据登录账号判断是否为超级管理员root账号为超级管理员并设置对应的管理员级别显示文本
if(loginin_account == "root")
{
ui->label_8->setText("超级管理员");
//ui->tab_6->setVisible(true);
}
else ui->label_8->setText("普通管理员");
else
ui->label_8->setText("普通管理员");
}
//账户权限检查(三级:超管,管理,游客;a =0 为超管)
// 检查账户权限的函数,根据传入参数判断是否具有相应操作权限,返回布尔值表示是否有权限
bool Supermarket::CheckAccount(bool a)
{
// 如果传入参数a为0表示检查是否为超级管理员权限
if(a == 0)
{
// 判断登录账号是否为"root"是则返回有权限1表示有权限
if(loginin_account == "root")
return 1;
else
{
// 如果不是超级管理员弹出提示信息框告知此操作只有大BOSS可以执行并返回无权限0表示无权限
QUIWidget::showMessageBoxInfo("此操作只有大BOSS可以执行.",5);
return 0;
}
}
// 如果传入参数a为1表示检查是否为已登录的普通管理员权限
else if(a == 1)
{
// 如果登录账号为空,说明未登录,弹出提示信息框,告知此操作只有登录后才可以执行,并返回无权限
if(loginin_account == "")
{
QUIWidget::showMessageBoxInfo("此操作只有登陆后才可以执行.",5);
@ -177,756 +229,118 @@ bool Supermarket::CheckAccount(bool a)
}
else
{
// 如果已登录,返回有权限
return 1;
}
}
else
{
// 如果传入的参数不符合预期既不是0也不是1弹出错误提示框告知程序员写错代码了并返回无权限
QUIWidget::showMessageBoxError("程序员写错代码了,快拿他祭天.(错误代码:0X00001)",5);
return 0;
}
}
//批量写入
// 处理批量写入操作的菜单触发事件先检查是否具有超级管理员权限有权限则执行批量写入操作BatchInput函数
void Supermarket::on_action_O_triggered()
{
if(CheckAccount(0))
BatchInput();
}
//导出CSV
// 处理导出CSV文件操作的菜单触发事件先检查是否具有超级管理员权限有权限则执行导出CSV文件相关操作包括选择文件夹、导出数据等
void Supermarket::on_actionCSV_C_triggered()
{
//string dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), "/home", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks).toStdString();
if(CheckAccount(0))
{
// 获取要导出的文件夹名称,并转换为标准字符串类型
string dir = QUIWidget::getFolderName().toStdString();
// 执行批量导出数据到指定文件夹下的CSV文件操作
BatchOutput(dir);
// 将文件夹名称转换为QString类型
QString sdir = QString::fromStdString(dir);
// 打开导出文件所在的文件夹(在系统默认的文件管理器中打开)
QDesktopServices::openUrl(QUrl::fromLocalFile(sdir));
}
}
// 处理某个特定操作(可能是加密相关操作)的菜单触发事件,先检查是否具有超级管理员权限,有权限则执行相关操作(涉及文件加密、复制、删除等)
void Supermarket::on_actiondda_triggered()
{
if(CheckAccount(0))
{
// 先执行批量导出数据到"user"文件夹下这里具体功能看BatchOutput函数实现
BatchOutput("user");
// 获取要操作的文件夹名称,并转换为标准字符串类型
string dir = QUIWidget::getFolderName().toStdString();
// 创建一个进程对象用于执行外部命令这里可能是执行加密相关的命令行程序Des3.exe
QProcess process(this);
// 启动进程执行加密命令参数含义可能是加密相关的配置具体看Des3.exe程序要求
process.start("Des3.exe -l user\\Data.csv qwertyuiop user\\Locked_Data.qzq");
// 终止进程(这里可能需要根据实际情况看是否合理,也许是先启动后再终止的一种操作顺序要求)
process.terminate();
// 等待进程执行完毕
process.waitForFinished();
// 关闭进程相关资源
process.close();
// 将文件夹名称转换为QString类型
QString sdir = QString::fromStdString(dir);
// 拼接出加密后文件的完整路径
QString ssdir = sdir+"\\Locked_Data.qzq";
// 删除指定路径的文件(可能是之前存在的同名文件等)
QFile::remove(ssdir);
// 复制文件,将加密后的文件从源路径复制到目标路径
QUIWidget::copyFile("user\\Locked_Data.qzq",ssdir);
// 打开加密后文件所在的文件夹(在系统默认的文件管理器中打开)
QDesktopServices::openUrl(QUrl::fromLocalFile(sdir));
// 删除原始的数据文件(可能是清理操作)
QFile::remove("user\\Data.csv");
// 删除之前可能存在的加密文件(也许是旧版本等,具体看业务逻辑)
QFile::remove("user\\Locked_Data.qzq");
}
else
{
// 如果没有权限弹出错误提示框告知只有BOSS可以执行这个操作
QUIWidget::showMessageBoxError("只有BOSS可以执行这个操作.");
}
}
//清空数据库
// 处理清空数据库操作的菜单触发事件,先检查是否具有超级管理员权限,有权限则执行清空数据库相关操作(包括确认提示、删除数据等)
void Supermarket::on_actiond_2_triggered()
{
if(CheckAccount(0))
{
// 获取商品链表头指针
Good *p = head;
// 如果链表为空,说明数据库已经是空的,弹出提示信息框告知用户
if(p == NULL)
{
QUIWidget::showMessageBoxInfo("数据库已经是空的啦!",5);
}
else
{
// 弹出确认对话框询问用户是否确认要清空数据库返回用户选择的结果16384表示确认等具体看QUIWidget实现
int i = QUIWidget::showMessageBoxQuestion("您确认要清空嘛?");
//ui->statusbar->showMessage(QString::number(i),20000);
// 如果用户确认要清空(返回值符合确认的标识)
if(i == 16384)
{
// 在状态栏显示正在清空的提示信息
ui->statusbar->showMessage("正在清空...",2000);
// 将指针指向下一个节点(跳过链表头节点,从第二个节点开始删除)
p = p->next;
// 遍历链表,逐个删除节点(释放内存),直到链表末尾
for(;p!=NULL;p=p->next)
{
delete p;
}
// 清空后将链表头指针置为NULL表示数据库为空
head = NULL;
// 商品数量重置为0
number = 0;
// 清除状态栏之前的提示信息
ui->statusbar->clearMessage();
ui->statusbar->showMessage("清理完毕.",3000);
}
else
{
QUIWidget::showMessageBoxInfo("我什么也没做.",5);
}
}
}
}
void Supermarket::on_actiond_triggered()
{
if(CheckAccount(0))
{
QString dir = QUIWidget::getFolderName();
QFile::remove(dir+"//操作记录.csv");
bool is_copy = QUIWidget::copyFile("user//Log.csv",dir+"//操作记录.csv");
if(is_copy == true)
{
QDesktopServices::openUrl(QUrl::fromLocalFile(dir));
}
else
{
QUIWidget::showMessageBoxError("导出错误,请检查系统.");
}
}
}
void Supermarket::on_action_H_triggered()
{
QProcess::execute("explorer help.txt");
}
void Supermarket::on_action_A_triggered()
{
QDesktopServices::openUrl(QUrl(QString("http://60.205.215.163/")));
//QUrl url(QString("http://60.205.215.163/"));
//QDesktopServices::openUrl(url);
// QDesktopServices::openUrl("http://60.205.215.163/");
QUIWidget::showMessageBoxInfo("此程序核心为链式表QT开发界面基于QSS实现换肤、右键等加密系统基于DES加密方式由独立进程实现。",20);
}
void Supermarket::on_action_B_triggered()
{
QDesktopServices::openUrl(QUrl(QString("https://wj.qq.com/s/1773296/9f9c/")));
//QUrl url(QString("https://wj.qq.com/s/1773296/9f9c/"));
//QDesktopServices::openUrl(url);
}
void Supermarket::on_pushButton_3_clicked()
{
if(CheckAccount(1))
ManInput();
}
void Supermarket::on_pushButton_2_clicked()
{
if(CheckAccount(1))
OutStorage();
}
void Supermarket::on_pushButton_6_clicked()
{
if(CheckAccount(1))
Search();
}
void Supermarket::on_pushButton_7_clicked()
{
if(CheckAccount(1))
SetDate();
}
//置空操作
void Supermarket::on_pushButton_8_clicked()
{
ui->lineEdit->setText("");
ui->lineEdit_2->setText("");
ui->doubleSpinBox->setValue(0.00);
ui->doubleSpinBox_2->setValue(0.00);
ui->doubleSpinBox_11->setValue(0.00);
ui->comboBox->setCurrentText("请选择单位");
ui->comboBox_2->setCurrentText("请选择分类");
}
void Supermarket::on_pushButton_9_clicked()
{
ui->lineEdit_8->setText("");
ui->lineEdit_7->setText("");
ui->doubleSpinBox_7->setValue(0.00);
ui->doubleSpinBox_8->setValue(0.00);
ui->doubleSpinBox_13->setValue(0.00);
ui->comboBox_10->setCurrentText("可选单位");
ui->comboBox_9->setCurrentText("可选分类");
}
void Supermarket::on_pushButton_10_clicked()
{
ui->lineEdit_10->setText("");
ui->lineEdit_9->setText("");
ui->doubleSpinBox_9->setValue(0.00);
ui->doubleSpinBox_10->setValue(0.00);
ui->doubleSpinBox_14->setValue(0.00);
ui->comboBox_12->setCurrentText("可改单位");
ui->comboBox_11->setCurrentText("可改分类");
}
void Supermarket::on_pushButton_4_clicked()
{
loginin_account = "";
initUnAccount();
}
Good* Supermarket::GetLastPointer()
{
Good* p;
if(head == NULL) return head;
else
{
for(p=head; p->next!=NULL; p=p->next);
return p;
}
}
bool Supermarket::CheckID(string pid)
{
Good*p=head;
if(p==NULL)
{
return true;
}
else
{
while(p!=NULL)
{
if(pid == p->id)
return false;
else{p=p->next;}
}
return true;
}
}
bool Supermarket::ManInput()
{
Good *p,*q;
p = (Good*)new(Good);
if(ui->lineEdit->text().toStdString() == "")
QUIWidget::showMessageBoxError("ID不能为空.",5);
else
p->id = ui->lineEdit->text().toStdString();
if(CheckID(ui->lineEdit->text().toStdString()))
{
if(ui->lineEdit_2->text().toStdString() == "")
QUIWidget::showMessageBoxError("商品名称不能为空.",5);
else
p->name = ui->lineEdit_2->text().toStdString();
if(ui->doubleSpinBox->value()==0)
QUIWidget::showMessageBoxError("进价不能为0.",5);
else
p->cost = ui->doubleSpinBox->value();
if(ui->doubleSpinBox_2->value()==0)
QUIWidget::showMessageBoxError("售价不能为0.",5);
else
p->price = ui->doubleSpinBox_2->value();
if(ui->doubleSpinBox_11->value()==0)
QUIWidget::showMessageBoxError("数量不能为0.",5);
else
p->number = ui->doubleSpinBox_11->value();
if(ui->comboBox->currentText().toStdString() == "请选择单位")
QUIWidget::showMessageBoxError("请选择计量单位.",5);
else
p->measure_unit = ui->comboBox->currentText().toStdString();
if(ui->comboBox_2->currentText().toStdString() == "请选择分类")
QUIWidget::showMessageBoxError("请选择分类以便更好的处理.",5);
else
p->category = ui->comboBox_2->currentText().toStdString();
if((ui->lineEdit->text().toStdString() != "")&&(ui->lineEdit_2->text().toStdString() != "")&&(ui->doubleSpinBox->value()!=0)&&(ui->doubleSpinBox_2->value()!=0)&&(ui->doubleSpinBox_11->value()!=0)&&(ui->comboBox->currentText().toStdString() != "请选择单位")&&(ui->comboBox_2->currentText().toStdString() != "请选择分类"))
{
p->purchase_time =QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz ddd").toStdString();
p->next = NULL;
p->sell_time = "暂无记录";
number++;
if(head == NULL)
head = p;
else
{
q = GetLastPointer();
q->next = p;
}
Log("入库",true,p);
}
}
else
{
bool ok_change = 1;
q = SearchChild(ui->lineEdit->text().toStdString());
if((ui->lineEdit_2->text().toStdString() != "") && (ui->lineEdit_2->text().toStdString() != q->name))
{QUIWidget::showMessageBoxError("与已存在的商品名称不一致,如需修改请移步“修改”页.",5);ok_change = 0;}
if(ui->doubleSpinBox->value()==0)
{QUIWidget::showMessageBoxError("进价不能为0.",5);ok_change=0;}
if(ui->doubleSpinBox_2->value()==0)
{ QUIWidget::showMessageBoxError("售价不能为0.",5);ok_change=0;}
if(ui->doubleSpinBox_11->value()==0)
{QUIWidget::showMessageBoxError("数量不能为0.",5); ok_change = 0;}
if(ui->comboBox->currentText().toStdString() != "请选择单位" && ui->comboBox->currentText().toStdString() != q->measure_unit)
{ QUIWidget::showMessageBoxError("与已存在的商品单位不一致,如需修改请移步“修改”页.",5); ok_change = 0;}
if(ui->comboBox_2->currentText().toStdString() != "请选择分类" && ui->comboBox_2->currentText().toStdString()!=q->category)
{ QUIWidget::showMessageBoxError("与已存在的商品分类不一致,如需修改请移步“修改”页.",5); ok_change = 0;}
if(ok_change == 1)
{
if((ui->doubleSpinBox->value() != q->cost)||(ui->doubleSpinBox_2->value() != q->price))
{
int is_change = QUIWidget::showMessageBoxQuestion("这批产品的进价/售价与已存在的这件商品的平均进价/售价不一样吗?");
if(is_change == 16384)
{
q->cost = (q->cost*q->number + ui->doubleSpinBox->value()*ui->doubleSpinBox_11->value())/(q->number + ui->doubleSpinBox_11->value());
q->price = (q->price*q->number + ui->doubleSpinBox_2->value()*ui->doubleSpinBox_11->value())/(q->number + ui->doubleSpinBox_11->value());
q->number = q->number + ui->doubleSpinBox_11->value();
}
}
else
{
q->number = q->number + ui->doubleSpinBox_11->value();
}
Log("入库",true,q);
}
}
return true;
}
bool Supermarket::BatchInput()
{
string file_name = QUIWidget::getFileName("user","*.csv;;*.qzq").toStdString();
QString qfile_name = QString::fromStdString(file_name);
QFileInfo fileinfo;
fileinfo = QFileInfo(qfile_name);
if(fileinfo.suffix() == "qzq")
{
QFile::remove("cache\\CacheData.qzq");
QUIWidget::copyFile(qfile_name,"cache\\CacheData.qzq");
QProcess process;
process.start("Des3.exe -u cache\\CacheData.qzq qwertyuiop cache\\CacheData.csv");
process.terminate();
process.waitForFinished();
process.close();
file_name = "cache\\CacheData.csv";
}
ifstream read_file(file_name,ios::in);
int counts = 0;
string line_str,str;
bool all_read = 1;
while(getline(read_file,line_str))
{
counts++;
Good *p,*q;
p = (Good*)new(Good);
stringstream ss(line_str);
getline(ss,str,',');
p->name = str;
getline(ss,str,',');
p->id = str;
getline(ss,str,',');
p->cost = stod(str);
getline(ss,str,',');
p->price = stod(str);
getline(ss,str,',');
p->number = stod(str);
getline(ss,str,',');
p->measure_unit = str;
getline(ss,str,',');
p->category = str;
getline(ss,str,',');
p->purchase_time =str;
getline(ss,str,',');
p->sell_time = str;
p->next = NULL;
if(SearchChild(p->id) == NULL)
{
number++;
if(head == NULL)
head = p;
else
{
q = GetLastPointer();
q->next = p;
}
}
else all_read = 0;
}
if(all_read == 0)QUIWidget::showMessageBoxInfo("部分数据的ID与现有数据重复未导入此部分数据项。");
read_file.close();
QFile::remove("cache\\CacheData.csv");
QFile::remove("cache\\CacheData.qzq");
Log("批量导入",true,NULL);
return true;
}
bool Supermarket::BatchOutput(string dir)
{
QString sdir = QString::fromStdString(dir);
dir = dir +"\\Data.csv";
ofstream wfile(dir);
Good* p = head;
if(head == NULL)
{
QUIWidget::showMessageBoxError("无数据可导出.");
return false;
}
else{
while(p!= NULL)
{
wfile<<p->name<<","<<p->id<<","<<p->cost<<","<<p->price<<","<<p->number<<","<<p->measure_unit<<","<<p->category<<","<<p->purchase_time<<","<<p->sell_time<<endl;
p = p->next;
}
wfile.close();
Log("批量导出",true,NULL);
}
return true;
}
bool Supermarket::OutStorage()
{
Good* p;
string pid = ui->lineEdit_11->text().toStdString();
double num = ui->doubleSpinBox_12->value();
p = SearchChild(pid);
if(p == NULL)
{
QUIWidget::showMessageBoxError("未找到您输入的ID请重新输入或搜索一下。");
}
else if(p->number < num || num<=0)
{
QUIWidget::showMessageBoxError("您输入的数量不正确,请检查。");
}
else if(p->number == num)
{
p->number = p->number-num;
number --;
Good*phead = head;
{
for(;phead->next != p;phead=phead->next);
phead->next = p->next;
}
//p->sell_time =QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz ddd").toStdString();
Log("出库",true,p);
}
else
{
p->number = p->number-num;
p->sell_time =QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz ddd").toStdString();
Log("出库",true,p);
}
return true;
}
Good* Supermarket::SearchChild(string pid)
{
Good* p = head, *q = NULL;
if(p == NULL)
{
return NULL;
}
else
{
while(p!=NULL)
{
if(p->id == pid)
{
q = p;
break;
}
else p = p->next;
}
return q;
}
}
void Supermarket:: Search()
{
string sid, sname, smeasure_unit, scategory;
double scost=0, sprice = 0,snumber = 0;
sid = ui->lineEdit_8->text().toStdString();
sname = ui->lineEdit_7->text().toStdString();
scost = ui->doubleSpinBox_7->value();
sprice = ui->doubleSpinBox_8->value();
snumber = ui->doubleSpinBox_13->value();
smeasure_unit = ui->comboBox_10->currentText().toStdString();
scategory = ui->comboBox_9->currentText().toStdString();
Good* p = head;
int counts = 0;
QStandardItemModel *model = new QStandardItemModel();
ui->tableView->setModel(model);
model->setColumnCount(9);
model->setHorizontalHeaderItem(0,new QStandardItem(QObject::tr("ID")));
model->setHorizontalHeaderItem(1,new QStandardItem(QObject::tr("名称")));
model->setHorizontalHeaderItem(2,new QStandardItem(QObject::tr("进价")));
model->setHorizontalHeaderItem(3,new QStandardItem(QObject::tr("售价")));
model->setHorizontalHeaderItem(4,new QStandardItem(QObject::tr("数量")));
model->setHorizontalHeaderItem(5,new QStandardItem(QObject::tr("单位")));
model->setHorizontalHeaderItem(6,new QStandardItem(QObject::tr("类别")));
model->setHorizontalHeaderItem(7,new QStandardItem(QObject::tr("入库时间")));
model->setHorizontalHeaderItem(8,new QStandardItem(QObject::tr("出库时间")));
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);//表头通过内容列宽自适应
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);//表头根据窗口自适应
if(p==NULL)
{
QUIWidget::showMessageBoxError("没有找到任何匹配项。");
}
else
{
for(;p!=NULL;p=p->next)
{
if((sid==p->id||sid=="")&&(sname==p->name||sname=="")&&(smeasure_unit==p->measure_unit||smeasure_unit=="可选单位")&&(scategory==p->category||scategory=="可选分类")&&(scost==p->cost||scost==0)&&(sprice==p->price||sprice==0)&&(snumber==p->number||snumber==0))
{
model->setItem(counts,0,new QStandardItem(QString::fromStdString(p->id)));
model->setItem(counts,1,new QStandardItem(QString::fromStdString(p->name)));
model->setItem(counts,2,new QStandardItem(QString::number(p->cost,10,2)));
model->setItem(counts,3,new QStandardItem(QString::number(p->price,10,2)));
model->setItem(counts,4,new QStandardItem(QString::number(p->number,10,2)));
model->setItem(counts,5,new QStandardItem(QString::fromStdString(p->measure_unit)));
model->setItem(counts,6,new QStandardItem(QString::fromStdString(p->category)));
model->setItem(counts,7,new QStandardItem(QString::fromStdString(p->purchase_time)));
model->setItem(counts,8,new QStandardItem(QString::fromStdString(p->sell_time)));
counts++;
}
ui->statusbar->showMessage("正在搜索...",500);
}
}
ui->statusbar->clearMessage();
ui->statusbar->showMessage("搜索完毕.",3000);
}
bool Supermarket::SetDate()
{
string sid, sname, smeasure_unit, scategory;
double scost=0, sprice = 0,snumber = 0;
sid = ui->lineEdit_10->text().toStdString();
sname = ui->lineEdit_9->text().toStdString();
scost = ui->doubleSpinBox_9->value();
sprice = ui->doubleSpinBox_10->value();
snumber = ui->doubleSpinBox_14->value();
smeasure_unit = ui->comboBox_12->currentText().toStdString();
scategory = ui->comboBox_11->currentText().toStdString();
if(sid == "")
QUIWidget::showMessageBoxInfo("ID是必须要输入的项",5);
else
{
Good *p = SearchChild(sid);
if(p == NULL)
{
QUIWidget::showMessageBoxError("未找到您输入的ID请重新输入或查询一下。");
return false;
}
else
{
if(sid != "")p->id = sid;
if(sname != "")p->name = sname;
if(scost != 0)p->cost = scost;
if(sprice != 0)p->price = sprice;
if(snumber != 0)p->number = snumber;
if(smeasure_unit != "可改单位")p->measure_unit = smeasure_unit;
if(scategory != "可改分类")p->category = scategory;
Log("修改",true,p);
return true;
}
}
return false;
}
long Supermarket::GetNumber()
{
return number;
}
//统计
void Supermarket::Statistics()
{
ui->label_17->setText("商品种数:");
ui->label_15->setText("员工总数:");
ui->label_13->setText("总支出:");
ui->label_11->setText("总价值:");
ui->label_18->setText(QString::number(number));
string file_name = "user//account.csv",line_str;
int account_num = 0;
ifstream read_account(file_name,ios::in);
while(getline(read_account,line_str))
{account_num++;}
ui->label_16->setText(QString::number(account_num));
double out = 0, in = 0;
Good *p = head;
if(p == NULL)
{
ui->label_14->setText("0");
ui->label_12->setText("0");
}
else
{
while(p!=NULL)
{
out = out + p->cost * p->number;
in = in +p->price * p->number;
p=p->next;
}
ui->label_14->setText(QString::number(out,10,6));
ui->label_12->setText(QString::number(in,10,6));
out = 0;
in = 0;
}
}
//写日志
void Supermarket::Log(string operators, bool end_out, Good *p)
{
static long long order = 1000000000000000000;
//序号 + 人 + 时间 + 操作 + 结果
int rc = pmodel->rowCount();
int cc = pmodel->columnCount();
string sstr;
char strc[25];
itoa(cc,strc,10);
sstr = strc;
//QUIWidget::showMessageBoxInfo(QString::fromStdString(sstr),3000);
if(cc != 5)
{
delete pmodel;
QStandardItemModel *model = new QStandardItemModel();
model->setColumnCount(5);
model->setHorizontalHeaderItem(0,new QStandardItem(QObject::tr("操作结果")));
model->setHorizontalHeaderItem(1,new QStandardItem(QObject::tr("操作序号")));
model->setHorizontalHeaderItem(2,new QStandardItem(QObject::tr("执行账户")));
model->setHorizontalHeaderItem(3,new QStandardItem(QObject::tr("操作时间")));
model->setHorizontalHeaderItem(4,new QStandardItem(QObject::tr("操作内容")));
pmodel = model;
rc = 0;
}
ui->tableView->setModel(pmodel);
//ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);//表头根据窗口自适应
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);//表头通过内容列宽自适应
ui->tableView->horizontalHeader()->setStretchLastSection(true);//不留空,但最后一列会很宽
//ui->tableView->setColumnWidth(0,100);
//ui->tableView->setColumnWidth(1,300);
//写入文件,最近操作在文件后方
string dir = "user\\Log.csv";
ofstream wfile(dir,ios::app);
order = order + 1;
string this_time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz ddd").toStdString();
wfile<<end_out<<","<<order<<","<<loginin_account<<","<<this_time<<","<<operators<<endl;
wfile.close();
if(order >= 9000000000000000000)
order = 1000000000000000000;
//显示到TableView
string snumber,send_out;
char str[22];
if(p!=NULL)
{
sprintf(str,"%.2f",p->number);
snumber = str;
}
if(end_out == true)send_out = "成功";
else send_out = "失败";
pmodel->setItem(rc,0,new QStandardItem(QString::fromStdString(send_out)));
pmodel->setItem(rc,1,new QStandardItem(QString::number(order)));
pmodel->setItem(rc,2,new QStandardItem(QString::fromStdString(loginin_account)));
pmodel->setItem(rc,3,new QStandardItem(QString::fromStdString(this_time)));
if(operators == "出库")
{
pmodel->setItem(rc,4,new QStandardItem(QString::fromStdString(""+operators+"ID为"+p->id+"的商品,仓库剩余"+snumber+p->measure_unit)));
}
else if(operators == "入库")
{
pmodel->setItem(rc,4,new QStandardItem(QString::fromStdString(""+operators+"ID为"+p->id+"的商品,仓库剩余"+snumber+p->measure_unit)));
}
else if(p!=NULL)
{
pmodel->setItem(rc,4,new QStandardItem(QString::fromStdString(operators+"ID为"+p->id+"的商品"+snumber+p->measure_unit)));
}
else
{
pmodel->setItem(rc,4,new QStandardItem(QString::fromStdString(operators)));
}
pmodel->sort(1, Qt::DescendingOrder);
}
/*
bool Supermarket::Upload()
{
QString path="http://192.168.252.2:8000/disk/"; //服务器的url
QMap<QString,QString> params_send; //上传的普通参数 在本程序中 需要上传一个普通参数为"username"
params_send.insert("username","10005");
QString fileFormName="upload_file"; //上传文件表单中的名字
QFile *file=new QFile(":/Untitled.png");
QString newFileName="1A.png";
UpLoadForm(path,params_send,fileFormName,file,newFileName);
return true;
}
//上传备份
void UpLoadForm(QString Path,QMap<QString,QString> params,QString fileFormName,QFile *uploadFile,QString newFileName){
QString BOUNDARY=QUuid::createUuid().toString();
QByteArray sb=QByteArray();
//先上传普通的表单数据
for(QMap<QString,QString>::Iterator t=params.begin();t!=params.end();t++){
sb.append("--"+BOUNDARY+"\r\n");
sb.append(QString("Content-Disposition: form-data; name=\"")+t.key()+QString("\"")+QString("\r\n"));
sb.append("\r\n");
sb.append(t.value()+"\r\n");
}
//上传文件的头部
sb.append("--"+BOUNDARY+"\r\n");
sb.append(QString("Content-Disposition: form-data; name=\"")+fileFormName+QString("\"; filename=\"")+newFileName+QString("\"")+QString("\r\n"));
sb.append("\r\n");
//上传文件内容
if(!uploadFile->open(QIODevice::ReadOnly)){
return;
}
sb.append(uploadFile->readAll());
sb.append("\r\n");
sb.append("--"+BOUNDARY+"\r\n");
//编辑HTTP头部
QNetworkAccessManager *_uploadManager=new QNetworkAccessManager();
QNetworkRequest request=QNetworkRequest(QUrl(Path));
request.setRawHeader(QString("Content-Type").toLatin1(),QString("multipart/form-data; boundary="+BOUNDARY).toLatin1());
request.setRawHeader(QString("Content-Length").toLatin1(),QString::number(sb.length()).toLatin1());
//执行post请求
_uploadManager->post(request,sb);
}
*/
// 在状态栏显示清理完毕的提示信息
ui->statusbar

@ -1,93 +1,166 @@
#ifndef SUPERMARKET_H
#define SUPERMARKET_H
// 包含Qt的主窗口头文件用于创建基于Qt的图形用户界面应用程序的主窗口类
#include <QMainWindow>
// 包含C++标准输入输出流文件操作相关头文件,用于读写文件等操作
#include<fstream>
// 包含字符串流头文件,方便对字符串进行分割、解析等操作,常用于处理按特定格式分隔的文本数据
#include<sstream>
// 包含C++标准输入输出流头文件,用于基本的控制台输入输出操作(这里可能部分功能未用到,但习惯性包含)
#include<iostream>
// 包含Qt的字符串类头文件用于处理文本字符串在Qt框架中广泛使用
#include<QString>
// 包含C++标准字符串头文件用于使用标准的字符串类型便于与其他C++标准库函数配合使用
#include <string>
// 包含Qt的定时器类头文件用于实现定时触发某些操作的功能比如定时更新界面显示、执行定时任务等
#include <QTimer>
// 包含Qt的文件操作类头文件用于进行文件的读写、复制、删除等各种文件相关操作
#include <QFile>
// 包含Qt的网络相关类头文件虽然此处代码中未明确体现其具体使用但可能后续会用于网络通信相关功能扩展
#include <QtNetwork>
// 包含Qt的调试输出头文件方便在调试程序时输出相关信息查看程序运行状态和变量值等
#include <QDebug>
// 包含Qt的日期时间类头文件用于获取、处理日期时间相关信息比如记录操作时间、显示时间等
#include <qdatetime.h>
// 包含由UI设计工具生成的超市界面相关的头文件里面包含了界面元素的定义和相关操作函数声明等
#include "ui_supermarket.h"
// 包含自定义的QUIWidget头文件可能这个类提供了一些通用的窗口部件相关的功能、样式设置等供本类使用
#include "quiwidget.h"
// 使用标准命名空间避免在使用标准库中的类型、函数等时需要频繁添加std::前缀
using namespace std;
// 声明Ui命名空间下的Supermarket类这是由UI设计工具生成的类具体定义在对应的ui_supermarket.cpp文件中此处提前声明方便后续使用
namespace Ui {
class Supermarket;
}
// 定义Good结构体用于表示商品的相关信息一个Good结构体对象代表一个商品的各项属性
struct Good
{
// 商品名称,使用标准字符串类型存储
string name;
// 商品的唯一标识符ID用于区分不同商品
string id;
double cost, price; //分别是进价和售价
// 商品的进价,即进货价格,使用双精度浮点数类型表示
double cost,
// 商品的售价,即销售给顾客的价格,同样为双精度浮点数类型
price;
// 商品的库存数量,以数字形式存储
double number;
string measure_unit, category; //计量单位和类别
string purchase_time, sell_time; //入库、出库时间和保质期
// 商品的计量单位,比如个、千克、升等,用字符串表示
string measure_unit,
// 商品的分类信息,例如食品、日用品等,也是字符串类型
category;
// 商品的入库时间,记录商品进入仓库的具体日期时间,格式为字符串
string purchase_time,
// 商品的出库时间,记录商品从仓库发出(销售等情况)的日期时间,初始为暂无记录等表示,同样是字符串类型
sell_time;
// 指向下一个商品节点的指针,用于构建链表结构来存储多个商品信息
Good* next;
};
// 定义Supermarket类继承自QMainWindow代表超市管理系统的主窗口类包含了各种与超市业务操作相关的功能和界面交互逻辑
class Supermarket : public QMainWindow
{
Q_OBJECT
public:
// 显式构造函数用于创建Supermarket类的实例对象传入父窗口指针默认值为0表示无父窗口
explicit Supermarket(QWidget *parent = 0);
// 析构函数用于释放Supermarket类对象占用的资源比如相关的内存空间等
~Supermarket();
bool ManInput(); //人工输入并创建、入库商品,成功返回1,否则0,下同
bool BatchInput(); //批量导入
bool BatchOutput(string dir); //导出数据
bool OutStorage(); //出库操作
bool SetDate(); //修改数据
Good* SearchChild(string pid); //搜索查询部件
// 人工输入商品信息并创建商品对象将其入库到系统中操作成功返回1失败返回0默认用于单个商品的手动录入操作
bool ManInput();
// 批量导入商品数据从外部文件读取数据并解析后添加到系统中成功返回1失败返回0用于一次性导入多个商品信息的场景
bool BatchInput();
// 将系统中的商品数据导出到指定目录下以某种格式可能是文件形式保存成功返回1失败返回0用于数据备份、共享等需求
bool BatchOutput(string dir);
// 执行商品出库操作减少库存数量等相关处理成功返回1失败返回0对应商品销售等出库业务场景
bool OutStorage();
// 修改商品的相关数据比如价格、数量等信息成功返回1失败返回0用于对已存在商品信息的更新操作
bool SetDate();
// 根据商品ID在系统中搜索查询对应的商品信息返回找到的商品指针Good*类型若未找到则返回NULL
Good* SearchChild(string pid);
// 执行商品信息的搜索操作,可能是根据多个条件在系统中查找符合要求的商品,并将结果展示在界面上(具体展示方式看函数实现)
void Search();
long GetNumber(); //个数
// 获取系统中商品的总个数,返回长整型的数量值,用于统计库存商品总数等情况
long GetNumber();
// 获取商品链表中的最后一个商品节点的指针,用于在链表末尾添加新节点等操作场景
Good* GetLastPointer();
bool CheckAccount(bool a = 1);//用户权限检查
// 检查用户的权限传入参数a默认值为1可根据不同情况传入不同值来区分不同权限检查需求根据规则返回是否有权限的布尔值
bool CheckAccount(bool a = 1);
// 检查给定的商品ID是否已经存在于系统中返回布尔值用于在添加新商品时避免ID重复等情况
bool CheckID(string pid);
void Statistics();//统计
void Log(string operators, bool end_out,Good *p); //操作记录日志
// 进行各种统计相关操作,比如统计商品总价值、总支出等信息,用于生成报表、展示统计数据等功能
void Statistics();
// 记录操作记录日志传入操作名称、操作是否成功的布尔值以及操作对应的商品指针可为NULL具体看操作类型用于记录系统中的关键操作历史
void Log(string operators, bool end_out,Good *p);
// 以下函数被注释掉了,可能原本计划实现但暂未完成或者后续不再需要的功能,从函数名看可能是用于上传相关操作(比如上传数据到服务器等)
//bool Upload();
QTime t;
// 用于记录时间相关操作的时间对象,具体使用场景看对应函数实现(比如统计操作耗时等)
QTime t;
private:
// 指向由UI设计工具生成的超市界面类的指针通过这个指针可以访问和操作界面上的各种元素如按钮、文本框等
Ui::Supermarket *ui;
// 指向商品链表头节点的指针,用于管理系统中的所有商品信息,通过链表结构存储多个商品
Good *head;
// 记录系统中商品的总数量,方便快速获取库存商品总数,避免每次都遍历链表统计
long number;
// 指向一个标准项模型对象,用于与界面上的表格视图等控件配合,展示和管理数据(如商品列表数据等)
QStandardItemModel *pmodel;
// 记录当前登录的账户名称,用于权限判断、操作记录等与用户账户相关的功能逻辑
string loginin_account;
private slots:
// 初始化表单相关设置,比如创建模型、设置界面显示等,返回初始化好的标准项模型指针,供后续操作使用
QStandardItemModel* initForm();
// 进行登录账户后的相关初始化操作,比如显示登录后应显示的界面元素,隐藏未登录时的相关元素等
void initAccount();
// 进行未登录账户时的界面初始化操作,隐藏登录后才显示的元素,显示未登录相关的界面元素,如登录框等
void initUnAccount();
// 处理登录按钮点击事件的槽函数,用于验证用户输入的账号和密码,并进行登录相关的业务逻辑处理
void on_pushButton_clicked();
// 处理某个按钮可能是与人工输入商品相关的按钮点击事件的槽函数调用ManInput函数进行人工输入商品操作
void on_pushButton_3_clicked();
// 处理某个按钮可能是与商品出库相关的按钮点击事件的槽函数调用OutStorage函数执行商品出库操作
void on_pushButton_2_clicked();
// 处理某个按钮可能是与商品搜索相关的按钮点击事件的槽函数调用Search函数进行商品搜索操作
void on_pushButton_6_clicked();
// 处理某个按钮可能是与修改商品数据相关的按钮点击事件的槽函数调用SetDate函数执行修改商品数据操作
void on_pushButton_7_clicked();
// 处理某个菜单动作可能是批量输入相关菜单选项触发事件的槽函数调用BatchInput函数执行批量导入商品数据操作
void on_action_O_triggered();
// 处理某个菜单动作可能是导出CSV文件相关菜单选项触发事件的槽函数调用BatchOutput函数执行导出数据操作
void on_actionCSV_C_triggered();
// 处理某个菜单动作(可能是查看帮助相关菜单选项)触发事件的槽函数,具体功能看实现(可能打开帮助文档等)
void on_action_H_triggered();
// 处理某个菜单动作(可能是打开某个网址相关菜单选项)触发事件的槽函数,具体功能看实现(可能打开指定网页用于展示信息等)
void on_action_A_triggered();
// 处理某个菜单动作(可能是打开另一个网址相关菜单选项)触发事件的槽函数,具体功能看实现(类似上面打开网址的功能,不同网址对应不同用途)
void on_action_B_triggered();
// 处理某个按钮(可能是用于清空某些输入框等操作的按钮)点击事件的槽函数,执行对应的清空操作,重置界面上相关输入控件的内容
void on_pushButton_8_clicked();
// 处理另一个按钮(可能也是用于清空相关输入框等操作的按钮)点击事件的槽函数,执行对应的清空操作,类似上面的功能但针对不同的输入控件
void on_pushButton_9_clicked();
// 处理又一个按钮(同样可能是清空输入框相关操作按钮)点击事件的槽函数,执行清空操作,针对另外一组输入控件进行重置
void on_pushButton_10_clicked();
// 处理某个按钮(可能是退出登录或者重置登录状态相关按钮)点击事件的槽函数,执行相应的操作,比如清空登录账户信息,恢复未登录界面显示等
void on_pushButton_4_clicked();
// 处理某个菜单动作(可能是清空数据库相关菜单选项)触发事件的槽函数,执行清空数据库的相关操作,比如删除所有商品记录等
void on_actiond_2_triggered();
// 处理某个菜单动作(可能是导出操作记录相关菜单选项)触发事件的槽函数,执行导出操作记录相关的操作,比如将操作日志保存到文件等
void on_actiond_triggered();
// 处理某个菜单动作(可能是特定的加密或数据处理相关菜单选项)触发事件的槽函数,执行对应的复杂操作(具体看函数实现内容)
void on_actiondda_triggered();
public slots:
// 定时器触发的槽函数,用于更新界面上显示的当前时间信息,保持时间显示的实时性
void timerUpdate(void);
// 定时器触发的另一个槽函数,用于执行随着时间增加而需要进行的操作,比如统计数据更新等(具体看函数实现)
void timerAdd();
};
// 以下函数被注释掉了,可能原本计划实现但暂未完成或者后续不再需要的功能,从函数名看可能是用于上传相关操作的具体实现函数(比如设置上传参数、上传文件等)
//void UpLoadForm(QString Path,QMap<QString,QString> params,QString fileFormName,QFile *uploadFile,QString newFileName);
#endif // SUPERMARKET_H
#endif // SUPERMARKET_H

@ -5,22 +5,48 @@
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
// 以上是一段注释说明告知该代码是由Qt用户界面编译器Qt User Interface Compiler从名为'login.ui'的UI文件生成而来
// 同时提醒如果重新编译UI文件在此文件中所做的更改将会丢失。
#ifndef UI_LOGIN_H
#define UI_LOGIN_H
// 条件编译指令用于防止头文件被重复包含。如果UI_LOGIN_H这个宏没有被定义过就执行下面的代码直到遇到 #endif。
#include <QtCore/QVariant>
// 引入QtCore模块中的QVariant类的头文件QVariant是一种通用的数据类型可以存储多种不同类型的数据常用于在Qt中处理不同类型的数据传递等情况。
#include <QtWidgets/QAction>
// 引入QtWidgets模块中的QAction类的头文件QAction通常用于表示一个可以执行的动作比如菜单项、工具栏按钮对应的操作等可关联快捷键、图标等属性。
#include <QtWidgets/QApplication>
// 引入QtWidgets模块中的QApplication类的头文件QApplication是Qt应用程序的基础类用于管理整个应用程序的资源、事件循环等每个Qt应用程序都需要创建一个该类的实例来启动。
#include <QtWidgets/QButtonGroup>
// 引入QtWidgets模块中的QButtonGroup类的头文件QButtonGroup用于对按钮进行分组管理方便统一处理按钮相关的逻辑例如设置按钮组内的互斥等功能。
#include <QtWidgets/QDialog>
// 引入QtWidgets模块中的QDialog类的头文件QDialog是用于创建对话框窗口的基类常用于弹出式的交互界面比如提示框、登录框等。
#include <QtWidgets/QGridLayout>
// 引入QtWidgets模块中的QGridLayout类的头文件QGridLayout是一种布局管理器按照网格形式来排列其中的子部件方便进行规则的界面布局。
#include <QtWidgets/QHBoxLayout>
// 引入QtWidgets模块中的QHBoxLayout类的头文件QHBoxLayout是水平布局管理器会将添加到其中的子部件按照水平方向依次排列。
#include <QtWidgets/QHeaderView>
// 引入QtWidgets模块中的QHeaderView类的头文件QHeaderView常用于在视图类如列表视图、表格视图等中作为表头显示部分可自定义表头的外观和交互行为等但此处可能并非核心使用场景也许是其他相关布局或组件依赖了它。
#include <QtWidgets/QLabel>
// 引入QtWidgets模块中的QLabel类的头文件QLabel用于显示文本或图像等静态信息常作为界面中的提示标签等用途。
#include <QtWidgets/QLineEdit>
// 引入QtWidgets模块中的QLineEdit类的头文件QLineEdit是用于用户输入单行文本的部件比如输入用户名、密码等场景会用到。
#include <QtWidgets/QPushButton>
// 引入QtWidgets模块中的QPushButton类的头文件QPushButton是常见的按钮部件用户点击可触发相应的操作或事件。
#include <QtWidgets/QVBoxLayout>
// 引入QtWidgets模块中的QVBoxLayout类的头文件QVBoxLayout是垂直布局管理器会将添加到其中的子部件按照垂直方向依次排列。
QT_BEGIN_NAMESPACE
@ -28,100 +54,169 @@ class Ui_Login
{
public:
QVBoxLayout *verticalLayout;
// 声明一个垂直布局管理器指针verticalLayout用于对整个登录界面进行整体的垂直布局安排后续会在这个布局中添加其他子布局和部件。
QVBoxLayout *verticalLayout_2;
// 声明另一个垂直布局管理器指针verticalLayout_2其具体用途将在后续代码中体现可能用于界面某一部分的垂直布局划分。
QGridLayout *gridLayout;
// 声明一个网格布局管理器指针gridLayout推测是用于以网格形式排列登录界面中的输入框和对应的标签等部件方便进行整齐的布局设置。
QLineEdit *lineEdit_2;
// 声明一个QLineEdit类型的指针lineEdit_2从后续代码看可能用于用户输入密码等文本信息是界面中的一个输入部件。
QLineEdit *lineEdit;
// 声明一个QLineEdit类型的指针lineEdit可能用于用户输入用户名等文本信息同样是界面中的一个输入部件。
QLabel *label;
// 声明一个QLabel类型的指针label用于在界面中显示相应的提示文本可能是对应lineEdit_2比如密码输入框的提示标签。
QLabel *label_2;
// 声明一个QLabel类型的指针label_2同样用于显示提示文本可能是对应lineEdit比如用户名输入框的提示标签。
QVBoxLayout *verticalLayout_3;
// 声明又一个垂直布局管理器指针verticalLayout_3具体作用将在后续代码中明确可能用于界面另一部分的垂直布局组织。
QHBoxLayout *horizontalLayout;
// 声明一个水平布局管理器指针horizontalLayout推测是用于将登录界面中的按钮如登录、取消等按钮按照水平方向进行排列布局。
QPushButton *pushButton_3;
// 声明一个QPushButton类型的指针pushButton_3是界面中的一个按钮部件具体功能由后续设置的文本等确定。
QPushButton *pushButton_2;
// 声明一个QPushButton类型的指针pushButton_2同样是界面中的一个按钮部件其功能也有待后续文本设置等操作明确。
QPushButton *pushButton;
// 声明一个QPushButton类型的指针pushButton也是界面中的一个按钮部件具体用途会在后续代码中体现。
void setupUi(QDialog *Login)
// 定义setupUi函数用于设置登录界面Login对话框的布局和部件相关属性传入的参数Login是指向QDialog类型的指针表示要设置的登录对话框对象。
{
if (Login->objectName().isEmpty())
Login->setObjectName(QStringLiteral("Login"));
// 判断传入的登录对话框对象Login的objectName是否为空如果为空则将其objectName设置为"Login",方便在程序中通过名称来识别该对话框。
Login->resize(257, 163);
// 设置登录对话框Login的初始大小为宽257像素高163像素确定登录界面的初始尺寸。
verticalLayout = new QVBoxLayout(Login);
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
// 创建一个垂直布局管理器对象并将其关联到登录对话框Login上同时为该布局管理器设置一个名称方便后续通过名称来操作它这个布局将作为整个登录界面布局的基础容器。
verticalLayout_2 = new QVBoxLayout();
verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2"));
// 创建另一个垂直布局管理器对象verticalLayout_2同样设置其名称后续会将它添加到前面创建的verticalLayout布局中用于界面某部分的布局划分。
verticalLayout->addLayout(verticalLayout_2);
// 将verticalLayout_2布局添加到verticalLayout布局中按照垂直方向排列目前verticalLayout_2还是一个空的布局容器后续会往里添加部件或子布局。
gridLayout = new QGridLayout();
gridLayout->setObjectName(QStringLiteral("gridLayout"));
// 创建一个网格布局管理器对象gridLayout并设置其名称用于以网格形式排列相关部件比如输入框和对应的标签等使其布局更规整。
lineEdit_2 = new QLineEdit(Login);
lineEdit_2->setObjectName(QStringLiteral("lineEdit_2"));
// 创建一个QLineEdit对象用于输入文本的部件并将其关联到登录对话框Login上同时设置其名称这个部件可能用于输入密码等信息后续会添加到网格布局中。
gridLayout->addWidget(lineEdit_2, 1, 1, 1, 1);
// 将lineEdit_2这个QLineEdit部件添加到gridLayout网格布局中参数(1, 1, 1, 1)表示放置在网格的第1行第1列跨越1行1列确定其在网格布局中的位置。
lineEdit = new QLineEdit(Login);
lineEdit->setObjectName(QStringLiteral("lineEdit"));
// 创建另一个QLineEdit对象同样关联到登录对话框Login并设置名称这个部件可能用于输入用户名等信息后续也会添加到网格布局中。
gridLayout->addWidget(lineEdit, 0, 1, 1, 1);
// 将lineEdit这个QLineEdit部件添加到gridLayout网格布局中放置在第0行第1列跨越1行1列与其他部件一起构成网格布局的一部分。
label = new QLabel(Login);
label->setObjectName(QStringLiteral("label"));
// 创建一个QLabel对象用于显示文本的标签部件关联到登录对话框Login并设置名称该标签可能用于提示密码输入相关的信息后续会添加到网格布局中与对应的输入框配合。
gridLayout->addWidget(label, 1, 0, 1, 1);
// 将label这个QLabel部件添加到gridLayout网格布局中放置在第1行第0列跨越1行1列与前面添加的lineEdit_2输入框对应形成输入框和标签的布局组合。
label_2 = new QLabel(Login);
label_2->setObjectName(QStringLiteral("label_2"));
// 创建另一个QLabel对象同样关联到登录对话框Login并设置名称该标签可能用于提示用户名输入相关的信息后续也添加到网格布局中。
gridLayout->addWidget(label_2, 0, 0, 1, 1);
// 将label_2这个QLabel部件添加到gridLayout网格布局中放置在第0行第0列跨越1行1列与前面添加的lineEdit输入框对应形成用户名相关的输入框和标签的布局组合。
gridLayout->setColumnStretch(0, 2);
gridLayout->setColumnStretch(1, 7);
// 设置gridLayout网格布局中列的拉伸比例第0列的拉伸比例设置为2第1列的拉伸比例设置为7这样在界面大小改变时各列会按照这个比例自动调整宽度保证布局的合理性。
verticalLayout->addLayout(gridLayout);
// 将gridLayout网格布局添加到verticalLayout垂直布局中按照垂直方向排列使得用户名、密码输入框及对应的标签等部件显示在登录界面的相应位置。
verticalLayout_3 = new QVBoxLayout();
verticalLayout_3->setObjectName(QStringLiteral("verticalLayout_3"));
// 创建又一个垂直布局管理器对象verticalLayout_3设置其名称后续会将它添加到最外层的verticalLayout布局中用于界面另一部分的布局安排。
verticalLayout->addLayout(verticalLayout_3);
// 将verticalLayout_3布局添加到verticalLayout垂直布局中目前它还是空的布局容器可能用于后续添加其他部件或进行空白间隔等布局设置。
horizontalLayout = new QHBoxLayout();
horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
// 创建一个水平布局管理器对象horizontalLayout并设置其名称用于将登录界面中的按钮按照水平方向进行排列布局。
pushButton_3 = new QPushButton(Login);
pushButton_3->setObjectName(QStringLiteral("pushButton_3"));
// 创建一个QPushButton对象按钮部件关联到登录对话框Login并设置名称该按钮的具体功能和显示文本等会在后续代码中进一步设置。
horizontalLayout->addWidget(pushButton_3);
// 将pushButton_3按钮添加到horizontalLayout水平布局中按照水平方向排列使其在界面中处于合适的位置。
pushButton_2 = new QPushButton(Login);
pushButton_2->setObjectName(QStringLiteral("pushButton_2"));
// 创建另一个QPushButton对象同样关联到登录对话框Login并设置名称该按钮也会在后续设置具体功能和显示文本等属性。
horizontalLayout->addWidget(pushButton_2);
// 将pushButton_2按钮添加到horizontalLayout水平布局中与其他按钮一起按照水平方向排列准备构成按钮组的布局。
pushButton = new QPushButton(Login);
pushButton->setObjectName(QStringLiteral("pushButton"));
// 创建又一个QPushButton对象关联到登录对话框Login并设置名称同样等待后续设置其具体功能和显示文本等内容。
horizontalLayout->addWidget(pushButton);
// 将pushButton按钮添加到horizontalLayout水平布局中至此三个按钮都添加到了水平布局中后续会通过设置文本等操作使其成为具有明确功能的登录相关按钮。
verticalLayout->addLayout(horizontalLayout);
// 将horizontalLayout水平布局添加到verticalLayout垂直布局中按照垂直方向排列使得按钮组显示在登录界面的相应位置完成整个登录界面的布局安排。
verticalLayout->setStretch(0, 2);
verticalLayout->setStretch(1, 9);
verticalLayout->setStretch(2, 2);
verticalLayout->setStretch(3, 1);
// 设置verticalLayout垂直布局中各个子布局或部件所在区域的拉伸比例不同的比例会影响在界面大小改变时各部分所占空间的分配情况使得界面布局在不同尺寸下能保持相对合理的外观。
retranslateUi(Login);
// 调用retranslateUi函数用于设置界面中各部件显示的文本内容比如按钮的文字、标签的提示文本等实现界面文本的本地化或自定义设置。
QMetaObject::connectSlotsByName(Login);
// 使用Qt的元对象系统根据部件的名称自动连接信号与槽方便实现按钮点击等事件与对应的处理函数的关联使得界面具有交互性。
} // setupUi
void retranslateUi(QDialog *Login)
// 定义retranslateUi函数用于翻译或设置登录界面中各部件的显示文本内容传入的参数Login是指向QDialog类型的登录对话框对象。
{
Login->setWindowTitle(QApplication::translate("Login", "Dialog", Q_NULLPTR));
// 设置登录对话框Login的窗口标题通过QApplication的translate函数进行文本翻译这里如果有国际化相关设置会根据当前语言环境获取对应的翻译文本当前设置为"Dialog"),实际可能就是显示为"Dialog"这个英文单词作为窗口标题。
label->setText(QApplication::translate("Login", " \345\257\206\347\240\201\357\274\232", Q_NULLPTR));
// 设置label标签部件显示的文本内容同样通过translate函数进行文本处理这里显示的是一串特定编码可能是UTF-8等编码格式下的中文字符编码的文本具体含义需要看对应的编码对应的实际字符内容可能是密码相关的提示信息。
label_2->setText(QApplication::translate("Login", " \350\264\246\345\217\267\357\274\232", Q_NULLPTR));
// 设置label_2标签部件显示的文本内容也是通过translate函数进行文本处理同样是特定编码的文本可能是用户名相关的提示信息。
pushButton_3->setText(QApplication::translate("Login", "\345\277\230\350\256\260\345\257\206\347\240\201(F)", Q_NULLPTR));
// 设置pushButton_3按钮部件显示的文本内容通过translate函数进行文本翻译和设置这里显示的文本也是特定编码格式下的内容可能是对应某个功能比如忘记密码等从编码对应的实际字符猜测的按钮文字括号中的F可能是快捷键提示之类的标识。
pushButton_2->setText(QApplication::translate("Login", "\347\231\273\345\275\225(L)", Q_NULLPTR));
// 设置pushButton_2按钮部件显示的文本内容通过translate函数进行文本处理显示的文本可能对应登录功能从编码对应的实际字符及括号中的L猜测可能是Login的缩写作为快捷键提示之类的标识用于用户点击登录操作。
pushButton->setText(QApplication::translate("Login", "\345\217\226\346\266\210(C)", Q_NULLPTR));
// 设置pushButton按钮部件显示的文本内容通过translate函数进行文本处理显示的文本可能对应取消等功能从编码对应的实际字符及括号中的C猜测可能是Cancel的缩写作为快捷键提示之类的标识用于用户点击取消操作或关闭登录界面等。
} // retranslateUi
};
@ -129,7 +224,4 @@ public:
namespace Ui {
class Login: public Ui_Login {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_LOGIN_H
// 在Ui命名空间中定义了一个名为Login的类它继承自Ui_Login类这种嵌套定义的方式在Qt的UI代码生成机制中有特定的用途方便区分不同模块或界面的UI相关

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save