#pragma once #include #include #include #include #include #include #include #include "base.qpb.h" // 创建命名空间 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 LOG() qDebug().noquote() << TAG //避免链接阶段出现“函数重定义的问题” static inline QString formatTime(int64_t timestamp) { //先把时间戳转换为datetime对象 QDateTime datetime = QDateTime::fromSecsSinceEpoch(timestamp); //把datetime对象转化为格式化的时间 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 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) { qDebug() << "文件打开失败!!!"; 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) { qDebug() << "文件打开失败!!!"; return; } file.write(content); file.flush(); file.close(); } /////////////////////////// // 用户信息 /////////////////////////// class UserInfo { public: //初始化,避免一些随机值可能的负面影响 QString userId = ""; //用户编号 QString nickname = ""; //用户昵称 QString description = ""; //用户签名 QString phone = ""; //手机号码 QIcon avatar; //用户头像 //从protobuffer的UserInfo对象,转换为当前代码的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()); } } }; /////////////////////////// //消息信息 /////////////////////////// enum MessageType { TEXT_TYPE, //文本消息 IMAGE_TYPE, //图片消息 FILE_TYPE, //文件消息 SPEECH_TYPE //语音消息 }; class Message { public: QString messageId = ""; //消息的编号 QString chatSessionId = ""; //消息所属会话的编号 QString time = ""; //消息的时间,通过格式化的方式来表示 MessageType messageType = TEXT_TYPE; //消息类型 UserInfo sender; //发送者信息 QByteArray content; //消息的正文内容 QString fileId = ""; //文件的身份标识,当为文件,图片,语音,视频有效,当为文本则为"" QString fileName = ""; //文件名称 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(); } } void load(const 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; } } } private: static QString makeId() { //Uuid这东西背后也是一套算法,能够生成“全球唯一的身份标识” //Qt对UUID也有封装 //{75eb37e5-5af5-4bfb-8d0e-5261038a9107}(16进制的整数) return "M" + QUuid::createUuid().toString().mid(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; //后续使用时再进一步进行设置 message.fileId = ""; //此处并不使用,设置为"" 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; //后续使用时再进一步进行设置 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; //后续使用时再进一步进行设置 message.fileId = ""; //此处并不使用,设置为"" message.fileName = ""; return message; } }; /////////////////////////// //会话信息 /////////////////////////// class ChatSessionInfo { public: QString chatSessionId = ""; //会话编号 QString chatSessionName = ""; //会话名字(单聊或群聊) Message lastMessage; //表示会话的最新消息 QIcon avatar; //会话的头像(单聊或群聊) QString userId = ""; //(单聊为对方的id,群聊为"") 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"); } } } }; } //end namespace model