一个基于qt的桌面聊天系统的学习笔记(1)-邮件模块(1)邮件界面的初始化流程

邮件客户端:
一.初始化邮件主界面(在IMMailCtrl中定义)时,会在构造函数中初始化邮件通信控制类(在IMMailCtrl中定义),而IMMailCtrl类的构造函数会初始化IMTcpSocket(在IMTcpSocket中定义),并且连接IMTcpSocket和IMMailCtrl的信号与槽

IMMailWidget::IMMailWidget(const QString &myID, QWidget *parent)
  : m_myID(myID), QWidget(parent)
{
  m_mailCtrl = new IMMailCtrl(myID, this);
}
IMMailCtrl::IMMailCtrl(const QString & id, QObject *parent) :
    m_myID(id), QObject(parent)
{
    m_tcpSocket = new IMTcpSocket(this);
    m_tcpSocket->setFlag(1);
    m_tcpSocket->requestConnect();
    connect(m_tcpSocket, SIGNAL(connected()), this, SLOT(requestGetInMails()));
    connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(readMessage()));
}

二.当IMTcpSocket连接上时,调用IMMailCtrl的槽函数requestGetInMails,requestGetInMails函数通过IMTcpSocket将信息类型设置为GET_IN_MAIL 发送给服务器

void IMMailCtrl::requestGetInMails()
{
    qDebug() << "request in mails";
    if (NULL == m_tcpSocket)
        return;
    m_blockSize = 0;
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
   // out.setVersion(QDataStream::Qt_4_8);
    out << quint16(0) << int(GET_IN_MAILS) << m_myID;
    out.device()->seek(0);
    out << quint16(block.size() - sizeof(quint16));
    m_tcpSocket->write(block);
}

服务器端:
一.服务器用于控制客户端socket的类(在IMClientSocketCtrl中定义)的构造函数中连接了socket的信号和槽,当客户端的连接到达时,调用receiveMessage槽函数

IMClientSocketCtrl::IMClientSocketCtrl(QObject *parent)
    :QTcpSocket(parent)
{
    connect(this, &IMClientSocketCtrl::readyRead,
            this, &IMClientSocketCtrl::receiveMessage);
    connect(this, &IMClientSocketCtrl::disconnected,
            this, &IMClientSocketCtrl::deleteScoket);

    m_blockSize = 0;
    m_save.m_clientSocket = this;
}

二.receiveMessage函数识别到GET_IN_MAILS消息类型,发出sendSignal信号

void IMClientSocketCtrl::receiveMessage()
{
    QDataStream in(this);
    //设置QDataStream的版本,这里先省略
    if(m_blockSize == 0)
        {
            if(bytesAvailable() < (int)sizeof(quint16))
                {
                    return;
                }
            in >> m_blockSize;
        }

    if(bytesAvailable() < m_blockSize)
        {
            return;
        }
    in >> m_save.m_requestKind;

    qDebug() << "receive message: " << m_save.m_requestKind;

    switch (m_save.m_requestKind) 
    {
        case GET_IN_MAILS:
        case GET_OUT_MAILS:
        {
            in >> m_save.m_myID;
            m_save.m_socketID = m_save.m_myID;
            m_save.m_socketID.append(MAIL_ADDRESS_FORMAT);
            break;
        }
    }
    emit sendSignal(m_save);
    }

三.服务器类(在IMTcpServer中定义)捕获到这个信号,并调用sendMessage槽函数

void IMTcpServer::incomingConnection(int socketDescriptor)
{
  //建立新连接,并连接相应的信号/槽
  IMClientSocketCtrl *clientScoket = new IMClientSocketCtrl(this);
  clientScoket->setSocketDescriptor(socketDescriptor);
  connect(clientScoket, &IMClientSocketCtrl::sendSignal,
          this, &IMTcpServer::sendMessage);
  connect(clientScoket, &IMClientSocketCtrl::deleteSignal,
          this, &IMTcpServer::clientDisconnected);
}

四.sendMessage函数识别到GET_IN_MAILS消息类型,通过数据库操作类(在IMDatabaseCtrl中定义)的searchInMails函数查询客户的收件箱记录,如果成功则返回消息类型GET_IN_MAILS_SUCCESS,并将收信箱信息存储在Vector中。然后向客户端发送查询到的收件箱信息以及消息类型

void IMTcpServer::sendMessage(const SaveTmpInformation &save)
{
  m_save.m_requestKind = save.m_requestKind;
  //根据save.request来处理各种信息
  switch (m_save.m_requestKind) {
     case GET_IN_MAILS:
      {
        m_save.m_myID = save.m_myID;
        m_save.m_replyKind = m_database.searchInMails(m_save.m_myID, m_save.m_inMailsVec);
        save.m_clientSocket->sendMessage(m_save);
        if(GET_IN_MAILS_SUCCESS == m_save.m_replyKind)
          {
            QString mailAddress = save.m_myID;
            mailAddress.append(MAIL_ADDRESS_FORMAT);
            if(m_userMailMap.contains(mailAddress))
              {
                qDebug() << "have connected:" << mailAddress;
              }
            else
              {
                m_userMailMap.insert(mailAddress, save.m_clientSocket);
                emit haveNewAddress(mailAddress);
              }
          }
        break;
      }
    }
  }
int IMDatabaseCtrl::searchInMails(const QString & id,
                                  QVector<MailInformation> & mailsVec)
{
    if (!createConnection())
    {
        return GET_IN_MAILS_FAIL;
    }
    //sql 事务
    QSqlDatabase::database().transaction();

    QSqlQuery query(*m_db);
    query.prepare(SEARCH_IN_MAILS_IN_MAIL);
    query.addBindValue(id);
    query.addBindValue(MAIL_ADDRESS_FORMAT);
    query.exec();
    errorSQLOrder(query, "get-mails-search");

    QSqlDatabase::database().commit();

    if (!query.isActive())
    {
        m_db->close();
        return GET_IN_MAILS_FAIL;
    }

    mailsVec.clear();
    MailInformation mail;
    while (query.next())
    {
        mail.m_mailID = query.value(0).toInt();
        mail.m_senderAddress = query.value(1).toString();
//        mail. = query.value(2).toString();
        mail.m_receiverAddress = query.value(3).toString();
//        mail. = query.value(4).toString();
        mail.m_theme = query.value(5).toString();
        mail.m_content = query.value(6).toString();
        mail.m_dateTime = query.value(7).toDateTime();
        mail.m_status = query.value(8).toInt();

        mailsVec.push_back(mail);
    }

    return GET_IN_MAILS_SUCCESS;
}

邮件客户端:
一.客户端的邮件通信控制类(在IMMailCtrl中定义)中的客户端tcpsocket类(在IMTcoSocket中定义)接收到可以读的信号,调用槽函数readMessage函数进行处理

IMMailCtrl::IMMailCtrl(const QString & id, QObject *parent) :
    m_myID(id), QObject(parent)
{
    m_tcpSocket = new IMTcpSocket(this);
    m_tcpSocket->setFlag(1);
    m_tcpSocket->requestConnect();
    connect(m_tcpSocket, SIGNAL(connected()), this, SLOT(requestGetInMails()));
    connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(readMessage()));
}

二.readMessage函数识别到消息类型为GET_IN_MAILS_SUCCESS,读取收信箱信息到Vector,发出getInMailsSuccess信号

void IMMailCtrl::readMessage()
{
    if (NULL == m_tcpSocket)
        return;
    QDataStream in(m_tcpSocket);

    if (m_blockSize == 0)
    {
        if (m_tcpSocket->bytesAvailable() < (int)sizeof(quint16))
            return;
        in >> m_blockSize;
    }

    if (m_tcpSocket->bytesAvailable() < m_blockSize)
        return;
    int type;
    int len;
    in >> type;

    switch (type)
    {
    case GET_IN_MAILS_SUCCESS:
    {
        in >> len;
        m_inMailsVec.clear();
        m_inMailsVec.resize(len);
        for(int i=0; i<len; i++)
        {
            in >> m_inMailsVec[i];
        }
        qDebug() << "in mails len: " << len;
        emit getInMailsSuccess(m_inMailsVec);
        break;
    }
}

三.邮件主界面类(在IMMailWidget中定义)接收到信号,调用setInMailsWidget槽函数

void IMMailWidget::linkSignalWithSlot()
{
  connect(m_mailCtrl, &IMMailCtrl::getInMailsSuccess,
          this, &IMMailWidget::setInMailsWidget);
}

四.setInMailsWidget函数设置收信箱窗口,并调用邮件通信控制类(在IMMailCtrl中定义)的requestGetOutMails方法

void IMMailWidget::setInMailsWidget(const QVector<MailInformation> &inMailsVec)
{
  int len = inMailsVec.size();
  for(int i = 0; i < len; i ++)
    {
      addInMailButton(inMailsVec[i]);
    }
  m_mailCtrl->requestGetOutMails();
}

五.requestGetOutMails函数向服务器发送请求获取发件箱信息,接下来的过程与获取收信箱过程类似,就省略了。

void IMMailCtrl::requestGetInMails()
{
    qDebug() << "request in mails";
    if (NULL == m_tcpSocket)
        return;
    m_blockSize = 0;
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
   // out.setVersion(QDataStream::Qt_4_8);
    out << quint16(0) << int(GET_IN_MAILS) << m_myID;
    out.device()->seek(0);
    out << quint16(block.size() - sizeof(quint16));
    m_tcpSocket->write(block);
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值