客户端及时通讯系统(1)

编写核心数据结构

  • 一、核心数据结构介绍
  • 二、将本地新项目推送到gitee已有仓库上
  • 三、代码实现
    • 3.1 核心数据结构成员变量设计和工具类设计

一、核心数据结构介绍

1)用户信息(UserTnfo)
用户的属性

2)会话信息(ChatSessionInfo)
用户与用户之间的聊天会话

3)消息信息(Message)
文本消息
图片消息
文件消息
语音消息

文本消息,是正文的字符串;图片、文件、语言消息,正文是一个二进制序列。
表示字符串,必须使用QString;表示二进制数据,必须使用QByteArray。

1.我们要创建目录然后创建文件来表示我们的核心类,model是MVC结构里的模型(qt Creator中不方便直接创建,我们就手动创建model)
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
2.把c++头文件导入到qt里
在这里插入图片描述
在这里插入图片描述
3.qt的Cmake自动更新文件内容,编译qt文件所需要的依赖(qt_add_executable)
在这里插入图片描述
4.命名空间的约定(我设置的当前约定)

1.如果代码所在文件,就是项目的顶层目录中,就直接使用全局的命名空间(不需要手动设置命名空间)
2.如果代码所在文件,在某个子目录中,此时子目录就是文件的命名空间

5.认识static

普通函数:需要把对象构造出来,才能使用普通的函数
加static的函数:不需要先构造函数就可以调用。

6.认识uuid

UUID这个东西,背后是一套算法,就能生成全球唯一的身份标识。

7.认识qDebug

qDebug 打印字符串的时候, 就会自动加上 " “;
qDebug().noquote()可以去除双引号(”")。

二、将本地新项目推送到gitee已有仓库上

在命令窗口中输入:git init
在 Gitee 中 我们刚刚新建的仓库里,去复制仓库的地址
在命令窗口中输入:git remote add origin 你的仓库地址
在命令窗口中输入:git pull origin master
在命令窗口中输入:git add .
在命令窗口中输入:git commit -m “提交项目”
在命令窗口中输入:git push origin master

三、代码实现

3.1 核心数据结构成员变量设计和工具类设计

#pragma once

#include <QString>
#include <QIcon>
#include <QUuid>
#include <QDateTime>
#include <QFile>
#include <QFileInfo>
#include <QDebug>

//创建命名空间
namespace model {

//
/// 工具函数. 后续很多模块可能都要用到
//

static inline QString getFileName(const QString& path) {
    QFileInfo fileInfo(path);
    return fileInfo.fileName();
}

// 封装一个 "宏" 作为打印日志的方式.
#define TAG QString("[%1:%2]").arg(model::getFileName(__FILE__), QString::number(__LINE__))
// #define TAG "[" << __LINE__ << "]"

// qDebug 打印字符串的时候, 就会自动加上 " "
#define LOG() qDebug().noquote() << TAG

// 要求函数的定义如果写在 .h 中, 必须加 static 或者 inline (当然两个都加也可以), 避免链接阶段出现 "函数重定义" 的问题.
static inline QString formatTime(int64_t timestamp) {
    // 先把时间戳, 转换成 QDateTime 对象
    QDateTime dateTime = QDateTime::fromSecsSinceEpoch(timestamp);
    // 把 QDateTime 对象转成 "格式化时间"
    return dateTime.toString("MM-dd HH:mm:ss");
}

// 通过这个函数得到 秒级 的时间
static inline int64_t getTime() {
    return QDateTime::currentSecsSinceEpoch();
}

// 根据 QByteArray, 转成 QIcon
static inline QIcon makeIcon(const QByteArray& byteArray) {
    //QPixmap提供很多关于图片的处理方法
    QPixmap pixmap;
    //加载数据
    pixmap.loadFromData(byteArray);
    QIcon icon(pixmap);
    return icon;
}

// 读写文件操作.
// 从指定文件中, 读取所有的二进制内容. 得到一个 QByteArray
static inline QByteArray loadFileToByteArray(const QString& path) {
    QFile file(path);
    bool ok = file.open(QFile::ReadOnly);
    if (!ok) {
        LOG() << "文件打开失败!";
        return QByteArray();
    }
    QByteArray content = file.readAll();
    file.close();
    return content;
}

// 把 QByteArray 中的内容, 写入到某个指定文件里
static inline void writeByteArrayToFile(const QString& path, const QByteArray& content) {
    QFile file(path);
    bool ok = file.open(QFile::WriteOnly);
    if (!ok) {
        LOG() << "文件打开失败!";
        return;
    }
    file.write(content);
    file.flush();
    file.close();
}


/
/// 用户信息
/

//用户信息
class UserInfo{
public:
    QString userId = "";			// 用户编号
    QString nickname = "";			// 用户昵称
    QString description = ""; 		// 用户签名
    QString phone = "";				// 手机号码
    QIcon avatar;					// 用户头像
};

/
/// 消息信息
/

enum MessageType {
    TEXT_TYPE,		// 文本消息
    IMAGE_TYPE, 	// 图片消息
    FILE_TYPE, 		// 文件消息
    SPEECH_TYPE 	// 语音消息
};

class Message {
public:
    QString messageId = "";				// 消息的编号
    QString chatSessionId = "";			// 消息所属会话的编号
    QString time = "";					// 消息的时间. 通过 "格式化" 时间的方式来表示. 形如 06-07 12:00:00
    MessageType messageType = TEXT_TYPE;// 消息类型
    UserInfo sender;			    // 发送者的信息
    QByteArray content;					// 消息的正文内容
    QString fileId = "";				// 文件的身份标识. 当消息类型为 文件, 图片, 语音 的时候, 才有效. 当消息类型为 文本, 则为 ""
    QString fileName = ""; 				// 文件名称. 只是当消息类型为 文件 消息, 才有效. 其他消息均为 ""

    // 此处 extraInfo 目前只是在消息类型为文件消息时, 作为 "文件名" 补充.
    static Message makeMessage(MessageType messageType, const QString& chatSessionId, const UserInfo& sender,
    const QByteArray& content, const QString& extraInfo) {
        if (messageType == TEXT_TYPE) {
            return makeTextMessage(chatSessionId, sender, content);
        } else if (messageType == IMAGE_TYPE) {
            return makeImageMessage(chatSessionId, sender, content);
        } else if (messageType == FILE_TYPE) {
            return makeFileMessage(chatSessionId, sender, content, extraInfo);
        } else if (messageType == SPEECH_TYPE) {
            return makeSpeechMessage(chatSessionId, sender, content);
        } else {
            // 触发了未知的消息类型
            return Message();
        }
    }

private:
    // 通过这个方法生成唯一的 messageId
    static QString makeId() {
        return "M" + QUuid::createUuid().toString().sliced(25, 12);
    }

    static Message makeTextMessage(const QString& chatSessionId, const UserInfo& sender, const QByteArray& content) {
        Message message;
        // 此处需要确保, 设置的 messageId 是 "唯一" 的
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime()); // 生成一个格式化时间
        message.content = content;
        message.messageType = TEXT_TYPE;
        // 对于文本消息来说, 这俩属性不使用, 设为 ""
        message.fileId = "";
        message.fileName = "";
        return message;
    }

    static Message makeImageMessage(const QString& chatSessionId, const UserInfo& sender, const QByteArray& content) {
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.content = content;
        message.messageType = IMAGE_TYPE;
        // fileId 后续使用的时候再进一步设置
        message.fileId = "";
        // fileName 不使用, 直接设为 ""
        message.fileName = "";
        return message;
    }

    static Message makeFileMessage(const QString& chatSessionId, const UserInfo& sender, const QByteArray& content, const QString& fileName) {
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.content = content;
        message.messageType = FILE_TYPE;
        // fileId 后续使用的时候进一步设置
        message.fileId = "";
        message.fileName = fileName;
        return message;
    }

    static Message makeSpeechMessage(const QString& chatSessionId, const UserInfo& sender, const QByteArray& content) {
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.content = content;
        message.messageType = SPEECH_TYPE;
        // fileId 后续使用的时候进一步设置
        message.fileId = "";
        // fileName 不使用, 直接设为 ""
        message.fileName = "";
        return message;
    }

};

/
/// 会话信息
/
class ChatSessionInfo {
public:
    QString chatSessionId = "";	  		// 会话编号
    QString chatSessionName = "";		// 会话名字, 如果会话是单聊, 名字就是对方的昵称; 如果是群聊, 名字就是群聊的名称.
    Message lastMessage;				// 表示最新的消息.
    QIcon avatar;						// 会话头像. 如果会话是单聊, 头像就是对方的头像; 如果是群聊, 头像群聊的头像.
    QString userId = "";				// 对于单聊来说, 表示对方的用户 id, 对于群聊设为 ""
};

} //end model

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/982393.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

针对半导体行业招聘系统有哪些?

近年来&#xff0c;全球半导体产业迎来爆发式增长&#xff0c;芯片设计、制造、封装等环节对高技能人才的需求急剧攀升。然而&#xff0c;行业面临多重挑战&#xff1a;技术迭代快导致岗位要求动态变化、优质人才争夺激烈、传统招聘模式效率低下。以某头部半导体企业为例&#…

汽车智能钥匙中PKE低频天线的作用

PKE&#xff08;Passive Keyless Entry&#xff09;即被动式无钥匙进入系统&#xff0c;汽车智能钥匙中PKE低频天线在现代汽车的智能功能和安全保障方面发挥着关键作用&#xff0c;以下是其具体作用&#xff1a; 信号交互与身份认证 低频信号接收&#xff1a;当车主靠近车辆时…

清华大学DeepSeek赋能家庭教育【附下载链接】

核心要点&#xff1a; DeepSeek通过基础模型&#xff08;V3&#xff09;、深度思考模型&#xff08;R1&#xff09;及联网模型&#xff0c;为家庭教育提供分层支持&#xff1a;V3用于作业辅导&#xff0c;R1培养批判性思维&#xff0c;联网模型助力探究性学习。家长需遵循目标导…

是德科技十周年:以创新丈量未来,用科技赋能世界

是德科技成立十周年&#xff0c;以全球测试测量领域领军者的姿态&#xff0c;书写了一部突破与创新的发展史诗。作为从惠普、安捷伦深厚技术积淀中孕育而生的行业标杆&#xff0c;十年来是德科技始终站在科技浪潮之巅&#xff0c;构建起覆盖5G通信、人工智能、汽车电子、量子计…

Springboot 梳理

一、Springboot 特性 方便创建可独立运行的spring应用程序直接内嵌Tomcat等服务简化了项目的构建配置为spring及第三方库提供自动配置提供生产级特性无需生成代码或者进行xml配置 二、四大核心 自动配置起步依赖命令行界面Actuator - 生成级的特性 三、自动配置的实现原理 …

unity console日志双击响应事件扩展

1 对于项目中一些比较长的日志&#xff0c;比如前后端交互协议具体数据等&#xff0c;这些日志内容可能会比较长&#xff0c;在unity控制面板上查看不是十分方便&#xff0c;我们可以对双击事件进行扩展&#xff0c;将日志保存到一个文本中&#xff0c;然后用系统默认的文本查看…

GPIO相关寄存器

共七种寄存器用于控制GPIO GPIOx_CRL&#xff08;常用&#xff09; GPIOx_CRH&#xff08;常用&#xff09; GPIOx_IDR&#xff08;常用&#xff09; GPIOx_ODR&#xff08;常用&#xff09; GPIOx_BSRR&#xff08;常用&#xff09; GPIOx_BRR&#xff08;不常用&#x…

简单多状态 dp 问题(典型算法思想)—— OJ例题算法解析思路

目录 一、面试题 17.16. 按摩师 - 力扣&#xff08;LeetCode&#xff09; 算法代码&#xff1a; 代码思路解析&#xff1a; 问题分析&#xff1a; 动态规划定义&#xff1a; 状态转移方程&#xff1a; 初始化&#xff1a; 填表&#xff1a; 返回值&#xff1a; 优化空…

深度解码!清华大学第六弹《AIGC发展研究3.0版》

在Grok3与GPT-4.5相继发布之际&#xff0c;《AIGC发展研究3.0版》的重磅报告——这份长达200页的行业圣经&#xff0c;不仅预测了2025年AI技术爆发点&#xff0c;更将「天人合一」的东方智慧融入AI伦理建构&#xff0c;堪称数字时代的《道德经》。 文档&#xff1a;清华大学第…

基于Hadoop的热门旅游景点推荐数据分析与可视化系统(基于Django大数据技术的热门旅游景点数据分析与可视化)

基于Hadoop大数据技术的热门旅游景点推荐数据分析与可视化系统设计与实现&#xff08;基于大数据技术的Django热门旅游景点数据分析与可视化系统设计与实现&#xff09; 1. 开发工具和实现技术 Pycharm, Python3.7&#xff0c;Django框架&#xff0c;Hadoop&#xff0c;Spark…

bert模型笔记

1.各预训练模型说明 BERT模型在英文数据集上提供了两种大小的模型&#xff0c;Base和Large。Uncased是意味着输入的词都会转变成小写&#xff0c;cased是意味着输入的词会保存其大写&#xff08;在命名实体识别等项目上需要&#xff09;。Multilingual是支持多语言的&#xff0…

dify 工作流 迭代

测试工作流&#xff1b;输入 测试工作流&#xff1b;运行结果 迭代&#xff1b;item使用解构&#xff1b;解析出每个对象

加载Ubuntu配置(source /etc/profile)

source /etc/profile 加载Ubuntu配置 加载前 加载后 启动项目&#xff1a; 问题&#xff1a; 当时安装JAVA非root账户

DeepSeek开源Day4:DualPipeEPLB技术详解

2 月 24 日&#xff0c;DeepSeek 启动 “开源周”&#xff0c;第四个开源的代码库为 DualPipe 与 EPLB&#xff08;一下发布了两个&#xff09;。DualPipe 与 EPLB 依然使用了大量与 Hopper 架构绑定的技术。 DualPipe 是由 DeepSeek-AI 团队开发的一种双向流水线并行通信算法&…

【计算机网络入门】初学计算机网络(九)

目录 1.令牌传递协议 2. 局域网&IEEE802 2.1 局域网基本概念和体系结构 3. 以太网&IEEE802.3 3.1 MAC层标准 3.1.1 以太网V2标准 ​编辑 3.2 单播广播 3.3 冲突域广播域 4. 虚拟局域网VLAN 1.令牌传递协议 先回顾一下令牌环网技术&#xff0c;多个主机形成…

数据结构 常见的排序算法

&#x1f33b;个人主页&#xff1a;路飞雪吖~ &#x1f320;专栏&#xff1a;数据结构 目录 &#x1f33b;个人主页&#xff1a;路飞雪吖~ 一、插入排序 &#x1f31f;直接插入排序 &#x1f31f;希尔排序 二、选择排序 &#x1f31f;选择排序 &#x1f31f;堆排序…

vscode离线配置远程服务器

目录 一、前提 二、方法 2.1 查看vscode的commit_id 2.2 下载linux服务器安装包 2.3 安装包上传到远程服务器&#xff0c;并进行文件解压缩 三、常见错误 Failed to set up socket for dynamic port forward to remote port&#xff08;vscode报错解决方法&#xff09;-C…

洛谷 P1480 A/B Problem(高精度详解)c++

题目链接&#xff1a;P1480 A/B Problem - 洛谷 1.题目分析 1&#xff1a;说明这里是高精度除以低精度的形式&#xff0c;为什么不是高精度除以高精度的形式&#xff0c;是因为它很少见&#xff0c;它的模拟方式是用高精度减法来做的&#xff0c;并不能用小学列竖式的方法模拟…

SpringMVC学习(controller层加载控制与(业务、功能)bean加载控制、Web容器初始化配置类)(3)

目录 一、SpringMVC、Spring的bean加载控制。 &#xff08;1&#xff09;实际开发的包结构层次。 &#xff08;2&#xff09;如何"精准"控制两个容器分别加载各自bean。(分析) <1>SpringMVC相关bean加载控制。(方法) <2>Spring相关bean加载控制。(方法) …

R的安装以及jupyter配置windows

今天&#xff0c;跟大家分享一下R的安装以及jupyter的配置 首先&#xff0c;我们去R的官网&#xff0c;打开进入下图web页面&#xff1a; 点击download R: 进入清华园镜像&#xff0c;根据系统来选择下载对应的R&#xff1a; 我这里用的Windows&#xff0c;就以windows为例…