1 Star 8 Fork 2

UNSTOPPABLE/ 毕设大作业基于qt5开发的局域网聊天软件

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
mainwindow.cpp 14.13 KB
一键复制 编辑 原始数据 按行查看 历史
UNSTOPPABLE 提交于 2022-08-19 16:11 +08:00 . 首次提交
#include "contactinfo.h"
#include "mainwindow.h"
#include "talkui.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QHostInfo>
#include <QDateTime>
#include <QDir>
#include <QNetworkInterface>
#include <QTextCodec>
#include <QDebug>
#include<QCloseEvent>
#include<QScreen>
#include<QPixmap>
#include<QClipboard>
#include<QDesktopWidget>
#include <QDesktopServices>
#include <QTimer>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 初始化 获取本机ip,mac
QDir dir;
sourceHostUserName= dir.home().dirName();
sourceHostName= QHostInfo::localHostName();
sourceMac= getHostMacAddress();
sourceIp=getHostIpAddress(sourceHostName);
sqlUtil=new SqlUtil();
// 显示时间
QTime curtime=QTime::currentTime();
QString strtm=curtime.toString("hh:mm:ss");
ui->myLcdNumber->display(strtm);
QTimer *timer1=new QTimer();
connect(timer1,&QTimer::timeout,[=](){
ui->myLcdNumber->display(curtime.currentTime().toString("hh:mm:ss"));
});
timer1->start(1000);
// 设置默认UI样式
TalkUI::setPushTextButtonQss(ui->talkTabBtn);
TalkUI::setPushTextButtonQss(ui->talkOptionBtn);
TalkUI::setPushTextButtonQss(ui->aboutTabBtn);
TalkUI::setPushTextButtonQss(ui->setTabBtn);
TalkUI::setPushButtonQss(ui->sendMsgBtn);
TalkUI::setPushTextButtonQss(ui->emptyBtn);
contactList = new ContactList();
TalkUI::setContactListQss(contactList);
ui->contactListWrap->addWidget(contactList);
talkMsgList = new TalkMsgList();
talkMsgList->setViewMode(QListView::ListMode);
talkMsgList->setFlow(QListView::TopToBottom);
TalkUI::setTalkMsgListQss(talkMsgList);
ui->talkMsgListWrap->addWidget(talkMsgList);
// 默认隐藏会话界面
ui->talkBoxEmpty->setVisible(true);
ui->talkBox->setVisible(false);
// 联系人列表项点击切换时,清空当前会话,获取当前切换到的联系人的消息历史记录,更新到视图
connect(contactList,&ContactList::contactItemClick,this,[this](ContactInfo *contactInfo){
if(curContact!=nullptr&&contactInfo->sourceMac==curContact->sourceMac){
return;
}
// 更新当前会话界面的用户信息
curContact=contactInfo;
ui->nickName->setText(contactInfo->sourceHostUserName);
// 清空当前会话
talkMsgList->clear();
// 显示会话视图
ui->talkBoxEmpty->setVisible(false);
ui->talkBox->setVisible(true);
// 获取当前切换到的联系人的消息历史记录,更新到视图
QList<ContactInfo*> *myTalkList=sqlUtil->talkRecordListByContactMac(contactInfo);
if(myTalkList!=nullptr){
for(int i=0;i<myTalkList->size();i++){
ContactInfo *item=myTalkList->value(i);
if(item->sourceMac==MainWindow::sourceMac){
item->sourceHostUserName=this->sourceHostUserName;
}else {
item->sourceHostUserName=curContact->sourceHostUserName;
}
talkMsgList->slotAddMsg(item,item->sourceMac==MainWindow::sourceMac);
}
}
});
connect(sqlUtil,&SqlUtil::initSuccess,this,[this](){
// 数据打开成功,加载用户列表
QList<ContactInfo*> *myContactList=sqlUtil->contactList();
if(myContactList!=nullptr){
for(int i=0;i<myContactList->size();i++){
ContactInfo *item=myContactList->value(i);
contactList->slotAddContact(item,item->sourceMac==MainWindow::sourceMac);
}
}
});
// 打开db前先绑定信号,否则接收不到
sqlUtil->openDb();
// 聊天主窗口显示,开始创建套接字通信对象
mSocket=new QUdpSocket(this);
// 开始绑定本机端口号2425
bool isBindPort=mSocket->bind(sourcePort);
if(isBindPort){
// 绑定成功
// 向广播地址发送本机上线通知
MainWindow::reportOnline();
// 开始监听收到的消息
connect(mSocket,&QUdpSocket::readyRead,this,[this](){
receiveHandle();
});
}else {
// 绑定失败
QMessageBox::warning(this,"提示","端口绑定失败,请重启软件!");
}
}
//发送按钮点击事件
void MainWindow::on_sendMsgBtn_clicked()
{
if(curContact!=nullptr){
QString sendMsg= ui->msgInput->toPlainText();
if(sendMsg==""){
// QMessageBox::warning(this,"提示","请输入内容");
return;
}
ContactInfo *contactInfo=new ContactInfo;
QString redayMsg= buildFormatMsg(MsgProtocol::Xfg,MsgTypeCode::SendMsg,sendMsg,contactInfo);
sendHandle(redayMsg,QHostAddress(curContact->sourceIp));
ui->msgInput->clear();
if(curContact->sourceMac!=MainWindow::sourceMac){
contactInfo->ContactMac=curContact->sourceMac;
sqlUtil->addMsg(contactInfo);
talkMsgList->slotAddMsg(contactInfo,contactInfo->sourceMac==MainWindow::sourceMac);
}
qDebug()<<"发送了一条消息,接收方:"<<curContact->sourceIp;
}else {
QMessageBox::warning(this,"提示","请选择联系人");
}
}
void MainWindow::playNewMsgSound()
{
QSound::play(":/sound/ring1.wav");
}
//广播上线通知
void MainWindow::reportOnline()
{
qDebug()<<"---开始广播上线通知---";
QString redayMsg= buildFormatMsg(MsgProtocol::Xfg,MsgTypeCode::Online);
sendHandle(redayMsg,QHostAddress::Broadcast);
}
//构建发送的数据包格式
QString MainWindow::buildFormatMsg(MsgProtocol msgProtocol,MsgTypeCode msgTypeCode,QString msg,ContactInfo *contactInfo){
// QString destIp="255.255.255.255"; //当前网段广播地址
QString curTime=QString::number(QDateTime::currentDateTime().toTime_t());
//数据包前缀格式:version:package#sourceMac#curTime:sourceHostUserName:sourceHostName:msgTypeCode:
QString prefix="%1:%2:%3:%4:%5:";
QString readyMsg=prefix.arg(version).arg(package+"#"+sourceMac+"#"+curTime).arg(sourceHostUserName).arg(sourceHostName).arg(msgTypeCode);
if(contactInfo!=nullptr){
contactInfo->version=version;
contactInfo->packageNo=package;
contactInfo->sourceMac=sourceMac;
contactInfo->timeStamp=curTime;
contactInfo->sourceHostUserName=sourceHostUserName;
contactInfo->sourceHostName=sourceHostName;
contactInfo->msgTypeCode=msgTypeCode;
contactInfo->msgPayLoad=msg;
contactInfo->sourceIp=sourceIp;
}
switch (msgTypeCode)
{
case MsgTypeCode::Online:{
readyMsg=readyMsg+"";
break;
}
case MsgTypeCode::AnsOnline:{
readyMsg=readyMsg+"";
break;
}
case MsgTypeCode::Offline:{
readyMsg=readyMsg+"";
break;
}
case MsgTypeCode::SendMsg:{
readyMsg=readyMsg+msg;
break;
}
default:{
break;
}
}
return readyMsg;
}
//关闭程序事件
void MainWindow::closeEvent(QCloseEvent *event){
QMessageBox msgBox;
int ret = msgBox.question(this,"警告","确认退出程序?",QMessageBox::Ok | QMessageBox::Cancel,QMessageBox::Ok);
if(ret == QMessageBox::Ok){
//窗口关闭
//向广播地址发送本机离线通知
QString redayMsg= buildFormatMsg(MsgProtocol::Xfg,MsgTypeCode::Offline);
sendHandle(redayMsg,QHostAddress::Broadcast);
event->accept();
}else{
//忽略窗口关闭
event->ignore();
}
}
//发送数据处理
void MainWindow::sendHandle(QString readyMsg,QHostAddress addr){
qDebug()<<"发送:"<<readyMsg;
QTextCodec *tc = QTextCodec::codecForName("GBK");
mSocket->writeDatagram(tc->fromUnicode(readyMsg),addr,destPort);
}
//接收数据处理
void MainWindow::receiveHandle(){
char msg[1024]={0};
QHostAddress ipAddress; //源ip地址
mSocket->readDatagram(msg,sizeof msg,&ipAddress);
QString sourceIp=ipAddress.toString().replace("::ffff:","");
QTextCodec *tc = QTextCodec::codecForName("GBK");
QString msgStr= tc->toUnicode(msg);
if(msgStr.contains("xfg")){
QStringList msgList=msgStr.split(":"); //版本号:包信息:用户名:主机名:命令编号:附加消息
qDebug()<<"收到:"<<msgList;
QString version=msgList[0];
QStringList package=msgList[1].split("#"); //包号#mac#时间戳
QString packageNo=package[0];
QString sourceMac=package[1];
QString timeStamp=package[2];
QString sourceHostUserName=msgList[2];
QString sourceHostName=msgList[3];
QString msgTypeCode=msgList[4];
QString msgPayLoad=msgList[5];
ContactInfo *contactInfo=new ContactInfo;
contactInfo->version=version;
contactInfo->packageNo=packageNo;
contactInfo->sourceMac=sourceMac;
contactInfo->timeStamp=timeStamp;
contactInfo->sourceHostUserName=sourceHostUserName;
contactInfo->sourceHostName=sourceHostName;
contactInfo->msgTypeCode=msgTypeCode;
contactInfo->msgPayLoad=msgPayLoad;
contactInfo->sourceIp=sourceIp;
contactInfo->ContactMac=sourceMac;
switch (msgTypeCode.toInt()) {
case MsgTypeCode::Online:{
// qDebug()<<"---有新上线好友---"<<sourceIp;
// 添加到好友列表
addToContactList(contactInfo);
//发送响应
QString redayMsg= buildFormatMsg(MsgProtocol::Xfg,MsgTypeCode::AnsOnline,"");
sendHandle(redayMsg,QHostAddress(sourceIp));
break;
}
case MsgTypeCode::AnsOnline:{
addToContactList(contactInfo);
break;
}
case MsgTypeCode::Offline:{
// qDebug()<<"---有好友下线---"<<sourceIp;
break;
}
case MsgTypeCode::SendMsg:{
// qDebug()<<"---有新消息---"<<sourceIp;
MainWindow::addMsgHandle(contactInfo);
break;
}
// case MsgTypeCode::GetPubKey:{
// break;
// }
// case MsgTypeCode::AnsPubKey:{
// QString redayMsg= buildFormatMsg(MsgProtocol::Xfg,MsgTypeCode::AnsPubKey);
// sendHandle(redayMsg,QHostAddress(curContact->sourceIp));
// break;
// }
default:{
break;
}
}
}
}
//获取主机ip地址
QString MainWindow::getHostIpAddress(QString hostName)
{
QHostInfo hostinfo = QHostInfo::fromName(hostName);
QString ipAddr="";
foreach(QHostAddress address,hostinfo.addresses())
{
if(address.protocol() == QAbstractSocket::IPv4Protocol)
{
ipAddr=address.toString();
}
}
return ipAddr;
}
//获取主机mac地址
QString MainWindow::getHostMacAddress()
{
QList<QNetworkInterface> ints = QNetworkInterface::allInterfaces();
int intsCount = ints.count();
QString macAddr="";
for(int i = 0; i < intsCount; i ++)
{
QNetworkInterface::InterfaceFlags intFlags= ints[i].flags();
if(intFlags.testFlag(QNetworkInterface::IsUp) && intFlags.testFlag(QNetworkInterface::IsRunning) && (!intFlags.testFlag(QNetworkInterface::IsLoopBack)))
{
macAddr=ints[i].hardwareAddress();
break;
}
}
return macAddr.replace(":","");
}
//1添加新用户到数据库,2更新用户列表显示
void MainWindow::addToContactList(ContactInfo *contactInfo){
// 根据mac地址查询当前新用户是否在数据库中已存在
if(sqlUtil->contactListByMacAddr(contactInfo)){
//已存在,更新该用户的信息到数据库
//更新到视图
//contactList->slotRefrechContact(contactInfo,contactInfo->sourceMac==MainWindow::sourceMac);
if(curContact!=nullptr&&contactInfo->sourceMac==curContact->sourceMac){
//该用户是当前打开的聊天会话的联系人,则同步更新curContact中的数据
curContact=contactInfo;
}else{
//该用户不是当前打开的聊天会话的联系人
}
}else{
//不存在,直接新增用户到数据库
sqlUtil->addContact(contactInfo);
//更新到视图
contactList->slotAddContact(contactInfo,false);
}
}
//1添加新消息到数据库,2直接追加新消息到聊天界面
void MainWindow::addMsgHandle(ContactInfo *contactInfo){
//根据mac地址判断当前接收到的新消息的是谁发的
if(sqlUtil->contactListByMacAddr(contactInfo)){
// 新消息的发送人在已有的联系人列表中,则直接添加到数据库
sqlUtil->addMsg(contactInfo);
if(curContact!=nullptr&&contactInfo->sourceMac==curContact->sourceMac){
//新消息的发送人是当前打开的聊天会话的联系人,则同步更新消息到聊天会话界面上显示
talkMsgList->slotAddMsg(contactInfo,contactInfo->sourceMac==MainWindow::sourceMac);
}else{
//新消息的发送人不是当前打开的聊天会话的联系人,在新用户头像上显示红点提示,声音提示
//contactList->showRedDot(contactInfo);
playNewMsgSound();
}
}else {
// 新消息的发送人在不在联系人列表中,先在数据库添加该新联系人,
sqlUtil->addContact(contactInfo);
//然后再将新消息添加到数据库
sqlUtil->addMsg(contactInfo);
//然后更新用户列表界面显示,在新用户头像上显示红点提示
contactList->slotAddContact(contactInfo,false);
//contactList->showRedDot(contactInfo);
playNewMsgSound();
}
}
MainWindow::~MainWindow()
{
delete ui;
}
//截图
void MainWindow::on_captureScreenBtn_clicked()
{
QDesktopWidget *desk = QApplication::desktop();
QScreen *screen = QGuiApplication::primaryScreen();
QPixmap pixmap = screen->grabWindow(desk->winId());
// QClipboard *clipboard = QApplication::clipboard();
// clipboard->setPixmap(pixmap);
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/UnStoppableeee/lan-chat-software-based-on-qt5.git
[email protected]:UnStoppableeee/lan-chat-software-based-on-qt5.git
UnStoppableeee
lan-chat-software-based-on-qt5
毕设大作业基于qt5开发的局域网聊天软件
master

搜索帮助