一个基于qt的桌面聊天系统的学习笔记(1)-邮件模块(2)收发信处理流程

写信:
一.在邮件编辑界面(在IMMailWriteWidget文件中定义)中编辑好信件,点击发送按钮,发出clicked信号
二.IMMailWriteWidget捕获到这个信号,调用槽函数onClickBtnSend


connect(m_btnSend, SIGNAL(clicked()),
            this, SLOT(onClickBtnSend()));

三.在槽函数onClickBtnSend中调用getMailInformation函数取得消息输入框的信息,再让邮件控制器类IMMailCtrl调用requestSendMail函数


void IMMailWriteWidget::onClickBtnSend()
{
    if (m_leReceiverAddress->text().isEmpty())
    {
        QMessageBox::about(NULL, tr("提示"), tr("收件人不能为空!"));
        return;
    }
    if (m_leReceiverAddress->text().compare(m_myID) == 0)
    {
        QMessageBox::about(NULL, tr("提示"), tr("不能给自己发送邮件!"));
        return;
    }
    if (m_leTheme->text().isEmpty())
    {
        QMessageBox::about(NULL, tr("提示"), tr("信件主题不能为空"));

        return;
    }
    if (m_textInput->toPlainText().isEmpty())
    {
        QMessageBox::about(NULL, tr("提示"), tr("信件内容不能为空!"));
        return;
    }

    // 获取信息输入框的信息
    getMailInformation();

    m_mailCtrl->requestSendMail(m_mail);
}

四.requestSendMail函数通过socket与服务器通信(并把消息类型标记为SEND_MAIL)


void IMMailCtrl::requestSendMail(const MailInformation &mail)
{
    qDebug() << "send mail: " << mail.m_theme;

    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(SEND_MAIL) << mail;
    out.device()->seek(0);
    out << quint16(block.size() - sizeof(quint16));
    m_tcpSocket->write(block);

}

服务器:
一.在客户端通信类(在IMClientSocket类中定义)的receiveMessage函数中识别到SEND_MAIL, 发出sendSignal信号


    connect(this, &IMClientSocketCtrl::readyRead,
            this, &IMClientSocketCtrl::receiveMessage);
    connect(this, &IMClientSocketCtrl::disconnected,
            this, &IMClientSocketCtrl::deleteScoket);

void IMClientSocketCtrl::receiveMessage()
{
    switch (m_save.m_requestKind)
    {
        case SEND_MAIL:
        { 
            in >> m_save.m_mail;
            break;
        }
    }
    emit sendSignal(m_save);
}

二.服务器类(在IMTcpServer类中定义)捕获到这个信号,调用sendMessage槽函数进行处理


 connect(clientScoket, &IMClientSocketCtrl::sendSignal,
          this, &IMTcpServer::sendMessage);
  connect(clientScoket, &IMClientSocketCtrl::deleteSignal,
          this, &IMTcpServer::clientDisconnected);

三.sendMessage识别到SEND_MAIL,通过操作数据库类(在IMDatabase中定义)往数据库中插入一条邮件记录,如果成功就返回SEND_MAIL_SUCCESS到relyKind,然后通过socket给发信方发送消息,告诉发信方信已成功发出。然后在服务器的邮箱用户表中找到收信人的socket, 把信件发送给收信人

int IMDatabaseCtrl::insertMail(MailInformation & mail)
{
    if (!createConnection())
    {
        return SEND_MAIL_FAIL;
    }
    //sql 事务
    QSqlDatabase::database().transaction();

    QSqlQuery query(*m_db);
    query.prepare(INSERT_MAIL_IN_MAIL);
    query.addBindValue(mail.m_senderAddress);
    query.addBindValue(MAIL_ADDRESS_FORMAT);
    query.addBindValue(mail.m_receiverAddress);
    query.addBindValue(MAIL_ADDRESS_FORMAT);
    query.addBindValue(mail.m_theme);
    query.addBindValue(mail.m_content);
    query.addBindValue(mail.m_dateTime);
    query.exec();

    errorSQLOrder(query, "insert-mail");
    if (!query.isActive())
    {
        qDebug() << "QUERY_FAIL::" << query.lastError().text();
        m_db->close();
        return SEND_MAIL_FAIL;
    }

    if (0 >= query.numRowsAffected())
    {
        return SEND_MAIL_FAIL;
    }
    QSqlDatabase::database().commit();

    query.exec("select LAST_INSERT_ID() from Mail");
    if (query.next())
    {
        mail.m_mailID = query.value(0).toInt();
    }

//    m_db->close();
    return SEND_MAIL_SUCCESS;
}

void IMTcpServer::sendMessage(const SaveTmpInformation &save)
{
    m_save.m_requestKind = save.m_requestKind;
    switch(m_save.m_requestKind)
    {
        case SEND_MAIL:
        {
            m_save.m_mail = save.m_mail;
            m_save.m_replyKind = m_database.insertMail(m_save.m_mail);

            save.m_clientSocket->sendMessage(m_save);

            if(SEND_MAIL_SUCCESS == m_save.m_replyKind)
            {
                QString mailAddress = m_save.m_mail.m_receiverAddress;
                mailAddress.append(MAIL_ADDRESS_FORMAT);

                QMap::iterator iter;
                iter = m_userMailMap.find(mailAddress);
                if(iter != m_userMailMap.end())
                {
                    m_save.m_replyKind = RECEIVE_MAIL;
                    iter.value()->sendMessage(m_save);
                }
            }
            break;
        }
    }
}

收信:
一.邮件通信控制类(在IMMailCtrl中定义)的socket与服务器连接成功并准备好读信息时,会调用readMessage槽函数



    connect(m_tcpSocket, SIGNAL(connected()), this, SLOT(requestGetInMails()));
    connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(readMessage()));

二.readMessage槽函数识别到RECEIVE_MAIL,发出getInMail信号


void IMMailCtrl::readMessage()
{
    in >> type;

    switch (type)
    {
        case RECEIVE_MAIL:
    {
        in >> m_mail;
        if (m_mail.m_receiverAddress == m_myID)
            emit getInMail(m_mail);
        break;
    }
    }
}

三.邮件主界面(在IMMailWidget中定义)捕获信号, 调用addNewInMailButton


  connect(m_mailCtrl, &IMMailCtrl::getInMail,
          this, &IMMailWidget::addNewInMailButton);

bool IMMailWidget::addNewInMailButton(const MailInformation &mail)
{
  if(m_inMailMap.contains(mail.m_mailID))
    {
      return false;
    }
  IMMailButton *button = new IMMailButton(mail, this, this);

  m_inMailMap.insert(mail.m_mailID, button);
  m_inWidget.insertItem(0, button);
  return true;
}

你可能感兴趣的:(邮件,桌面聊天软件,学习笔记)