Qt:QTcpSocket、QTcpServerに基づいて作成されたマルチユーザネットワークチャットルーム(TCP/IPプロトコル)――サーバーソースコード


コンパイル環境:Ubuntu 18.04,Qt5.11.2
QTcpSockServer.pro
TEMPLATE = app
CONFIG += console c++11
CONFIG += console precompile_header
CONFIG -= app_bundle
CONFIG += qt
QT += core gui network sql
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

HEADERS  += \
    CommonInc.h \
    Database.h \
    Structure.h \
    TcpServer.h \
    ServerSocket.h

SOURCES += \
        TcpServer.cpp \
        Database.cpp \
        main.cpp \
        ServerSocket.cpp

main.cpp
#include 

#include "CommonInc.h"
#include "TcpServer.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    //       
    TcpServer *server = new TcpServer();

    if (!server->listen(QHostAddress::Any, Constant::LISTEN_PORT))
    {
        QString strErr(QObject::tr("critical: Satrting server listen fail, error string:: "));
        strErr += server->errorString();
        qDebug("%s", strErr.toStdString().c_str());
        exit(EXIT_FAILURE);
    }


    int ret = a.exec();
    delete server;

    return ret;
}


CommonInc.h
/*********************************************
File Name: CommonInc.h
Description:        
********************************************/
#ifndef COMMONINC_H
#define COMMONINC_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define TEST_SWITCH //    

#endif // COMMONINC_H


structure.h
/*********************************************
File Name: Structure.h
Description:         
********************************************/
#ifndef STRUCTURE_H
#define STRUCTURE_H

#include "CommonInc.h"

class ServerSocket;

//            ,   QString::fromUtf8(sourceText)
static const QString GROUP_NAME_DEFAULT = QString(QObject::tr("New Friend"));

namespace Constant //  
{
    const unsigned int LOGIN_TIMEOUT = 15;        //(seconds)      

    const unsigned int LISTEN_PORT = 1234;        //TCP    

    const QString DB_CLI_DRIVER = "QMYSQL";       //          
    const QString DB_CLI_USERNAME = "root";       //         
    const QString DB_CLI_PWD = "";                //        
    const QString DB_CLI_HOSTNAME = "localhost";  //          (IP)
    const QString DB_CLI_DATABASE = "clientDB";   //        

    const QString DB_SER_DRIVER = "QMYSQL";       //          
    const QString DB_SER_USERNAME = "root";       //         
    const QString DB_SER_PWD = "";                //        
    const QString DB_SER_HOSTNAME = "localhost";  //          (IP)
    const QString DB_SER_DATABASE = "serverDB";   //        
}

//     
struct ServerNode{
    QString serIPaddress; //     
    int serPort; //     
    ServerNode(){serPort = 0;}
};

//     
enum LoginStatus
{
    LS_ONLINE = 0,                      //   
    LS_INVISIBLE = 1,                   //   
    LS_BUSY = 2,                        //   
    LS_LEAVE = 3,                       //   
    LS_NOTDISTURB = 4,                  //     
    LS_OFFLINE = 5
};

//     (   ,   )
enum FlockStatus
{
    FS_FLOCK_HOST = 0,                  //   
    FS_FLOCK_ADMAIN = 1,                //     
    FS_FLOCK_MEMBER = 2                 //    
};

//       (   ,   )
enum DiscussionStatus
{
    DS_DISCUSSION_HOST = 0,             //   
    DS_DISCUSSION_MEMBER = 1            //   
};

//email /     (   ,   )
enum EmailStatus
{
    ES_MAIL_UNREAD = 0,
    ES_MAIL_READ = 1
};

//   (  )  
enum MessageType
{
    /*********************** CToS ************************/
    MT_CHECK_CONNECTION,                //           
    MT_LOGIN,                           //   
    MT_REGISTER,                        //   
    MT_GET_QUESTION_ANSWER,             //          
    MT_GET_QUESTION_ANSWER_SUCCESS,
    MT_GET_QUESTION_ANSWER_FAIL,

    MT_CHECK_MESSAGE,                   //           (     )

    MT_GET_ALL_FRIENDS,                 //         

    MT_TALK,                            //     
    MT_ADD_FRIEND,                      //     

    MT_GET_FRIEND_INFORMATION,          //       
    MT_DELETE_FRIEND,                   //     
    MT_GET_MYSELF_INFORMATION,          //       
    MT_CHANGE_INFORMATION,              //        
    MT_CHANGE_REMARK,                   //   (  )  
    MT_CHANGE_PASSWORD,                 //     
    MT_CHANGE_STATUE,                   //       
    //         
    MT_QUIT,                            //   

    /*********************** SToC ************************/

    MT_LOGIN_SUCCESS ,                  //     
    MT_LOGIN_FAIL,                      //     
    MT_HAVE_LOGINED,                    //     
    MT_REGISTER_SUCCESS,                //     
    MT_REGISTER_FAIL,                   //     

    MT_REMOVE_BOX,                      //     
    MT_REMOVE_BOX_SUCCESS,
    MT_REMOVE_BOX_FAIL,
    MT_RENAME_BOX,                      //      
    MT_RENAME_BOX_SUCCESS,
    MT_RENAME_BOX_FAIL,
    MT_CREATE_BOX,                      //     
    MT_CREATE_BOX_SUCEESS,
    MT_CREATE_BOX_FAIL,
    MT_MOVE_FRIEND_BOX,                 //            36
    MT_MOVE_FRIEND_BOX_SUCCESS,
    MT_MOVE_FRIEND_BOX_FAIL,


    MT_GET_ALL_FRIENDS_SUCCESS,         //           
    MT_GET_ALL_FRIENDS_FAIL,            //           
    MT_NO_FRIEND,                       //     

    MT_NO_MESSAGE,                      //     
    MT_HAVE_MESSAGE,                    //    
    MT_HAVE_TALK_MESSAGE,               //      

    MT_FRIEND_REQUESTED,                //     
    MT_FRIEDN_NO_ACCOUNT,               //        
    MT_ALREAD_FRIENDS,                  //       

    MT_GET_FRIEND_FAIL,
    MT_GET_FRIEND_SUCCESS,              //         
    MT_DELETE_FRIEND_FAIL,
    MT_DELETE_FRIEND_SUCCESS,           //       
    MT_GET_MYSELF_FAIL,
    MT_GET_MYSELF_SUCCESS,              //           
    MT_CHANGE_INFORMATION_FAIL,
    MT_CHANGE_INFORMATION_SUCCESS,      //         

    MT_CHANGE_REMARK_FAIL,              //       
    MT_CHANGE_REMARK_SUCCESS,           //       

    MT_OLD_PWD_IS_WRONG,                //       
    MT_CHANGE_PWD_FAIL,                 //       
    MT_CHANGE_PWD_SUCCESS,              //       

    /*********************** CToC ************************/

    MT_REQUEST_FRIEND,                  //       
    MT_AGREE_FRIEND,                    //       
    MT_REFUSE_FRIEND,                   //       
    MT_ADD_FRIEND_FAIL,                 //       
    MT_ADD_FRIEND_SUCCESS,              //       
    MT_END_ADD_FRIEND,                  //       
    MT_BE_DELETED,                      //         

    MT_MESSAGE,				            //     
    MT_TALK_MESSAGE,                    //     

    MT_GET_HISTORY_MESSAGE,             //     
    MT_GET_HISTORY_MESSAGE_SUCCESS,
    MT_GET_HISTORY_MESSAGE_FAIL
};

//           
struct SaveFile
{
    QFont m_Font;
    QColor m_Color;
    //          
    friend QDataStream & operator<< (QDataStream &out, const SaveFile &sf)
    {
       out << sf.m_Font << sf.m_Color;
       return out;
    }
    friend QDataStream & operator>> (QDataStream &in, SaveFile &sf)
    {
       in >> sf.m_Font >> sf.m_Color;
       return in;
    }
};

//    (   ,   )
struct MailInformation
{
    int m_MailID;
    QString m_SenderAddress;
    QString m_ReceiverAddress;
    QString m_Theme;
    QString m_Content;
    QDateTime m_dateTime;
    int m_Status;

    MailInformation()
    {
        m_Status = ES_MAIL_READ;
    }

    //          
    friend QDataStream &operator<<(QDataStream &out, const MailInformation &mail)
    {
        out << mail.m_MailID << mail.m_SenderAddress << mail.m_ReceiverAddress
            << mail.m_Theme << mail.m_Content << mail.m_dateTime << mail.m_Status;
        return out;
    }

    friend QDataStream &operator>>(QDataStream &in, MailInformation &mail)
    {
        in >> mail.m_MailID >> mail.m_SenderAddress >> mail.m_ReceiverAddress
           >> mail.m_Theme >> mail.m_Content >> mail.m_dateTime >> mail.m_Status;
        return in;
    }
};

//       
struct UserInformation
{
    int m_HeadPortrait;
    QString m_UserID;
    QString m_NickName;
    QString m_Password;
    QString m_Sex;
    QDate m_Birthday;
    QString m_Question;
    QString m_Answer;
    QString m_Name;
    QString m_Phone;
    QString m_Address;
    QDateTime m_RegDateTime;
    //QString m_Mark;
    int m_Status;

    UserInformation()
    {
       m_Status = LS_OFFLINE;
       m_HeadPortrait = 1;
    }
    //          
    friend QDataStream &operator<<(QDataStream &out, const UserInformation &user)
    {
       out << user.m_HeadPortrait << user.m_UserID << user.m_NickName
           << user.m_Password << user.m_Sex << user.m_Birthday
           << user.m_Question << user.m_Answer << user.m_Name
           << user.m_Phone << user.m_Address << user.m_RegDateTime
           << user.m_Status;
       return out;
    }

    friend QDataStream &operator>>(QDataStream &in, UserInformation &user)
    {
       in >> user.m_HeadPortrait >> user.m_UserID >> user.m_NickName
          >> user.m_Password >> user.m_Sex >> user.m_Birthday
          >> user.m_Question >> user.m_Answer >> user.m_Name
          >>  user.m_Phone >> user.m_Address >> user.m_RegDateTime
          >> user.m_Status;
       return in;
    }
};

//     
struct FriendInformation
{
    int m_HeadPortrait;
    QString m_UserID;
    QString m_NickName;
    QString m_GroupName;
    QString m_RemarkName;
    int m_Status;

    FriendInformation()
    {
       m_Status = LS_OFFLINE;
       m_HeadPortrait = 1;
       m_GroupName = GROUP_NAME_DEFAULT;
    }
    //         
    friend QDataStream & operator<< (QDataStream &out, const FriendInformation &fri)
    {
       out << fri.m_HeadPortrait << fri.m_UserID << fri.m_NickName
           << fri.m_GroupName << fri.m_RemarkName << fri.m_Status;
       return out;
    }
    friend QDataStream & operator>> (QDataStream &in, FriendInformation &fri)
    {
       in >> fri.m_HeadPortrait >> fri.m_UserID >> fri.m_NickName
          >> fri.m_GroupName >> fri.m_RemarkName >> fri.m_Status;
       return in;
    }
};

//               
struct TempStrings
{
    QString m_One;
    QString m_Two;
    QString m_Three;
    //         
    friend QDataStream & operator<< (QDataStream &out, const TempStrings &str)
    {
       out << str.m_One << str.m_Two << str.m_Three;
       return out;
    }
    friend QDataStream & operator>> (QDataStream &in, TempStrings &str)
    {
       in >> str.m_One >> str.m_Two >> str.m_Three;
       return in;
    }
};

//      
struct ChatInformation
{
    QString m_MyID;
   int m_HeadPortrait;
   QString m_FriendID;          //   id
   QString m_FriendNickname;    //     
   QString m_FriendRemark;      //     
   QString m_FriendMark;        //     
   QString m_FriendIP;          //   ip  
   int m_FriendStatus;

    ChatInformation()
    {
       m_FriendStatus = LS_OFFLINE;
       m_HeadPortrait= 1;
       m_FriendMark = QString(QObject::tr("    "));
    }
};

//     
struct TalkMessage
{
    int m_Type;               //     
    QString m_SenderID;       //    ID
    QString m_SenderIP;       //    IP
    QString m_ReceiverID;     //    ID
    QString m_ReceiverIP;     //    IP
    QString m_Text;           //     
    QDateTime m_dateTime;

    TalkMessage() {	m_Type = 0; }
    //         
    friend QDataStream & operator<< (QDataStream &out, const TalkMessage &mes)
    {
       out << mes.m_Type << mes.m_SenderID << mes.m_SenderIP << mes.m_ReceiverID
           << mes.m_ReceiverIP << mes.m_Text << mes.m_dateTime;
       return out;
    }

    friend QDataStream & operator>> (QDataStream &in, TalkMessage &mes)
    {
       in >> mes.m_Type >> mes.m_SenderID >> mes.m_SenderIP >> mes.m_ReceiverID
          >> mes.m_ReceiverIP >> mes.m_Text >>  mes.m_dateTime;
       return in;
    }
};

//       
struct LoginInformation
{
    QString m_UserID;
    QString m_Password;
    int m_Status;

    LoginInformation()
    {	m_Status = LS_OFFLINE;	}
    //         
    friend QDataStream & operator<< (QDataStream &out, const LoginInformation &li)
    {
       out << li.m_UserID << li.m_Password << li.m_Status;
       return out;
    }
    friend QDataStream & operator>> (QDataStream &in, LoginInformation &li)
    {
       in >> li.m_UserID >> li.m_Password >> li.m_Status;
       return in;
    }
};

//      (   ,   )
struct FlockMember
{
    QString m_FlockID;     //  ID
    QString m_UserID;      //   ID
    int m_HeadPortrait;    //       
    QString m_Nickname;    //     
    int m_LoginStatus;     //       
    QString m_Remark;      //      
    int m_FlockStatus;     //     
    QDateTime m_dateTimejoin;  //     
    //         
    friend QDataStream & operator<< (QDataStream &out, const FlockMember &flockMember)
    {
       out << flockMember.m_FlockID << flockMember.m_UserID
           << flockMember.m_HeadPortrait << flockMember.m_Nickname
           << flockMember.m_LoginStatus << flockMember.m_Remark
           << flockMember.m_FlockStatus << flockMember.m_dateTimejoin;
       return out;
    }
    friend QDataStream & operator>> (QDataStream &in, FlockMember &flockMember)
    {
       in >> flockMember.m_FlockID >> flockMember.m_UserID
          >> flockMember.m_HeadPortrait >> flockMember.m_Nickname
          >> flockMember.m_LoginStatus >> flockMember.m_Remark
          >> flockMember.m_FlockStatus >> flockMember.m_dateTimejoin;
       return in;
    }
};

//        (   ,   )
struct DiscussionMember
{
    QString m_DiscussionID;    //    ID
    QString m_UserID;          //   ID
    int m_HeadPortrait;        //       
    QString m_NickName;        //     
    int m_LoginStatus;         //       
    int m_DiscussionStatus;    //     
    QDateTime m_dateTimejoin;  //     
    //         
    friend QDataStream & operator<< (QDataStream &out, const DiscussionMember &disMember)
    {
       out << disMember.m_DiscussionID << disMember.m_UserID
           << disMember.m_HeadPortrait << disMember.m_NickName
           << disMember.m_LoginStatus << disMember.m_DiscussionStatus
           << disMember.m_dateTimejoin;
       return out;
    }
    friend QDataStream & operator>> (QDataStream &in, DiscussionMember &disMember)
    {
       in >> disMember.m_DiscussionID >> disMember.m_UserID
          >> disMember.m_HeadPortrait >> disMember.m_NickName
          >> disMember.m_LoginStatus  >> disMember.m_DiscussionStatus
          >> disMember.m_dateTimejoin;
       return in;
    }
};

//    (   ,   )
struct FlockInformation
{
    QString m_FlockID;
    QString m_CreatorID;
    QDate m_CreateDate;
    QString m_FlockName;
    QString m_Theme;
    //         
    friend QDataStream & operator<< (QDataStream &out, const FlockInformation &flock)
    {
       out << flock.m_FlockID << flock.m_CreatorID << flock.m_CreateDate
           << flock.m_FlockName << flock.m_Theme;
       return out;
    }
    friend QDataStream & operator>> (QDataStream &in, FlockInformation &flock)
    {
       in >> flock.m_FlockID >> flock.m_CreatorID >> flock.m_CreateDate
          >> flock.m_FlockName >> flock.m_Theme;
       return in;
   }
};

//      (   ,   )
struct DiscussionInformation
{
    QString m_DiscussionID;
    QString m_CreatorID;
    QDate m_CreateDate;
    QString m_DiscussionName;
    QString m_Theme;
    //         
    friend QDataStream & operator<< (QDataStream &out, const DiscussionInformation &dis)
    {
       out << dis.m_DiscussionID << dis.m_CreatorID << dis.m_CreateDate
           << dis.m_DiscussionName << dis.m_Theme;
       return out;
    }
    friend QDataStream & operator>> (QDataStream &in, DiscussionInformation &dis)
    {
       in >> dis.m_DiscussionID >> dis.m_CreatorID >> dis.m_CreateDate
          >> dis.m_DiscussionName >> dis.m_Theme;
       return in;
    }
};

//           ,    / 
struct SaveTmpInformation
{
    int m_RequestKind;
    int m_ReplyKind;
    ServerSocket *m_ServerSocket;

    QString m_MyID;
    QString m_PeerID;
    QDate m_Date;
    QString m_GroupName;
    QString m_GroupNameF;
    UserInformation m_UserInf;
    LoginInformation m_LoginInf;
    FriendInformation m_FriendInf;
    TalkMessage m_Message;
    int m_Status;
    TempStrings m_TempStr;
    QVector<TalkMessage> m_MessageVec;
    QVector<FriendInformation> m_FriendsVec;
    QVector<QString> m_IDVec;

    QString m_FlockID;
    FlockMember m_FlockMember;
    FlockInformation m_FlockInf;
    QVector<FlockInformation> m_FlocksVec;
    QVector<FlockMember> m_FlockMembersVec;
    QString m_DiscussionID;
    DiscussionMember m_DiscussionMember;
    DiscussionInformation m_DiscussionInf;
    QVector<DiscussionInformation> m_DiscussionsVec;
    QVector<DiscussionMember> m_DiscussionMembersVec;

    int m_MailID;
    MailInformation m_Mail;
    QVector<MailInformation>  m_InMailsVec;
    QVector<MailInformation>  m_OutMailsVec;

    QString m_Title;
    QString m_NewTitle;

    QString m_SocketID;

    QVector<TalkMessage> m_HistoryMessageVec;
};

//    
const int HEAD_BIG_SIZE = 40;
const int HEAD_SMALL_SIZE = 35;
const int HEAD_MINI_SIZE = 20;

//         
const int CHAT_WIDGET_TOOL_SIZE = 20;
const int CHAT_WIDGET_TOOL_SMALL_SIZE = 15;
//    
const int FONT_SIZE = 2;
//      
static const QString MAIL_ADDRESS_FORMAT = "@hackt.com";
//  /            
static const QString LOCAL_HISTORY_MESSAGE_PATH = "resource/history/local/";
static const QString NETWORK_HISTORY_MESSAGE_PATH = "resource/history/network/";

#endif // STRUCTURE_H


Database.h
/*********************************************
File Name: Database.h
Description:       
********************************************/
#ifndef DATABASE_H
#define DATABASE_H

#include "CommonInc.h"
#include "Structure.h"

class QSqlQuery;
class QDateTime;
class QSqlDatabase;

class Database : public QObject
{
    Q_OBJECT
public:
    Database(QObject *parent = nullptr);
    ~Database();
    //    
    bool createConnection();
    //      ,         status   OFFLINE
    bool initDatabase();
    //     (   )
    void close();
    //     (   )
    bool isOpen();
    //  、    
    int updatePassword(TempStrings &tmp);
    //           
    int searchQuestionAndAnswer(const QString &id, TempStrings & tmp);
    //     
    int searchUserInUserInformation(const LoginInformation &logInf, UserInformation &userInf);
    //   id      
    int searchFriendInformationByID(const QString &id, UserInformation &userInf);
    //   id      
    int searchMyselfInformationByID(const QString &id, UserInformation &userInf);
    //       
    int updateMyselfInformation(const UserInformation &user);
    //     
    int addUserInUserInformation(const UserInformation &userInf);
    //           
    int countRegisteredInPeriod(const QDateTime &datePre, const QDateTime &dateLater);
    //         
    int searchFriendsInformation(const QString &id, QVector<FriendInformation> &friendsVec);
    //       ID
    bool searchFriendsID(const QString &id, QVector<QString> &IDVec);
    //       
    bool updateStatus(int status, const QString & id);
    //       
    int updateRemark(const TempStrings & tmpStr);
    //     
    int deleteFriend(const QString & myID, const QString & friendID, QString & groupName, QString & groupNameF);
    //     
    bool addFriend(const TalkMessage & talMes);
    //  DateCounterb       
    bool insertValuesInDateCounter(const QDate &date);
    //           +1
    int getUserTimes(const QDate &date);
    //           
    bool increaseUserTimes(const QDate &date);
    //          
    int moveFriendToGroup(const QString & myID, const QString & friendID, const QString & title, const QString & newTitle);
    //      
    int renameGroup(const QString & id, const QString & title,  const QString & newTitle);
    //       
    bool addHistoryMsg(const TalkMessage &talMes);
    //       
    bool addOfflineMsg(const TalkMessage &talMes);
    //                  
    int searchHistoryMsgOfFriendInDate(const QString & myID, const QString &friendID, const QDate & date, QVector<TalkMessage> & mesVec);


private:
    //  SQL      
    void errorSQLOrder(QSqlQuery query, QString mark);
    //       
    void createTable();

    QSqlDatabase *m_SqlDatabase;
};

#endif // DATABASE_H

Database.cpp
/*********************************************
File Name: Database.cpp
Description:      
********************************************/

#include 
#include 
#include 
#include 
#include 
#include 
#include "Database.h"

//        
static const QString UPDATE_STATUS_IN_USERINFORMATION_SQL =
        "update UserInformation set status = 5";

//      
static const QString UPDATE_PASSWORD_IN_USERINFORMATION_SQL =
        "update UserInformation set password = ?"
        "where user = ? and password = ?";

//            
static const QString SEARCH_QUESTION_ANSWER_IN_USERINFORMATION_SQL =
        "select password, question, answer from UserInformation where userID = ?;";

//       
static const QString SEARCH_USER_IN_USERINFORMATION_SQL =
        "select * from UserInformation where (userID = ? and password = ?)";

//       
static const QString SEARCH_USER_IN_USERINFORMATION_ID_SQL =
        "select * from UserInformation where userID = ?";

//       
static const QString UPDATE_USERINFORMATION_SQL =
        "update UserInformation set "
        "head = ?, nickname = ?, sex = ?, birthday = ?, "
        "name = ?, phone = ?, address = ?  where userID = ?;";

//         
static const QString  UPDATE_STATUS_IN_USERINFORMATION_BY_ID_SQL=
        "update UserInformation set status = ? where userID = ?;";

//          
static const QString  UPDATE_REMARKNAME_IN_USERFRIENDS_SQL=
        "update UserFriends set remarkName = ? where userID = ? and friendID = ?;";

//        UserInformation  
static const QString ADD_USER_IN_USERINFORMATION_SQL =
        "insert into UserInformation values(?,?,?,?,?,?,?,?,?,?,?,?,?)";

//               
static const QString COUNT_REGISTERED_USERS_IN_USERINFORMATION_SQL =
        "select count(*) from UserInformation where regDate >= ? and regDate < ?";

//           
static const QString SEARCH_FRIENDS_IN_USERFRIENDS_USERINFORMATION_SQL =
                                        "select UserFriends.groupName, UserFriends.friendID, "
                                        "UserInformation.nickName, UserFriends.remarkName,"
                                        "UserInformation.status, UserInformation.head "
                                        "from UserFriends,UserInformation "
                                        "where UserFriends.userID = ? "
                                        "and UserInformation.userID = UserFriends.friendID;";

//            
static const QString SEARCH_ID_IN_USERFRIENDS_SQL =
                                        "select friendID from UserFriends where userID = ?";

//             
static const QString SEARCH_GROUPNAME_IN_USERFRIENDS_SQL =
                                        "select groupName from UserFriends where userID = ? and friendID = ?";

//             
static const QString DELETE_FRIEND_IN_USERFRIENDS_SQL =
                                        "delete from UserFriends where "
                                        "(userID = ? and friendID = ?) or "
                                        "(userID = ? and friendID = ?)";

//            
static const QString ADD_FRIEND_IN_USERFRIENDS_SQL =
                                        "insert into UserFriends(userID, friendID, groupName) values (?, ?, ?);";

//   DataCounter      
static const QString COUNT_DATARECORD_IN_DATECOUNTER_SQL =
                                        "select count(*) from DateCounter where date = ?;";

//        DataCounter  
static const QString INSERT_VALUES_IN_DATECOUNTER_SQL =
                                        "insert into DateCounter values(?, 0, 0, 0);";

//           
static const QString SELECT_USERTIMES_IN_DATECOUNTER_SQL =
                                        "select userTimes from DateCounter where date = ?;";

//          
static const QString INCREASE_USERTIMES_IN_DATECOUNTER_SQL =
                                        "update DateCounter set userTimes = userTimes + 1 where date = ?;";

/************************ group ***************************/
//   /        
static const QString RENAME_GROUPNAME_IN_USERFREINS =
                                    "update UserFriends set groupName = ? where userID = ? and groupName = ?;";

//   /        
static const QString MOVE_FRIEND_IN_USERFREINS =
                                    "update UserFriends set groupName = ? where userID = ? "
                                    "and friendID = ?;";

/************************ message ************************/
//        HistoryMessage  
static const QString INSERT_MESSAGE_IN_HISTORYMESSAGE =
                                    "insert into HistoryMessage (senderID, receiverID, content, dateTime) "
                                    "values(?, ?, ?, ?); ";

//        OfflineMessage  
static const QString INSERT_MESSAGE_IN_OFFLINEMESSAGE =
                                    "insert into OfflineMessage (kind, senderID, receiverID, content) "
                                    "values(?, ?, ?, ?);";

//       
static const QString SEARCH_FRIEND_DATE_MESSAGE_IN_HISTORYMESSAGE =
                                    "select senderID, receiverID, content, dateTime from HistoryMessage "
                                    "where ( (senderID = ? and receiverID = ?) "
                                    "or (senderID = ? and receiverID = ?) ) "
                                    "and dateTime >= ? and dateTime < ?;";

/********************create tables********************/
static const QString CREATE_TABLE_USERINFORMATION_SQL = "";
static const QString CREATE_TABLE_USERFRIENDS_SQL = "";
static const QString CREATE_TABLE_TMPMESSAGE_SQL = "";

//html QString
QString simplifyRichText(QString richText)
{
    QTextDocument doc;
    doc.setHtml(richText);
    qDebug() << "say:"<< doc.toPlainText();
    return doc.toPlainText();
}

Database::Database(QObject *parent) :
    QObject(parent)
{
    m_SqlDatabase = new QSqlDatabase;
}

Database::~Database()
{
    if (m_SqlDatabase != nullptr)
    {
        if (m_SqlDatabase->isOpen())
            m_SqlDatabase->close();
        delete m_SqlDatabase;
        m_SqlDatabase = nullptr;
    }
}

bool Database::createConnection() //       
{
    if(m_SqlDatabase == nullptr)
    {
        m_SqlDatabase = new QSqlDatabase;
    }
    if(m_SqlDatabase->isOpen())
    {
        return true;
    }
    //         
    if(QSqlDatabase::contains("serverDB"))
    {
        *m_SqlDatabase = QSqlDatabase::database("serverDB");
    }else
    {
        //      ,   
        *m_SqlDatabase = QSqlDatabase::addDatabase(Constant::DB_CLI_DRIVER,Constant::DB_SER_DATABASE);
        m_SqlDatabase->setDatabaseName(Constant::DB_CLI_DATABASE);
    }
    m_SqlDatabase->setUserName(Constant::DB_SER_USERNAME);
    m_SqlDatabase->setPassword(Constant::DB_SER_PWD);
    m_SqlDatabase->setHostName(Constant::DB_SER_HOSTNAME);
    if(!m_SqlDatabase->open())
    {
        QSqlError sqlError = m_SqlDatabase->lastError();
        QString errorString = sqlError.text();
        return false;
    }
    return true;
}

bool Database::initDatabase() //      ,       status  OFFLINE
{
    if(!createConnection())
    {
        return false;
    }
    QSqlQuery sqlQuery(*m_SqlDatabase);
    sqlQuery.exec(UPDATE_STATUS_IN_USERINFORMATION_SQL);
    errorSQLOrder(sqlQuery, "initDatabase");
    if(!sqlQuery.isActive())
    {
        m_SqlDatabase->close();
        return false;
    }
    m_SqlDatabase->close();
    return false;
}

void Database::close() //     
{
    if(m_SqlDatabase != nullptr && m_SqlDatabase->isOpen())
    {
        m_SqlDatabase->close();
    }
}

bool Database::isOpen() //       
{
    return m_SqlDatabase->isOpen();
}

int Database::updatePassword(TempStrings &tmp)
{
    if(!createConnection())
    {
        return MT_CHANGE_PWD_FAIL;
    }
    //sql  
    QSqlDatabase::database().transaction(); //          ,          
    QSqlQuery sqlquery(*m_SqlDatabase);
    sqlquery.prepare(UPDATE_PASSWORD_IN_USERINFORMATION_SQL); //      SQL      ,  true,    false

    sqlquery.addBindValue(tmp.m_Three); //        ,  val       
    sqlquery.addBindValue(tmp.m_One);
    sqlquery.addBindValue(tmp.m_Two);

    sqlquery.exec(); //       SQL  ,        ,  true,    false
    errorSQLOrder(sqlquery,"update pwd");
    QSqlDatabase::database().commit(); //            ,      

    if(!sqlquery.isActive()) //isActive():          (    exec(),      Qsqlquery),   true
    {
        m_SqlDatabase->close();
        return MT_CHANGE_PWD_FAIL;
    }
    qDebug() << "size:" << sqlquery.numRowsAffected(); //     SQL       ,      ,   -1
    if(sqlquery.numRowsAffected() <= 0)
    {
        m_SqlDatabase->close();
        return MT_CHANGE_PWD_FAIL;
    }
    qDebug() << "size:" << sqlquery.numRowsAffected();
    return MT_CHANGE_PWD_SUCCESS;
}

int Database::searchQuestionAndAnswer(const QString &id, TempStrings &tmp) //         
{
    if(!createConnection())
    {
        return MT_GET_QUESTION_ANSWER_FAIL;
    }
    //Sql  
    QSqlDatabase::database().transaction();
    QSqlQuery sqlquery(*m_SqlDatabase);
    sqlquery.prepare(SEARCH_QUESTION_ANSWER_IN_USERINFORMATION_SQL);

    sqlquery.addBindValue(id);
    sqlquery.exec();
    errorSQLOrder(sqlquery,"forget pwd");
    QSqlDatabase::database().commit();

    if(!sqlquery.isActive())
    {
        m_SqlDatabase->close();
        return MT_GET_QUESTION_ANSWER_FAIL;
    }
    if(sqlquery.size() <= 0)//       (     );        ,                   ,   -1
    {
        m_SqlDatabase->close();
        return MT_GET_QUESTION_ANSWER_FAIL;
    }
    /*           (   ),            。
            ,                  false。         ,   true*/
    if(sqlquery.next())
    {
        tmp.m_One = sqlquery.value(0).toString();
        tmp.m_Two = sqlquery.value(1).toString();
        tmp.m_Three = sqlquery.value(2).toString();

        return MT_GET_QUESTION_ANSWER_SUCCESS;
    }
    return MT_GET_QUESTION_ANSWER_FAIL;
}

int Database::searchUserInUserInformation(const LoginInformation &logInf, UserInformation &userInf) //    (    )
{
    if(!createConnection())
    {
        return MT_LOGIN_FAIL;
    }
    //Sql  
    QSqlDatabase::database().transaction();
    QSqlQuery sqlquery(*m_SqlDatabase);
    sqlquery.prepare(SEARCH_USER_IN_USERINFORMATION_SQL);

    sqlquery.addBindValue(logInf.m_UserID);
    sqlquery.addBindValue(logInf.m_Password);
    sqlquery.exec();
    errorSQLOrder(sqlquery,"login search");
    QSqlDatabase::database().commit();

    if(!sqlquery.isActive())
    {
        m_SqlDatabase->close();
        return MT_LOGIN_FAIL;
    }
    if(sqlquery.size() <= 0)
    {
        m_SqlDatabase->close();
        return MT_LOGIN_FAIL;
    }
    if(sqlquery.next())
    {
        userInf.m_UserID = sqlquery.value(0).toString();
        userInf.m_NickName = sqlquery.value(1).toString();
        userInf.m_Sex = sqlquery.value(2).toString();
        userInf.m_Birthday = sqlquery.value(3).toDate();
        userInf.m_Address = sqlquery.value(4).toString();
        userInf.m_HeadPortrait = sqlquery.value(5).toInt();
        userInf.m_Phone = sqlquery.value(6).toString();
        userInf.m_RegDateTime = sqlquery.value(7).toDateTime();
        userInf.m_Name = sqlquery.value(8).toString();
        userInf.m_Status = logInf.m_Status;

        qDebug() << "searchUserInUserInformation:" << userInf.m_Status;
        if(updateStatus(logInf.m_Status, logInf.m_UserID))
        {
            return MT_LOGIN_SUCCESS;
        }
    }
    return MT_LOGIN_FAIL;
}

int Database::searchFriendInformationByID(const QString &id, UserInformation &userInf) //  id      
{
    if(!createConnection())
    {
        return MT_GET_FRIEND_FAIL;
    }
    //sql  
    QSqlDatabase::database().transaction();
    QSqlQuery sqlquery(*m_SqlDatabase);

    sqlquery.addBindValue(id);
    sqlquery.exec();
    errorSQLOrder(sqlquery, "friend inf search");
    QSqlDatabase::database().commit();

    if(!sqlquery.isActive())
    {
        m_SqlDatabase->close();
        return MT_GET_FRIEND_FAIL;
    }
    if(sqlquery.size() <= 0)
    {
        m_SqlDatabase->close();
        return MT_GET_FRIEND_FAIL;
    }
    if(sqlquery.next())
    {
        userInf.m_UserID = sqlquery.value(0).toString();
        userInf.m_NickName = sqlquery.value(1).toString();
        userInf.m_Sex = sqlquery.value(2).toString();
        userInf.m_Birthday = sqlquery.value(3).toDate();
        userInf.m_Address = sqlquery.value(4).toString();
        userInf.m_HeadPortrait = sqlquery.value(5).toInt();
        userInf.m_Phone = sqlquery.value(6).toString();
        userInf.m_RegDateTime = sqlquery.value(7).toDateTime();
        userInf.m_Name = sqlquery.value(8).toString();
        userInf.m_Status = sqlquery.value(9).toInt();
    }
    return MT_GET_FRIEND_SUCCESS;
}

int Database::searchMyselfInformationByID(const QString &id, UserInformation &userInf) //  id       
{
    if(!createConnection())
    {
        return MT_GET_MYSELF_FAIL;
    }
    //sql  
    QSqlDatabase::database().transaction();
    QSqlQuery sqlquery(*m_SqlDatabase);
    sqlquery.prepare(SEARCH_USER_IN_USERINFORMATION_ID_SQL);

    sqlquery.addBindValue(userInf.m_NickName);
    sqlquery.addBindValue(userInf.m_Sex);
    sqlquery.addBindValue(userInf.m_Birthday);
    sqlquery.addBindValue(userInf.m_Name);
    sqlquery.addBindValue(userInf.m_Phone);
    sqlquery.addBindValue(userInf.m_Address);
    sqlquery.addBindValue(userInf.m_UserID);
    sqlquery.addBindValue(id);
    sqlquery.exec();
    errorSQLOrder(sqlquery, "myself inf search");
    QSqlDatabase::database().commit();

    if(!sqlquery.isActive())
    {
        m_SqlDatabase->close();
        return MT_GET_MYSELF_FAIL;
    }
    if(sqlquery.size() <= 0)
    {
        m_SqlDatabase->close();
        return MT_GET_MYSELF_FAIL;
    }
    if(sqlquery.next())
    {
        userInf.m_UserID = sqlquery.value(0).toString();
        userInf.m_NickName = sqlquery.value(1).toString();
        userInf.m_Sex = sqlquery.value(2).toString();
        userInf.m_Birthday = sqlquery.value(3).toDate();
        userInf.m_Address = sqlquery.value(4).toString();
        userInf.m_HeadPortrait = sqlquery.value(5).toInt();
        userInf.m_Phone = sqlquery.value(6).toString();
        userInf.m_RegDateTime = sqlquery.value(7).toDateTime();
        userInf.m_Name = sqlquery.value(8).toString();
        userInf.m_Status = sqlquery.value(9).toInt();
    }
    return MT_GET_MYSELF_SUCCESS;
}

int Database::updateMyselfInformation(const UserInformation &userInf) //      
{
    if(!createConnection())
    {
        return MT_CHANGE_INFORMATION_FAIL;
    }
    //sql  
    QSqlDatabase::database().transaction();
    QSqlQuery sqlquery(*m_SqlDatabase);
    sqlquery.prepare(UPDATE_USERINFORMATION_SQL);
    sqlquery.addBindValue(userInf.m_HeadPortrait);
    sqlquery.addBindValue(userInf.m_NickName);
    sqlquery.addBindValue(userInf.m_Sex);
    sqlquery.addBindValue(userInf.m_Birthday);
    sqlquery.addBindValue(userInf.m_Name);
    sqlquery.addBindValue(userInf.m_Phone);
    sqlquery.addBindValue(userInf.m_Address);
    sqlquery.addBindValue(userInf.m_UserID);
    sqlquery.exec();
    errorSQLOrder(sqlquery, "change update userinf");
    QSqlDatabase::database().commit();

    if(!sqlquery.isActive())
    {
        //lastError():                (   )     
        qDebug() << "QUERY_FAIL::" << sqlquery.lastError().text();
        m_SqlDatabase->close();
        return MT_CHANGE_INFORMATION_FAIL;
    }
    return MT_CHANGE_INFORMATION_SUCCESS;
}

int Database::addUserInUserInformation(const UserInformation &userInf) //    
{
    if(!createConnection())
    {
        return MT_REGISTER_FAIL;
    }
    //sql  
    QSqlDatabase::database().transaction();
    QSqlQuery sqlquery(*m_SqlDatabase);
    sqlquery.prepare(ADD_USER_IN_USERINFORMATION_SQL);

    sqlquery.addBindValue(userInf.m_UserID);
    sqlquery.addBindValue(userInf.m_HeadPortrait);
    sqlquery.addBindValue(userInf.m_NickName);
    sqlquery.addBindValue(userInf.m_Password);
    sqlquery.addBindValue(userInf.m_Sex);
    sqlquery.addBindValue(userInf.m_Birthday.toString("yyyy-MM-dd"));
    sqlquery.addBindValue(userInf.m_Question);
    sqlquery.addBindValue(userInf.m_Answer);
    sqlquery.addBindValue(userInf.m_Name);
    sqlquery.addBindValue(userInf.m_Phone);
    sqlquery.addBindValue(userInf.m_Address);
    sqlquery.addBindValue(userInf.m_RegDateTime);//.toString("yyyy-MM-dd hh:mm:ss"));
    sqlquery.addBindValue(5);
    sqlquery.exec();
    errorSQLOrder(sqlquery, "register add");
    QSqlDatabase::database().commit();

    if(!sqlquery.isActive())
    {
        qDebug() << "QUERY FAIL::" << sqlquery.lastError().text();//                (   )     
        m_SqlDatabase->close();
        return MT_REGISTER_FAIL;
    }
    if(!increaseUserTimes(QDate::currentDate()))
    {
        return MT_REGISTER_FAIL;
    }
    return MT_REGISTER_SUCCESS;
}

int Database::countRegisteredInPeriod(const QDateTime &datePre, const QDateTime &dateLater) //              
{
    int count = 0;
    qDebug() << "A period of date:" << datePre.toString("yyyy-MM-dd hh:mm:ss")
             << dateLater.toString("yyyy-MM-dd hh:mm:ss");
    if(!createConnection())
    {
        return 0;
    }
    //sql  
    QSqlDatabase::database().transaction();
    QSqlQuery sqlquery(*m_SqlDatabase);
    sqlquery.prepare(COUNT_REGISTERED_USERS_IN_USERINFORMATION_SQL);

    sqlquery.addBindValue(datePre);
    sqlquery.addBindValue(dateLater);
    sqlquery.exec();
    errorSQLOrder(sqlquery, "register count");
    QSqlDatabase::database().commit();

    if(!sqlquery.isActive())
    {
        m_SqlDatabase->close();
        return 0;
    }
    while(sqlquery.next())
    {
        count = sqlquery.value(0).toInt() + 1;
    }
    return count;
}

int Database::searchFriendsInformation(const QString &id, QVector<FriendInformation> &friendsVec) //        
{
    if(!createConnection())
    {
        return MT_GET_ALL_FRIENDS_FAIL;
    }
    //sql  
    QSqlDatabase::database().transaction();
    QSqlQuery sqlquery(*m_SqlDatabase);
    sqlquery.prepare(SEARCH_FRIENDS_IN_USERFRIENDS_USERINFORMATION_SQL);
    sqlquery.addBindValue(id);
    sqlquery.exec();
    errorSQLOrder(sqlquery, "get all friend search");
    QSqlDatabase::database().commit();

    if(!sqlquery.isActive())
    {
        m_SqlDatabase->close();
        return MT_GET_ALL_FRIENDS_FAIL;
    }
    friendsVec.clear(); //          
    while(sqlquery.next())
    {
        FriendInformation friInf;
        friInf.m_GroupName = sqlquery.value(0).toString();
        friInf.m_UserID = sqlquery.value(1).toString();
        friInf.m_NickName = sqlquery.value(2).toString();
        friInf.m_RemarkName = sqlquery.value(3).toString();
        friInf.m_Status = sqlquery.value(4).toInt();
        friInf.m_HeadPortrait = sqlquery.value(5).toInt();
        friendsVec.push_back(friInf); //          STL   ,   append(value)
    }
    if(friendsVec.isEmpty())
    {
        return MT_NO_FRIEND;
    }
    return MT_GET_ALL_FRIENDS_SUCCESS;
}

bool Database::searchFriendsID(const QString &id, QVector<QString> &friVec) //      ID
{
    friVec.clear();
    if(!createConnection())
    {
        return false;
    }
    //sql  
    QSqlDatabase::database().transaction();
    QSqlQuery sqlquery(*m_SqlDatabase);
    sqlquery.prepare(SEARCH_ID_IN_USERFRIENDS_SQL);

    sqlquery.addBindValue(id);
    sqlquery.exec();
    errorSQLOrder(sqlquery, "get all friend id search");
    QSqlDatabase::database().commit();

    if(!sqlquery.isActive())
    {
        m_SqlDatabase->close();
        return false;
    }
    while(sqlquery.next())
    {
        friVec.push_back(sqlquery.value(0).toString());
    }
    return true;
}

void Database::errorSQLOrder(QSqlQuery sqlquery, QString flog) //  SQL      
{
    //  SQL    ,       
    if(!sqlquery.isActive())
    {
        QString str = sqlquery.lastError().text() + '
'
+ flog; qDebug() << "Mysql query error:" << str; qDebug() << "sqlquery text:" << sqlquery.lastQuery(); // , , } else { qDebug() << Constant::DB_SER_DRIVER << "excute success:"; qDebug() << "sql text:" << sqlquery.lastQuery(); } } void Database::createTable() // { // } bool Database::updateStatus(int status, const QString &id) // { qDebug() << "status is:" << status; if(!createConnection()) { return false; } //sql QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(UPDATE_STATUS_IN_USERINFORMATION_BY_ID_SQL); sqlquery.addBindValue(id); sqlquery.addBindValue(status); sqlquery.exec(); errorSQLOrder(sqlquery, "quit update status"); QSqlDatabase::database().commit(); if(!sqlquery.isActive()) { qDebug() << "QUERY_FAIL::" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } return true; } int Database::updateRemark(const TempStrings & tmpStr)// { if (!createConnection()) { return MT_CHANGE_REMARK_FAIL; } //sql QSqlDatabase::database().transaction(); QSqlQuery query(*m_SqlDatabase); query.prepare(UPDATE_REMARKNAME_IN_USERFRIENDS_SQL); query.addBindValue(tmpStr.m_Three); query.addBindValue(tmpStr.m_One); query.addBindValue(tmpStr.m_Two); query.exec(); errorSQLOrder(query, "update-remark"); QSqlDatabase::database().commit(); if (!query.isActive()) { qDebug() << "QUERY_FAIL::" << query.lastError().text(); m_SqlDatabase->close(); return MT_CHANGE_REMARK_FAIL; } return MT_CHANGE_REMARK_SUCCESS; } int Database::deleteFriend(const QString & myID, const QString & friendID, QString & groupName, QString & groupNameF)// { if(!createConnection()) { return MT_DELETE_FRIEND_FAIL; } //sql QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); // groupName sqlquery.prepare(SEARCH_GROUPNAME_IN_USERFRIENDS_SQL); sqlquery.addBindValue(myID); sqlquery.addBindValue(friendID); sqlquery.exec(); errorSQLOrder(sqlquery, "search friend through groupName"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return MT_DELETE_FRIEND_FAIL; } if(sqlquery.next()) { groupName = sqlquery.value(0).toString(); } sqlquery.clear(); // groupNameF sqlquery.prepare(SEARCH_GROUPNAME_IN_USERFRIENDS_SQL); sqlquery.addBindValue(friendID); sqlquery.addBindValue(myID); sqlquery.exec(); errorSQLOrder(sqlquery, "search friend through groupNameF"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return MT_DELETE_FRIEND_FAIL; } if(sqlquery.next()) { groupNameF = sqlquery.value(0).toString(); } sqlquery.clear(); // sqlquery.prepare(DELETE_FRIEND_IN_USERFRIENDS_SQL); sqlquery.addBindValue(myID); sqlquery.addBindValue(friendID); sqlquery.addBindValue(friendID); sqlquery.addBindValue(myID); sqlquery.exec(); errorSQLOrder(sqlquery, "delete friends"); QSqlDatabase::database().commit(); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return MT_DELETE_FRIEND_FAIL; } return MT_DELETE_FRIEND_SUCCESS; } bool Database::addFriend(const TalkMessage &talMes)// { if(!createConnection()) { return false; } //sql QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(ADD_FRIEND_IN_USERFRIENDS_SQL); sqlquery.addBindValue(talMes.m_SenderID); sqlquery.addBindValue(talMes.m_ReceiverID); sqlquery.addBindValue(GROUP_NAME_DEFAULT); sqlquery.exec(); errorSQLOrder(sqlquery, "add friend from sender"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } sqlquery.clear(); sqlquery.prepare(ADD_FRIEND_IN_USERFRIENDS_SQL); sqlquery.addBindValue(talMes.m_ReceiverID); sqlquery.addBindValue(talMes.m_SenderID); sqlquery.addBindValue(GROUP_NAME_DEFAULT); sqlquery.exec(); errorSQLOrder(sqlquery, "add friend from recevier"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } QSqlDatabase::database().commit(); return true; } bool Database::insertValuesInDateCounter(const QDate &date)// DateCounterb { int count = 0; if (!createConnection()) { return false; } //sql QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(COUNT_DATARECORD_IN_DATECOUNTER_SQL); sqlquery.addBindValue(date.toString("yyyy-MM-dd")); sqlquery.exec(); errorSQLOrder(sqlquery, "count-datecounter"); if(!sqlquery.isActive()) { qDebug() << "QUERY_FAIL::" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } if (sqlquery.next()) { count = sqlquery.value(0).toInt(); } if (count == 0) { sqlquery.prepare(INSERT_VALUES_IN_DATECOUNTER_SQL); sqlquery.addBindValue(date.toString("yyyy-MM-dd")); sqlquery.exec(); errorSQLOrder(sqlquery, "insert datecounter"); if (!sqlquery.isActive()) { qDebug() << "QUERY_FAIL::" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } if (sqlquery.numRowsAffected() <= 0) // SQL , -1, -1 { return false; } } QSqlDatabase::database().commit(); return true; } int Database::getUserTimes(const QDate &date)// +1= ID { int count = 0; if(!insertValuesInDateCounter(QDate::currentDate())) { return 0; } if(!createConnection()) { return 0; } //sql QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(SELECT_USERTIMES_IN_DATECOUNTER_SQL); sqlquery.addBindValue(date.toString("yyyy-MM-dd")); sqlquery.exec(); errorSQLOrder(sqlquery, "select usertimes"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } if(sqlquery.next()) { count = sqlquery.value(0).toInt(); } QSqlDatabase::database().commit(); return count + 1; } bool Database::increaseUserTimes(const QDate &date)// { if(!createConnection()) { return false; } //sql QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(INCREASE_USERTIMES_IN_DATECOUNTER_SQL); sqlquery.addBindValue(date.toString("yyyy-MM-dd")); sqlquery.exec(); errorSQLOrder(sqlquery, "increase usertimes"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } if(sqlquery.numRowsAffected() <= 0) { return false; } QSqlDatabase::database().commit(); return true; } int Database::moveFriendToGroup(const QString & myID, const QString & friendID, const QString & title, const QString & newTitle)// { if(!createConnection()) { return MT_MOVE_FRIEND_BOX_FAIL; } //sql QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(MOVE_FRIEND_IN_USERFREINS); sqlquery.addBindValue(title); sqlquery.addBindValue(newTitle); sqlquery.addBindValue(myID); sqlquery.addBindValue(friendID); sqlquery.exec(); errorSQLOrder(sqlquery, "move friend to group"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return MT_MOVE_FRIEND_BOX_FAIL; } if(sqlquery.numRowsAffected() <= 0) { return MT_MOVE_FRIEND_BOX_FAIL; } QSqlDatabase::database().commit(); return MT_MOVE_FRIEND_BOX_SUCCESS; } int Database::renameGroup(const QString & id, const QString & title, const QString & newTitle)// { if (!createConnection()) { return MT_RENAME_BOX_FAIL; } //sql QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(RENAME_GROUPNAME_IN_USERFREINS); sqlquery.addBindValue(newTitle); sqlquery.addBindValue(id); sqlquery.addBindValue(title); sqlquery.exec(); errorSQLOrder(sqlquery, "rename-group"); if (!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return MT_RENAME_BOX_FAIL; } if (sqlquery.numRowsAffected() <= 0) { return MT_RENAME_BOX_FAIL; } QSqlDatabase::database().commit(); return MT_RENAME_BOX_SUCCESS; } bool Database::addHistoryMsg(const TalkMessage &talMes)// { if (!createConnection()) { return false; } //sql QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(INSERT_MESSAGE_IN_HISTORYMESSAGE); sqlquery.addBindValue(talMes.m_SenderID); sqlquery.addBindValue(talMes.m_ReceiverID); sqlquery.addBindValue(simplifyRichText(talMes.m_Text)); sqlquery.addBindValue(talMes.m_dateTime); sqlquery.exec(); errorSQLOrder(sqlquery, "inser-mes-to-HistoryMmesage"); if (!sqlquery.isActive()) { qDebug() << "QUERY_FAIL::" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } if(sqlquery.numRowsAffected() <= 0) { return false; } QSqlDatabase::database().commit(); return true; } bool Database::addOfflineMsg(const TalkMessage &talMes)// { if(!createConnection()) { return false; } //sql QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(INSERT_MESSAGE_IN_OFFLINEMESSAGE); sqlquery.addBindValue(talMes.m_Type); sqlquery.addBindValue(talMes.m_SenderID); sqlquery.addBindValue(talMes.m_ReceiverID); sqlquery.addBindValue(talMes.m_Text); sqlquery.exec(); errorSQLOrder(sqlquery, "insert talmes to offline message"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } if(sqlquery.numRowsAffected() <= 0) { return false; } QSqlDatabase::database().commit(); return true; } // int Database::searchHistoryMsgOfFriendInDate(const QString & myID, const QString &friendID, const QDate & date, QVector<TalkMessage> & mesVec) { if(!createConnection()) { return MT_GET_HISTORY_MESSAGE_FAIL; } //sql QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(SEARCH_FRIEND_DATE_MESSAGE_IN_HISTORYMESSAGE); sqlquery.addBindValue(myID); sqlquery.addBindValue(friendID); sqlquery.addBindValue(date); sqlquery.exec(); errorSQLOrder(sqlquery, "get history msg of friend in oneDay"); QSqlDatabase::database().commit(); if(!sqlquery.isActive()) { m_SqlDatabase->close(); return MT_GET_HISTORY_MESSAGE_FAIL; } mesVec.clear(); // while(sqlquery.next()) { TalkMessage talMes; talMes.m_SenderID = sqlquery.value(0).toString(); talMes.m_SenderIP = sqlquery.value(1).toString(); talMes.m_ReceiverID = sqlquery.value(2).toString(); talMes.m_ReceiverIP = sqlquery.value(3).toString(); talMes.m_dateTime = sqlquery.value(4).toDateTime(); talMes.m_Type = sqlquery.value(5).toInt(); talMes.m_Text = sqlquery.value(6).toString(); mesVec.push_back(talMes); // STL , append(value) } if(mesVec.isEmpty()) { return MT_NO_MESSAGE; } return MT_GET_HISTORY_MESSAGE_SUCCESS; }

ServerSocket.h
/*********************************************
File Name: ServerSocket.h
Description:       socket,        
********************************************/
#ifndef SERVERSOCKET_H
#define SERVERSOCKET_H
#include 
#include "Database.h"
#include "Structure.h"

class QDateTime;

class ServerSocket:public QTcpSocket
{
    Q_OBJECT
public:
    ServerSocket(QObject *parent = nullptr);
    ~ServerSocket();

signals:
       //   server  
       void sendSignal(const SaveTmpInformation &tmp);
       //     
       void userLoginSignal(const UserInformation &userInf);
       //      
       void deleteSignal(const QString &acc);

public slots:
       //     
       void receiveMessage();
       //     
       void sendMessage(const SaveTmpInformation &tmp);
       //   socket
       void deleteScoket();

   private:
       quint16 m_BlockSize;

       SaveTmpInformation m_SaveTmpInfo;

       Database m_Database;
};

#endif // SERVERSOCKET_H

ServerSocket.cpp
/*********************************************
File Name: ServerSocket.cpp
Description:        socket  
                     QTcpSocket 
********************************************/
#include "ServerSocket.h"
#include 
#include 

ServerSocket::ServerSocket(QObject *parent):
    QTcpSocket(parent)
{
    connect(this, SIGNAL(readyRead()), this, SLOT(receiveMessage()));
    connect(this, SIGNAL(disconnected()), this, SLOT(deleteScoket()));
    m_BlockSize = 0;
    m_SaveTmpInfo.m_ServerSocket = this;
}

ServerSocket::~ServerSocket()
{
    if (m_Database.isOpen())
        m_Database.close();
}

void ServerSocket::receiveMessage() //         
{
    QDataStream in(this);
    in.setVersion(QDataStream::Qt_5_11); //  QDataStream        
    if(m_BlockSize == 0)
    {
        if(bytesAvailable() < (int)sizeof (quint16)) //bytesAvailable()            
        {
            return;
        }
        in >> m_BlockSize;
    }
    if(bytesAvailable() < m_BlockSize)
    {
        return;
    }
    in >> m_SaveTmpInfo.m_RequestKind; //               
    qDebug() << "receive message:" << m_SaveTmpInfo.m_RequestKind;

    switch (m_SaveTmpInfo.m_RequestKind)
    {
        case MT_CHECK_CONNECTION:
        {
            m_SaveTmpInfo.m_ReplyKind = MT_CHECK_CONNECTION;
            sendMessage(m_SaveTmpInfo);
            m_BlockSize = 0;
            break;
        }
        case MT_LOGIN:
        {
            in >> m_SaveTmpInfo.m_LoginInf;
            m_SaveTmpInfo.m_MyID = m_SaveTmpInfo.m_LoginInf.m_UserID;
            m_SaveTmpInfo.m_SocketID = m_SaveTmpInfo.m_MyID;
            break;
        }
        case MT_CHECK_MESSAGE:
        {
            in >> m_SaveTmpInfo.m_MyID;
            break;
        }
        case MT_REGISTER:
        {
            in >> m_SaveTmpInfo.m_UserInf;
            break;
        }
        case MT_GET_QUESTION_ANSWER:
        {
            in >> m_SaveTmpInfo.m_MyID;
            break;
        }
        case MT_TALK:
        {
            in >> m_SaveTmpInfo.m_Message;
            break;
        }
        case MT_GET_ALL_FRIENDS:
        {
            in >> m_SaveTmpInfo.m_MyID >> m_SaveTmpInfo.m_Status;
            m_SaveTmpInfo.m_SocketID = m_SaveTmpInfo.m_MyID;
            break;
        }
        case MT_GET_FRIEND_INFORMATION:
        {
            in >> m_SaveTmpInfo.m_PeerID;
            break;
        }
        case MT_GET_MYSELF_INFORMATION:
        {
            in >> m_SaveTmpInfo.m_MyID;
            break;
        }
        case MT_CHANGE_INFORMATION:
        {
            in >> m_SaveTmpInfo.m_UserInf;
            break;
        }
        case MT_CHANGE_REMARK:
        {
            in >> m_SaveTmpInfo.m_TempStr;
            break;
        }
        case MT_CHANGE_STATUE:
        {
            in >> m_SaveTmpInfo.m_MyID >> m_SaveTmpInfo.m_Status;
            break;
        }
        case MT_ADD_FRIEND:
        {
            in >> m_SaveTmpInfo.m_Message;
            break;
        }
        case MT_REFUSE_FRIEND:
        {
            break;
        }
        case MT_DELETE_FRIEND:
        {
            in >> m_SaveTmpInfo.m_MyID >> m_SaveTmpInfo.m_PeerID;
            break;
        }
        case MT_REMOVE_BOX:
        case MT_CREATE_BOX:
        {
            in >> m_SaveTmpInfo.m_MyID >> m_SaveTmpInfo.m_Title;
            break;
        }
        case MT_MOVE_FRIEND_BOX:
        {
            in >> m_SaveTmpInfo.m_MyID >> m_SaveTmpInfo.m_PeerID >> m_SaveTmpInfo.m_Title >> m_SaveTmpInfo.m_NewTitle;
            break;
        }
        case MT_RENAME_BOX:
        {
            in >> m_SaveTmpInfo.m_MyID >> m_SaveTmpInfo.m_Title >> m_SaveTmpInfo.m_NewTitle;
            break;
        }
        case MT_GET_HISTORY_MESSAGE:
        {
            in >> m_SaveTmpInfo.m_MyID >> m_SaveTmpInfo.m_PeerID >> m_SaveTmpInfo.m_Date;
            break;
        }
        case MT_CHANGE_PASSWORD:
        {
            in >> m_SaveTmpInfo.m_TempStr;
            break;
        }
        default:
        {
            qDebug() << "Unknow receive msg kind:" << m_SaveTmpInfo.m_RequestKind;
            break;
        }
    }
    QByteArray data = this->readAll(); //           ,           
    qDebug() << "leave in socket:" << data.size();

    m_BlockSize = 0;
    emit sendSignal(m_SaveTmpInfo);
}

void ServerSocket::sendMessage(const SaveTmpInformation &tmp) //    
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_5_11);
    out << quint16(0) << (int)tmp.m_ReplyKind;

    switch(tmp.m_ReplyKind)
    {
        case MT_LOGIN_SUCCESS:
        {
            out << tmp.m_UserInf;
            break;
        }
        case MT_REGISTER_SUCCESS:
        {
            out << tmp.m_UserInf.m_UserID << tmp.m_UserInf.m_HeadPortrait;
            break;
        }
        case MT_GET_QUESTION_ANSWER_SUCCESS:
        {
            out << tmp.m_TempStr;
            break;
        }
        case MT_GET_ALL_FRIENDS_SUCCESS:
        {
            int len = tmp.m_FriendsVec.size();
            out << len;
            for(int i = 0;i < len;++i)
            {
                out << tmp.m_FriendsVec[i];
            }
            break;
        }
        case MT_HAVE_MESSAGE:
        {
            break;
        }
        case MT_CHANGE_STATUE:
        {
            out << tmp.m_PeerID << tmp.m_Status;
            break;
        }
        case MT_GET_MYSELF_SUCCESS:
        {
            out << tmp.m_UserInf;
            break;
        }
        case MT_DELETE_FRIEND_SUCCESS:
        {
            out << tmp.m_MyID << tmp.m_PeerID << tmp.m_GroupName;
            break;
        }
        case MT_CHANGE_INFORMATION_SUCCESS:
        {
            out << tmp.m_UserInf;
            break;
        }
        case MT_CHANGE_INFORMATION:
        {
            out << tmp.m_FriendInf;
            break;
        }
        case MT_ADD_FRIEND_SUCCESS:
        {
            out << tmp.m_Message << tmp.m_UserInf;
            break;
        }
        case MT_GET_FRIEND_SUCCESS:
        {
            out << tmp.m_UserInf;
            break;
        }
        case MT_TALK:
        {
            out << tmp.m_Message;
            break;
        }
        case MT_CHANGE_REMARK_SUCCESS:
        {
            out << tmp.m_TempStr;
            break;
        }
        case MT_BE_DELETED:
        {
            out << tmp.m_MyID << tmp.m_PeerID << tmp.m_GroupNameF;
            break;
        }
        case MT_RENAME_BOX_SUCCESS:
        {
            out << tmp.m_MyID << tmp.m_Title << tmp.m_NewTitle;
            break;
        }
        case MT_MOVE_FRIEND_BOX_SUCCESS:
        {
            out << tmp.m_MyID << tmp.m_PeerID << tmp.m_Title << tmp.m_NewTitle;
            break;
        }
        case MT_GET_HISTORY_MESSAGE_SUCCESS:
        {
            out << tmp.m_MyID << tmp.m_PeerID << tmp.m_Date;
            int len = tmp.m_HistoryMessageVec.size();
            out << len;
            for(int i = 0;i < len;++i)
            {
                out << tmp.m_HistoryMessageVec[i];
            }
            break;
        }
        default:
        {
            qDebug() << "unknown send msg kind:" << m_SaveTmpInfo.m_RequestKind;
            break;
        }
    }
    //QIODevice *QDataStream::device()       I/O  ,           ,   0
    out.device()->seek(0);//QIODevice::seek(quint16)       pos,    true,    false
    out << quint16(block.size() - sizeof(quint16));
    write(block); //      maxSize         ,          ;      ,   -1
}

void ServerSocket::deleteScoket() //  socket
{
    if(!m_SaveTmpInfo.m_SocketID.isEmpty())
    {
        if(MT_LOGIN != m_SaveTmpInfo.m_RequestKind)
        {
            emit deleteSignal(m_SaveTmpInfo.m_SocketID);
        }
        deleteLater();
    }
}


TcpServer.h
/*********************************************
File Name: TcpServer.h
Description:     
********************************************/
#ifndef TCPSERVER_H
#define TCPSERVER_H

#include 
#include "ServerSocket.h"
#include "Structure.h"
#include "Database.h"

class TcpServer:public QTcpServer
{
    Q_OBJECT
public:
    TcpServer(QObject *parent = nullptr);
    ~TcpServer();

public slots:
    //       
    void clientDisconnected(const QString &id);
    //  ServerSocket    
    void sendMessage(const SaveTmpInformation &tmp);

signals:
    void haveNewID(const QString &id);
    void haveNewAddress(const QString &address);
    void haveLeftID(const QString &id);
    void haveLeftAddress(const QString &address);

private:
    //        ,      。           socket  
    void incomingConnection(int socketDescriptor);
    //       
    void friendRequest(const SaveTmpInformation &savTmp);
    //       
    void talkRequest(const SaveTmpInformation &save);
    //     ,      
    void tellFriendsStatusChanged(const QString &id, int status);
    //     ,      
    void tellFriendsInformationChanged(const QString &id);

    //     
    SaveTmpInformation m_SaveTmpInfo;
    //      
    Database m_Database;
    //       
    QMap<QString, ServerSocket*> m_mapOnlineUser;
    //       
    QMap<QString, int> m_mapOnlineUserStatus;
    //        
    QMap<QString, ServerSocket*> m_mapOnlineUserMail;
};

#endif // TCPSERVER_H

TcpServer.cpp
#include "TcpServer.h"

TcpServer::TcpServer(QObject *parent) :
    QTcpServer(parent)
{
    //         
}

TcpServer::~TcpServer()
{

}

void TcpServer::clientDisconnected(const QString &id) //       
{
    //          ,         
    if(id.contains(MAIL_ADDRESS_FORMAT))//contains():              str,   true,    false
    {
        m_mapOnlineUserMail.remove(id);//remove():       ,   1,       map   0
        emit haveLeftAddress(id);
    }
    else
    {
        m_mapOnlineUser.remove(id);
        emit haveLeftID(id);
        if(m_Database.updateStatus(LS_OFFLINE, id))
        {
            tellFriendsStatusChanged(id, LS_OFFLINE);
        }
    }
#ifdef TEST_SWITCH
    qDebug() << "userMap-size:" <<m_mapOnlineUser.size();
    QMapIterator<QString, ServerSocket*> i(m_mapOnlineUser);
    while (i.hasNext())
    {
        i.next();
        qDebug() << i.key();
    }
    qDebug() << "userMailMap-size:" << m_mapOnlineUserMail.size();
    QMapIterator<QString, ServerSocket*> j(m_mapOnlineUser);
    while(j.hasNext())
    {
        j.next();
        qDebug() << j.key();
    }
#endif
}

void TcpServer::sendMessage(const SaveTmpInformation &tmp)//    ,  ServerSocket    
{
    m_SaveTmpInfo.m_RequestKind = tmp.m_RequestKind;
    //  tmp.requestKind     
    switch(m_SaveTmpInfo.m_RequestKind)
    {
        case MT_LOGIN:
        {
            m_SaveTmpInfo.m_LoginInf = tmp.m_LoginInf;
            m_SaveTmpInfo.m_ServerSocket = tmp.m_ServerSocket;
            //        
            m_SaveTmpInfo.m_MyID = tmp.m_MyID;
            if(m_mapOnlineUser.contains(m_SaveTmpInfo.m_MyID))
            {
                m_SaveTmpInfo.m_ReplyKind = MT_HAVE_LOGINED;
            }
            else
            {
                //       
                m_SaveTmpInfo.m_ReplyKind = m_Database.searchUserInUserInformation(m_SaveTmpInfo.m_LoginInf, m_SaveTmpInfo.m_UserInf);
            }
            tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo);
            break;
        }
        case MT_REGISTER://  
        {
            m_SaveTmpInfo.m_UserInf = tmp.m_UserInf;
            int count = m_Database.getUserTimes(QDate::currentDate());
            if(count == 0)
            {
                m_SaveTmpInfo.m_ReplyKind = MT_REGISTER_FAIL;
            }
            else
            {
                QString id = QDate::currentDate().toString("yyyyMMdd");
                id.append(QString::number(0));
                id.append(QString::number(count));
                m_SaveTmpInfo.m_UserInf.m_UserID = id;
                m_SaveTmpInfo.m_UserInf.m_RegDateTime = QDateTime::currentDateTime();
                //       
                m_SaveTmpInfo.m_ReplyKind = m_Database.addUserInUserInformation(m_SaveTmpInfo.m_UserInf);
            }
            tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo);
            break;
        }
        case MT_GET_QUESTION_ANSWER://         
        {
            m_SaveTmpInfo.m_MyID = tmp.m_MyID;
            m_SaveTmpInfo.m_ReplyKind = m_Database.searchQuestionAndAnswer(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_TempStr);
            tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo);
            break;
        }
        case MT_CHECK_MESSAGE://    
        {
            break;
        }
        case MT_GET_ALL_FRIENDS://      
        {
            m_SaveTmpInfo.m_MyID = tmp.m_MyID;
            m_SaveTmpInfo.m_Status = tmp.m_Status;
            m_SaveTmpInfo.m_ServerSocket = tmp.m_ServerSocket;
            m_SaveTmpInfo.m_ReplyKind = m_Database.searchFriendsInformation(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_FriendsVec);
            tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo);
            if(MT_GET_ALL_FRIENDS_FAIL != m_SaveTmpInfo.m_ReplyKind)
            {
                if(!m_mapOnlineUser.contains(m_SaveTmpInfo.m_MyID))
                {
                    m_mapOnlineUser.insert(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_ServerSocket);
                    emit haveNewID(m_SaveTmpInfo.m_MyID);
                }
                tellFriendsStatusChanged(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_Status);
            }
            break;
        }
        case MT_TALK://    
        {
            talkRequest(tmp);
            break;
        }
        case MT_CHANGE_INFORMATION://        
        {
            m_SaveTmpInfo.m_UserInf = tmp.m_UserInf;
            m_SaveTmpInfo.m_ReplyKind = m_Database.updateMyselfInformation(tmp.m_UserInf);
            tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo);
            if(m_SaveTmpInfo.m_ReplyKind == MT_CHANGE_INFORMATION_SUCCESS)
            {
                tellFriendsInformationChanged(m_SaveTmpInfo.m_UserInf.m_UserID);
            }
            break;
        }
        case MT_GET_MYSELF_INFORMATION://      
        {
            m_SaveTmpInfo.m_MyID = tmp.m_MyID;
            m_SaveTmpInfo.m_ReplyKind = m_Database.searchMyselfInformationByID(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_UserInf);
            tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo);
            break;
        }
        case MT_GET_FRIEND_INFORMATION://      
        {
            m_SaveTmpInfo.m_PeerID = tmp.m_PeerID;
            m_SaveTmpInfo.m_ReplyKind = m_Database.searchFriendInformationByID(m_SaveTmpInfo.m_PeerID, m_SaveTmpInfo.m_UserInf);
            tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo);
            break;
        }
        case MT_DELETE_FRIEND://    
        {
            m_SaveTmpInfo.m_MyID = tmp.m_MyID;
            m_SaveTmpInfo.m_PeerID = tmp.m_MyID;
            m_SaveTmpInfo.m_ReplyKind = m_Database.deleteFriend(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_PeerID,
                                                                m_SaveTmpInfo.m_GroupName,m_SaveTmpInfo.m_GroupNameF);
            tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo);

            //              ,        
            QMap<QString, ServerSocket*>::iterator iter;
            //find(const Key &key):       ,         key  ,                end(),                            
            iter = m_mapOnlineUser.find(m_SaveTmpInfo.m_PeerID);
            if(m_mapOnlineUser.end() == iter) //    STL      ,                      
            {
                TalkMessage talMes;
                talMes.m_Type = MT_BE_DELETED;
                talMes.m_SenderID = tmp.m_MyID;
                talMes.m_ReceiverID = tmp.m_PeerID;
                talMes.m_Text = tmp.m_GroupNameF;
            }
            else
            {
                m_SaveTmpInfo.m_MyID = tmp.m_PeerID;
                m_SaveTmpInfo.m_PeerID = tmp.m_MyID;
                m_SaveTmpInfo.m_ReplyKind = MT_BE_DELETED;
                m_SaveTmpInfo.m_GroupName = tmp.m_GroupNameF;
                //T &iterator::value() const,              
                iter.value()->sendMessage(m_SaveTmpInfo);
            }
            break;
        }
        case MT_CHANGE_REMARK://    
        {
            m_SaveTmpInfo.m_TempStr = tmp.m_TempStr;
            m_SaveTmpInfo.m_ReplyKind = m_Database.updateRemark(tmp.m_TempStr);
            tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo);
            break;
        }
        case MT_ADD_FRIEND://    
        {
            friendRequest(tmp);
            break;
        }
        case MT_CHANGE_STATUE://      
        {
            if(m_Database.updateStatus(tmp.m_Status, tmp.m_MyID))
            {
                tellFriendsStatusChanged(tmp.m_MyID, tmp.m_Status);
            }
            break;
        }
        case MT_REMOVE_BOX://    
        {
            m_SaveTmpInfo.m_MyID = tmp.m_MyID;
            m_SaveTmpInfo.m_Title = tmp.m_Title;
            break;
        }
        case MT_CREATE_BOX://    
        {
            m_SaveTmpInfo.m_MyID = tmp.m_MyID;
            m_SaveTmpInfo.m_Title = tmp.m_Title;
            break;
        }
        case MT_MOVE_FRIEND_BOX://         
        {
            m_SaveTmpInfo.m_MyID = tmp.m_MyID;
            m_SaveTmpInfo.m_Title = tmp.m_Title;
            m_SaveTmpInfo.m_PeerID = tmp.m_PeerID;
            m_SaveTmpInfo.m_NewTitle = tmp.m_NewTitle;
            m_SaveTmpInfo.m_ReplyKind = m_Database.moveFriendToGroup(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_PeerID,
                                                                     m_SaveTmpInfo.m_Title, m_SaveTmpInfo.m_NewTitle);
            tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo);
            break;
        }
        case MT_RENAME_BOX://     
        {
            m_SaveTmpInfo.m_MyID = tmp.m_MyID;
            m_SaveTmpInfo.m_Title = tmp.m_Title;
            m_SaveTmpInfo.m_NewTitle = tmp.m_NewTitle;
            m_SaveTmpInfo.m_ReplyKind = m_Database.renameGroup(m_SaveTmpInfo.m_MyID,
                                                               m_SaveTmpInfo.m_Title, m_SaveTmpInfo.m_NewTitle);
            tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo);
            break;
        }
        case MT_GET_HISTORY_MESSAGE://               
        {
            m_SaveTmpInfo.m_MyID = tmp.m_MyID;
            m_SaveTmpInfo.m_PeerID = tmp.m_PeerID;
            m_SaveTmpInfo.m_Date = tmp.m_Date;
            m_SaveTmpInfo.m_ReplyKind = m_Database.searchHistoryMsgOfFriendInDate(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_PeerID,
                                                                                  m_SaveTmpInfo.m_Date, m_SaveTmpInfo.m_HistoryMessageVec);
            tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo);
            break;
        }
        case MT_CHANGE_PASSWORD://    
        {
            m_SaveTmpInfo.m_TempStr = tmp.m_TempStr;
            m_SaveTmpInfo.m_ReplyKind = m_Database.updatePassword(m_SaveTmpInfo.m_TempStr);
            tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo);
            break;
        }
        default:
        {
            break;
        }
    }
}

void TcpServer::incomingConnection(int socketDescriptor) //       ,      ,           socket  
{
    //     ,          
    ServerSocket *serverSocket = new ServerSocket(this);
    serverSocket->setSocketDescriptor(socketDescriptor);
    connect(serverSocket, SIGNAL(deleteSignal(const QString&)),
            this, SLOT(clientDisconnected(const QString&)));
    connect(serverSocket, SIGNAL(sendSignal(const SaveTmpInformation&)),
            this, SLOT(sendMessage(const SaveTmpInformation&)));

    qDebug() << "new client IP:" << serverSocket->peerAddress();
    qDebug() << "userMap-size:" << m_mapOnlineUser.size();

#ifdef TEST_SWITCH
    QMapIterator<QString, ServerSocket *> i(m_mapOnlineUser);
       while (i.hasNext()) {
           i.next();
           qDebug() << i.key();
       }

       qDebug() << "userMailMap-size:" << m_mapOnlineUserMail.size();
       QMapIterator<QString, ServerSocket *> j(m_mapOnlineUserMail);
       while (j.hasNext()) {
           j.next();
           qDebug() << j.key();
       }
#endif
}

void TcpServer::friendRequest(const SaveTmpInformation &savTmp) //        
{
    m_SaveTmpInfo.m_ReplyKind = MT_ADD_FRIEND;
    m_SaveTmpInfo.m_Message = savTmp.m_Message;
    switch(savTmp.m_Message.m_Type)
    {
        case MT_REQUEST_FRIEND:
        {
            if(MT_ADD_FRIEND_SUCCESS != m_Database.searchFriendInformationByID(m_SaveTmpInfo.m_Message.m_SenderID,
                                                                               m_SaveTmpInfo.m_UserInf))
            {
                return;
            }
            qDebug() << "request add friend";
            break;
        }
        case MT_REFUSE_FRIEND:
        {
            qDebug() << "refuse add friend";
            break;
        }
        case MT_AGREE_FRIEND:
        {
            if(!m_Database.addFriend(m_SaveTmpInfo.m_Message))
            {
                m_SaveTmpInfo.m_Message.m_Type = MT_ADD_FRIEND_FAIL;
                break;
            }
            m_SaveTmpInfo.m_Message.m_SenderID = savTmp.m_Message.m_ReceiverID;
            m_SaveTmpInfo.m_Message.m_ReceiverID = savTmp.m_Message.m_SenderID;
            if(MT_GET_FRIEND_SUCCESS != m_Database.searchFriendInformationByID(m_SaveTmpInfo.m_Message.m_SenderID,
                                                                               m_SaveTmpInfo.m_UserInf))
            {
                m_SaveTmpInfo.m_Message.m_Type = MT_ADD_FRIEND_FAIL;
                return;
            }
            qDebug() << "agree add friend";
            break;
        }
        default:
        {
        return;
        }
    }
    QMap<QString, ServerSocket*>::iterator iter;
    iter = m_mapOnlineUser.find(m_SaveTmpInfo.m_Message.m_ReceiverID);
    if(m_mapOnlineUser.end() == iter)
    {
        //save offline msg
    }
    else
    {
        iter.value()->sendMessage(m_SaveTmpInfo);
    }
}

void TcpServer::talkRequest(const SaveTmpInformation &savTmp) //      
{
    m_SaveTmpInfo.m_Message = savTmp.m_Message;
    switch(m_SaveTmpInfo.m_Message.m_Type)
    {
        case MT_TALK_MESSAGE:
        {
            m_SaveTmpInfo.m_ReplyKind = MT_TALK;
            QMap<QString, ServerSocket*>::iterator iter;
            iter = m_mapOnlineUser.find(m_SaveTmpInfo.m_Message.m_ReceiverID);

            //          
            m_Database.addHistoryMsg(m_SaveTmpInfo.m_Message);
            if(m_mapOnlineUser.end() == iter)
            {
                //          
                m_Database.addOfflineMsg(m_SaveTmpInfo.m_Message);
            }
            else
            {
                iter.value()->sendMessage(m_SaveTmpInfo);
            }
            break;
        }
        default:
        {
            break;
        }
    }
}

void TcpServer::tellFriendsStatusChanged(const QString &id, int status) //    ,      
{
    m_SaveTmpInfo.m_ReplyKind = MT_CHANGE_STATUE;
    m_SaveTmpInfo.m_Status = status;
    m_SaveTmpInfo.m_PeerID = id;
    m_Database.searchFriendsID(id, m_SaveTmpInfo.m_IDVec);

    QMap<QString, ServerSocket*>::iterator iter;
    for(int i = 0;i < m_SaveTmpInfo.m_IDVec.size();i++)
    {
        iter = m_mapOnlineUser.find(m_SaveTmpInfo.m_IDVec[i]);
        if(iter != m_mapOnlineUser.end())
        {
            iter.value()->sendMessage(m_SaveTmpInfo);
        }
    }
}

void TcpServer::tellFriendsInformationChanged(const QString &id) //    ,      
{
    m_SaveTmpInfo.m_ReplyKind = MT_CHANGE_INFORMATION;
    if(!m_Database.searchFriendsID(id, m_SaveTmpInfo.m_IDVec))
    {
        return;
    }
    m_SaveTmpInfo.m_FriendInf.m_HeadPortrait = m_SaveTmpInfo.m_UserInf.m_HeadPortrait;
    m_SaveTmpInfo.m_FriendInf.m_NickName = m_SaveTmpInfo.m_UserInf.m_NickName;
    m_SaveTmpInfo.m_FriendInf.m_UserID = m_SaveTmpInfo.m_UserInf.m_UserID;
    m_SaveTmpInfo.m_FriendInf.m_Status = m_SaveTmpInfo.m_UserInf.m_Status;

    QMap<QString, ServerSocket*>::iterator iter;
    for(int i = 0;i < m_SaveTmpInfo.m_IDVec.size();i++)
    {
        iter = m_mapOnlineUser.find(m_SaveTmpInfo.m_IDVec[i]);
        if(iter != m_mapOnlineUser.end())
        {
            iter.value()->sendMessage(m_SaveTmpInfo);
        }
    }
}