个人信息修改头像
前言
上一集我们就完成了修改手机号的内容。当然我们只完成了显性的修改内容,我们还有一个隐性的修改内容,那就是我们修改头像的内容。
需求分析
我们先来看到我们的个人信息页面。
当我们点击我们目前的头像的时候应该弹出一个选择头像路径的窗口
我们只允许选择Image Files的文件,我们选择了一个文件之后,我们就可以永久修改我们的头像了。
我们不仅要修改我们目前的个人信息的窗口上的内容,还要修改主窗口的头像显示以及会话中我们个人发出信息的头像。
那么我们还是来看一眼我们的URL和http的请求响应的定义。
这就是我们此次http请求所使用的URL。
这就是我们此次用户头像修改的http请求和响应的定义。那么就赶紧开始我们代码的编写吧。
客户端
我们的第一步还是要先给我们的头像的这个按钮连接一个信号槽!
connect(avatarBtn, &QPushButton::clicked, this, &SelfInfoWidget::clickAvatarBtn);
然后就会进入一个函数,这个函数我们要实现的功能其实很简单。
首先我们要弹出一个对话框用于选择图片文件,我们选择了文件,就可以通过路径读取我们的图片的内容,之后就可以进入到我们的发送请求的动作了!
当然我们还是要通过DataCenter来传递一些参数。
当然我们在这个位置发送了请求,我们也应该在这里接收一下响应处理那边发送的信号,之后触发我们更新头像的功能,也就是更新界面!
void SelfInfoWidget::clickAvatarBtn()
{
//弹出对话框,选择文件
QString filter = "Image Files(*.png *.jpg *.jpeg)";
QString imagePath = QFileDialog::getOpenFileName(this, "选择头像", QDir::homePath(), filter);
if(imagePath.isEmpty()){
//用户取消了
LOG() << "用户未选择任何头像";
return;
}
//根据路径,读取图片内容
QByteArray imageBytes = loadFileToByteArray(imagePath);
//发送请求
DataCenter* dataCenter = DataCenter::getInstance();
connect(dataCenter, &DataCenter::changeAvatarDone, this, &SelfInfoWidget::clickAvatarBtnDone, Qt::UniqueConnection);
dataCenter->changeAvatarAsync(imageBytes);
}
我们还是通过DataCenter传递loginSessionId给我们的NetClient。
void DataCenter::changeAvatarAsync(const QByteArray &imageBytes)
{
netClient.changeAvatar(loginSessionId, imageBytes);
}
之后就是到NetClient那边进行构造http请求,发送请求和处理响应部分。
void NetClient::changeAvatar(const QString &loginSessionId, const QByteArray &avatar)
{
//构造http请求body
bite_im::SetUserAvatarReq pbReq;
pbReq.setRequestId(makeRequestId());
pbReq.setSessionId(loginSessionId);
pbReq.setAvatar(avatar);
QByteArray body = pbReq.serialize(&serializer);
LOG() << "[修改头像] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << pbReq.sessionId();
//发送http请求
QNetworkReply* resp = this->sendHttpRequest("/service/user/set_avatar", body);
//处理响应
connect(resp, &QNetworkReply::finished, this, [=](){
bool ok = false;
QString reason;
auto pbResp = this->handleHttpResponse<bite_im::SetUserAvatarRsp>(resp, &ok, &reason);
//判定是否出错
if(!ok){
LOG() << "[修改头像]失败!reason=" << reason;
return;
}
//设置数据到DataCenter
dataCenter->resetAvatar(avatar);
//发送信号,通知调用
emit dataCenter->changeAvatarDone();
LOG() << "[修改头像] 处理响应完毕! requestId=" << pbResp->requestId();
});
}
构造http的body也就是按照我们之前proto文件定义的内容来写即可,之后发送请求也是我们之前封装的一个函数,处理响应这边也是非常的常规,我们只需要看我们发回来的响应的ok以及reason的内容。如果没有出错,我们就可以将数据设置到我们的DataCenter当中的myself当中。然后就可以通知我们的界面进行更新。
这个resetAvatar函数也是十分的简单,我们只需要判断一下我们的myself是否为空,如果不是空的,我们就直接把avatar设置到我们的myself中,当然还得借助我们之前封装的QByteArray转成QIcon的工具函数才可成功设置。
void DataCenter::resetAvatar(const QByteArray &avatar)
{
if(myself == nullptr){
return;
}
myself->avatar = makeIcon(avatar);
}
之后就发送了信号给我们的信号槽,我们这个信号槽一定要记得设置Qt::UniqueConnection!
在个人信息窗口当中,我们的信号槽连接如下:
connect(dataCenter, &DataCenter::changeAvatarDone, this, &SelfInfoWidget::clickAvatarBtnDone, Qt::UniqueConnection);
触发里面的函数即可。这个函数也是十分的简单,只需要将DataCenter里面的myself里的avatar的值设置到我们该界面的avatarBtn即可。
void SelfInfoWidget::clickAvatarBtnDone()
{
//更新到界面上
DataCenter* dataCenter = DataCenter::getInstance();
avatarBtn->setIcon(dataCenter->getMyself()->avatar);
}
但是!这就完了吗?
我们不要忘了我们需求分析中,还需要将我们的主界面的左侧区域的用户头像还有每一个会话里面,我们发送的消息也进行头像上的修改。
那么我们只需要在主界面的初始化信号槽函数里面添加以下代码即可。
connect(dataCenter, &DataCenter::changeAvatarDone, this, [=](){
UserInfo* myself = dataCenter->getMyself();
userAvatar->setIcon(myself->avatar);
});
这样只要发送了changeAvatarDone的信号就可以自动修改我们的主界面的头像。
那么修改个人发送的消息也是很简单,和之前修改了名称的功能是一样的。我们只针对自己发送的消息!
if(!isLeft){
//用户修改了昵称,同步修改此处的用户名称(只针对自己的消息)
DataCenter* dataCenter = DataCenter::getInstance();
connect(dataCenter, &DataCenter::changeNicknameDone, messageItem, [=](){
nameLabel->setText(dataCenter->getMyself()->nickname + " | " + message.time);
});
//用户修改了头像,同步修改此处的用户头像(只针对自己的消息)
connect(dataCenter, &DataCenter::changeAvatarDone, messageItem, [=](){
UserInfo* myself = dataCenter->getMyself();
avatarBtn->setIcon(myself->avatar);
});
}
这里就可以看到,如果消息是我们自己发送的,就会连接这个信号槽!
那么到这里我们客户端方面的内容就是彻底的完成了!
测试服务端
我们也是那几个步骤
第一步,配置我们http请求的路由,并分发给我们封装的函数。
httpServer.route("/service/user/set_avatar", [=](const QHttpServerRequest& req){
return this->setAvatar(req);
});
第二步,就是我们解析http请求、构造http响应。
QHttpServerResponse HttpServer::setAvatar(const QHttpServerRequest &req)
{
//解析请求
bite_im::SetUserAvatarReq pbReq;
pbReq.deserialize(&serializer, req.body());
LOG() << "[REQ 修改手机号] requestId=" << pbReq.requestId() << ", loginSessionId=" << pbReq.sessionId();
//构造响应
bite_im::SetUserAvatarRsp pbResp;
pbResp.setRequestId(pbReq.requestId());
pbResp.setSuccess(true);
pbResp.setErrmsg("");
QByteArray body = pbResp.serialize(&serializer);
//构造http响应
QHttpServerResponse resp(body, QHttpServerResponse::StatusCode::Ok);
resp.setHeader("Content-Type", "application/x-protobuf");
return resp;
}
这里,我们就完成了修改头像的一整条链路。那么这一集就先到这里。