核心数据类型转换

核心数据类型转换

前言

前几集我们简单做了三条我们前后端交互接口的约定,简单看了我们的proto文件的内容,简单介绍了我们的Protobuf,并将protobuffer引入了我们的项目之中。

那么这一集我们就要把我们protobuffer的proto文件里的核心数据类型和Qt里的核心数据类型进行load转换!

需求分析

我们今天需要转换的核心数据类型就是proto文件里的UserInfo、ChatSessionInfo以及MessageInfo这三个核心数据类型。

包含proto的头文件

我们今天就要在我们的model/data.h里面添加以下内容。

#include "base.qpb.h"

简单说一下为什么要添加这一条代码

proto文件在我们Qt程序编译的时候,会把proto转换成cpp的代码。

转换的过程中,会生成同名的.h和.cc文件,这里的.cc文件其实就是.cpp文件。

我们的protobuffer官方包含头文件一般格式如下:

base.proto   --->    base.pb.h

但是我们进入到Qt中就要入乡随俗

base.proto   --->    base.qpb.h

可能有人发现了,我们添加了这一段东西进入我们的代码之中,会报错!下划线是红色的!


那么我们就需要先编译一遍这个程序,如果能够正常运行就是成功了的。如果没有运行成功,就请看上一集的内容。

如果成功运行,但是还是有红色的下划线,那么我们给他剪切一下重新粘贴上去即可。

这个时候下划线就可能变成黄色的了,那么我们就不需要管他了。我之前就是重新启动,黄色下划线就无了。

核心数据类型转换方法

那么我们也废话不多说,我们就开始今天的核心数据类型转换的方法的编写吧。

UserInfo

    void load(const bite_im::UserInfo& userInfo){this->userId = userInfo.userId();this->nickname = userInfo.nickname();this->phone = userInfo.phone();this->description = userInfo.description();if(userInfo.avatar().isEmpty()){//使用默认头像this->avatar = QIcon(":/resource/image/defaultAvatar.png");}else{this->avatar = makeIcon(userInfo.avatar());}}

这里可以看到我们的bite_im这个命名空间,这个命名空间是我们的proto文件里面的。

可以看到我们的命名空间。

但是我们发现我们的proto文件是没有我们的get和set方法啊,这个我们是不需要担心的,这些方法我们的protobuffer都会给每个属性自动生成。虽然我们的命名是以下划线为分割,我们的Qt代码是驼峰,也不需要担心,我们的Qt的protobuffer的生成的方法,都会自动生成驼峰命名。


我们其实可以看到我们的头像还需要去判断是否为空,因为我们新创建的用户是没有我们的头像的,服务器这边存储的avatar就是一个空的字节数组。

MessageInfo

我们的MessageInfo最关键的内容就是我们的不同的消息类型来设置不同的content和messageType以及fileId这种细节。

    void load(bite_im::MessageInfo& messageInfo){this->messageId = messageInfo.messageId();this->chatSessionId = messageInfo.chatSessionId();this->time = formatTime(messageInfo.timestamp());this->sender.load(messageInfo.sender());//消息类型auto type = messageInfo.message().messageType();if(type == bite_im::MessageTypeGadget::MessageType::STRING){this->messageType = TEXT_TYPE;this->content = messageInfo.message().stringMessage().content().toUtf8();}else if(type == bite_im::MessageTypeGadget::MessageType::IMAGE){this->messageType = IMAGE_TYPE;if(messageInfo.message().imageMessage().hasImageContent()){this->content = messageInfo.message().imageMessage().imageContent();}if(messageInfo.message().imageMessage().hasFileId()){this->fileId = messageInfo.message().imageMessage().fileId();}}else if(type == bite_im::MessageTypeGadget::MessageType::FILE){this->messageType = FILE_TYPE;if(messageInfo.message().fileMessage().hasFileContents()){this->content = messageInfo.message().fileMessage().fileContents();}if(messageInfo.message().fileMessage().hasFileId()){this->fileId = messageInfo.message().fileMessage().fileId();}this->fileName = messageInfo.message().fileMessage().fileName();}else if(type == bite_im::MessageTypeGadget::MessageType::SPEECH){this->messageType = SPEECH_TYPE;if(messageInfo.message().speechMessage().hasFileContents()){this->content = messageInfo.message().speechMessage().fileContents();}if(messageInfo.message().speechMessage().hasFileId()){this->fileId = messageInfo.message().speechMessage().fileId();}}else{//错误类型LOG() << "非法消息类型! type=" << type;}}

大家可能看着头疼,这个看起来也太乱了。

那么我们就对照着proto文件来写。

message StringMessageInfo {string content = 1;//文字聊天内容
}
message ImageMessageInfo {optional string file_id = 1;//图片文件id,客户端发送的时候不用设置,由transmit服务器进行设置后交给storage的时候设置optional bytes image_content = 2;//图片数据,在ES中存储消息的时候只要id不要文件数据, 服务端转发的时候需要原样转发
}
message FileMessageInfo {optional string file_id = 1;//文件id,客户端发送的时候不用设置int64 file_size = 2;//文件大小string file_name = 3;//文件名称optional bytes file_contents = 4;//文件数据,在ES中存储消息的时候只要id和元信息,不要文件数据, 服务端转发的时候也不需要填充
}
message SpeechMessageInfo {optional string file_id = 1;//语音文件id,客户端发送的时候不用设置optional bytes file_contents = 2;//文件数据,在ES中存储消息的时候只要id不要文件数据, 服务端转发的时候也不需要填充
}
message MessageContent {MessageType message_type = 1; //消息类型oneof msg_content {StringMessageInfo string_message = 2;//文字消息FileMessageInfo file_message = 3;//文件消息SpeechMessageInfo speech_message = 4;//语音消息ImageMessageInfo image_message = 5;//图片消息};
}

时间这个内容,就可以用到我们之前写到的工具函数formatTime

这代码中的MessageTypeGadget我们是不需要去管的!这个是protobuffer生成的内容。

我们的sender也是一个proto的一个类的对象,但是我们在前面的UserInfo里面也写了他的load方法,那么我们只需要调用load方法即可。


我们可以看到我们的图片信息的时候,我们的代码怎么还需要去看这个图片是否为空啊?怎么还要去看fileId啊?

因为我们的图片信息中,我们可能是直接携带图片的内容,也可能是图片的文件id。可以看到我们的proto文件当中,图像的content是一个optional修饰的变量。

ChatSessionInfo

     void load(bite_im::ChatSessionInfo& chatSessionInfo){this->chatSessionId = chatSessionInfo.chatSessionId();this->chatSessionName = chatSessionInfo.chatSessionName();if(chatSessionInfo.hasSingleChatFriendId()){this->userId = chatSessionInfo.singleChatFriendId();}if(chatSessionInfo.hasPrevMessage()){lastMessage.load(chatSessionInfo.prevMessage());}if(chatSessionInfo.hasAvatar() && !(chatSessionInfo.avatar().isEmpty())){this->avatar = makeIcon(chatSessionInfo.avatar());}else{//没有头像,考虑单聊还是群聊if(userId != ""){//单聊this->avatar = QIcon(":/resource/image/defaultAvatar.png");}else{//群聊this->avatar = QIcon(":/resource/image/groupAvatar.png");}}}

我们这里的做法还是和上面的基本一致。这里我们的上一条消息就是直接load一下即可。之后我们就要去讨论这个头像了。

我们的头像在proto是一个QByteArray,我们需要转换成QIcon,就要使用我们之前写的工具函数!

如果没有头像,我们就需要分类讨论了,这里也是比较巧妙,如果没有userId就是群聊,有的话就是单聊。

如果是群聊就是以下头像。

那么这一集我们就先到这里。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入学习指针(5)!!!!!!!!!!!!!!!

文章目录 1.回调函数是什么&#xff1f;2.qsort使用举例2.1使用qsort函数排序整形数据2.2使用sqort排序结构数据 3.qsort函数的模拟实现 1.回调函数是什么&#xff1f; 回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针&#xff08;地址&#xff09;作为参数传递…

MyBatis xml 文件中 SQL 语句的小于号未转义导致报错

问题现象 在 MyBatis 的 xml 文件中添加了一个 SQL 语句 <select id"countXxx" resultType"int">select count(*) from t1 where count < 3 </select>启动 Spring Boot 应用程序后报错&#xff1a; Caused by: org.apache.ibatis.builde…

测试-正交表与工具pairs的介绍使用(1)

目录 正交表 生成正交表 步骤 实操 注意事项 编写测试用例 根据正交表编写测试用例 补充遗漏的重要测试用例 正交表 关于长篇大论也不多介绍了&#xff0c;我们只需要知道正交法的⽬的是为了减少⽤例数⽬&#xff0c;⽤尽量少的⽤例覆盖输⼊的两两组合 正交表的构成&…

qt QErrorMessage详解

1、概述 QErrorMessage是Qt框架中用于显示错误消息的一个对话框类。它提供了一个简单的模态对话框&#xff0c;用于向用户显示错误或警告消息。QErrorMessage通常用于应用程序中&#xff0c;当需要向用户报告错误但不希望中断当前操作时。它提供了一个标准的错误消息界面&…

设计模式(主要的五种)

1.设计模式&#xff1a; 设计模式就是代码设计经验 2.设计模式的类型&#xff1a; 分为三大类&#xff1a;创建型模式&#xff0c;结构型模式&#xff0c;行为模式 创建型模式&#xff1a; 单例模式&#xff1a;某个类只能有一个实例&#xff0c;提供一个全局的访问点。 工…

ZABBIX API获取监控服务器OS层信息

Zabbix 是一款强大的开源监控解决方案,能够通过其 API 接口自动化管理和获取监控数据。在这篇文章中,详细讲解如何通过 Zabbix API 批量获取服务器的系统名称、IP 地址及操作系统版本信息,并将数据保存到 CSV 文件中。本文适合对 Python 编程和 Zabbix 监控系统有一定基础的…

医院信息化与智能化系统(18)

医院信息化与智能化系统(18) 这里只描述对应过程&#xff0c;和可能遇到的问题及解决办法以及对应的参考链接&#xff0c;并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图&#xff0c;可以试试PlantUML&#xff0c;告诉GPT你的文件结构&#xff0c;让他给你对应…

场景解决方案丨迎战电商大促,企业管理跟踪驾驶舱助力中小企业打赢决胜之战

该方案已沉淀为➡️订单物流信息跟踪模板&#xff0c;点击&#x1f517;即可体验 随着互联网技术的发展和市场经济的变化&#xff0c;各行业的线上竞争愈发激烈。一方面&#xff0c;互联网平台凭借便捷的服务和丰富的产品吸引了大量客户&#xff1b;另一方面&#xff0c;复杂多…

Python练习12

Python日常练习 题目&#xff1a; 试题文件夹下的文本文件sentences.txt中&#xff0c;每行对应一个句子&#xff0c;该句子包含了多个 单词&#xff0c;单词之间以空格隔开。每个单词仅包含英文字母。我们希望能够将文件中的 每个句子转换为“山羊语”。句子的每…

DeFi 4.0峥嵘初现:主权金融时代的来临

近年来&#xff0c;Web3领域的创新似乎遇到了瓶颈&#xff0c;DeFi&#xff08;去中心化金融&#xff09;从热潮的巅峰逐渐进入了一个沉寂期。我们再也没有见到像DeFi Summer那样的行业兴奋&#xff0c;资本市场的动荡和Meme币的出现&#xff0c;似乎让人们忘记了曾经的区块链技…

如何通过六个步骤保护 AI 生成的代码

可以通过执行静态应用程序安全测试、动态安全测试、软件组合分析、使用安全代码实践、实施安全控制以及培训开发人员安全最佳实践来保护 AI 生成的代码。 随着人工智能 (AI) 在软件开发中发挥着越来越重要的作用&#xff0c;优先考虑 AI 生成的代码的安全性至关重要。 与人类…

51单片机教程(七)- 蜂鸣器

1 项目分析 利用P2.3引脚输出电平变化&#xff0c;控制蜂鸣器的鸣叫。 2 技术准备 1 蜂鸣器介绍 有绿色电路板的一种是无源蜂鸣器&#xff0c;没有电路板而用黑胶封闭的一种是有源蜂鸣器。 有源蜂鸣器和无源蜂鸣器 这里的“源”不是指电源。而是指震荡源。也就是说有源蜂鸣…

LangChain实际应用

1、LangChain与RAG检索增强生成技术 LangChain是个开源框架&#xff0c;可以将大语言模型与本地数据源相结合&#xff0c;该框架目前以Python或JavaScript包的形式提供&#xff1b; 大语言模型&#xff1a;可以是GPT-4或HuggingFace的模型&#xff1b;本地数据源&#xff1a;…

java的面向对象(从入门到深入)

目录 一、基本概念&#xff1a; 1.类 2.对象 3.继承 4.多态 5.封装 6.方法 7.接口 8.抽象 二、深入概念&#xff1a; 三:总结 一、基本概念&#xff1a; 1.类 类就是一个一个东西的蓝图&#xff0c;里面有着它的属性和方法。 2.对象 对象是一个类的实例化。 3.继承…

基础数据结构——队列(链表实现)

队列的性质 先进先出&#xff08;FIFO - First In First Out&#xff09;&#xff1a;最先加入队列的元素最先被移出后进后出&#xff08;后来的元素排在队尾&#xff09;只允许在队尾插入元素&#xff0c;在队首删除元素具有先来先服务的特点 链表实现队列 和之前创建链表相…

单纯的查询而言,vector和map谁更快

单纯的查询而言&#xff0c;vector和map谁更快 文章目录 单纯的查询而言&#xff0c;vector和map谁更快一、vector的查询二、vector和map对比三、总结 一、vector的查询 这道题目需要知道vector查询和随机访问的不同。 假设有一个包含 n 个元素的vector集合&#xff0c;需要查…

大A终究是逃不过高开低走的魔咒

大A终究是逃不过高开低走的魔咒&#xff0c;早盘高开太多&#xff0c;周末休市&#xff0c;今天会议结束&#xff0c;各种不确定因素增加等原因导致午盘普跌。其实还是那句话&#xff0c;股市嘛&#xff0c;涨多了会跌&#xff0c;跌多了会涨&#xff0c;别急也别慌。 周末&…

Ceisum无人机巡检视频投放

公司投标内容有个视频投放的功能动画&#xff0c;原本想实现这么一个效果&#xff1a; 案例效果来自别人的展示作品&#xff0c;Leader一眼就相中了这个效果&#xff0c;可惜别人的终究是别人的&#xff0c;又不会白白给你&#xff0c;终究是要自己动手尝试。 动画方面的展示…

Rust闭包(能够捕获周围作用域变量的匿名函数,广泛应用于迭代、过滤和映射)闭包变量三种捕获方式:通过引用(不可变引用)、通过可变引用和通过值(取得所有权)

文章目录 Rust 闭包详解闭包的定义与语法基本语法 闭包的特性- 环境捕获&#xff08;三种捕获方式&#xff1a;通过引用、通过可变引用和通过值&#xff08;取得所有权&#xff09;&#xff09;示例代码 - 内存安全与生命周期示例代码1 示例代码2&#xff1a;闭包所有权转移示例…

【国内中间件厂商排名及四大中间件对比分析】

国内中间件厂商排名 随着新兴技术的涌入&#xff0c;一批国产中间件厂商破土而出&#xff0c;并在短时间内迅速发展&#xff0c;我国中间件市场迎来洗牌&#xff0c;根据市占率&#xff0c;当前我国中间件厂商排名依次为&#xff1a;东方通、宝兰德、中创股份、金蝶天燕、普元…