仿QQ聊天项目(二)

目前可以聊天啦。。下面是截图


动手锻炼锻炼。。学习到了数据库、网络编程、多线程方面的知识。。感觉还是蛮好的。。等待进一步优化添加功能吧。。

下面贴上服务端和客户端的头文件。

#ifndef CLIENTCONTROLLER_H
#define CLIENTCONTROLLER_H
class ClientSocket;
class Client_UI;
class login;
#include
   
    
class ClientController :public QObject
{
    Q_OBJECT
public:
    ClientController();
private:
    ClientSocket*  clientSocket;
    Client_UI*     clientUI;
    login*         loginUI;
private slots:
    void OnTryLogin(QString account, QString password);
    void OnPermitLogin(quint32 ID, QString &name, QString &sign, quint32 picNumber);
    void OnRefuseLogin();
//    void OnReceiveFriendMessage(quint32 ID,QString& Message);
//    void OnSendMessage(quint32 ID, QString& Message);

};

#endif // CLIENTCONTROLLER_H
#ifndef CLIENTSOCKET_H
#define CLIENTSOCKET_H
#include 
    
     

class ClientSocket : public QTcpSocket
{
    Q_OBJECT
public:
    ClientSocket(const QString& hostAddress,
                 const QString& port,
                 const QString& account,
                 const QString& password,
                 QObject* parent =0 );
    enum Client_msgType{msg_login,msg_offLine,msg_SendMessage,msg_SearchFriend,msg_AddFriend};//枚举消息类型
    enum Server_msgType{msg_permitLogin,
                        msg_refuseLogin,
                        msg_FriendMessage,
                        msg_systemMessage,
                        msg_ContactorInformation = 10,
                        msg_CreateList,
                        msg_FriendOnline,
                        msg_FriendOffline};//枚举服务端发送来的消息类型
private:
    QString account;
    QString password;
    quint16 blockSize;
private slots:
    void Translate_Message();//解析服务端发送来的消息
    void tryLogin();//尝试登录
    void OnReceiveMessage();
    void SendMessage(quint32 ID, QString &Message);
    void OnSocketError(QAbstractSocket::SocketError socketError);
//    void offLine();    //下线
//    void SendMessage(quint32 ID,QString& message); //发送消息给好友
//    void SearchFriend(QString& cmd);//查找好友
//    void AddFriend(quint32 ID);//添加好友

//    void OnPermitLogin();//允许登录
//    void OnRefuseLogin();//拒绝登录
//    void OnCreateList(QString& GroupName);//创建列表
//    void OnReceiveContactorInformation(quint32 ID,
//                                     QString& groupName,
//                                     QString& name,
//                                     quint32& picNumber,
//                                     QString& sign,
//                                     bool     online);//获得好友信息
//    void OnReceiveFriendMessage(quint32 ID,QString& message);//收到来自好友的消息
//    void OnReceiveSystemMessage(QString& message);//收到系统消息


signals:
    void permitLogin(quint32 ID,QString& name,QString& sign,quint32 picnNumber);//允许登录
    void refuseLogin();//拒绝登录
    void ReceiveContactorInformation(QString& groupName,
                                     quint32 ID,
                                     QString& name,                                    
                                     QString& sign,
                                     quint32  picNumber,
                                     bool     online);//获得好友信息
    void ReceiveFriendMessage(quint32 ID,QString& message);//收到来自好友的消息
//    void ReceiveSystemMessage(QString& message);//收到系统消息
    void CreateList(QString& GroupName);//创建列表



};

#endif // CLIENTSOCKET_H
#ifndef LOGIN_H
#define LOGIN_H

#include 
     
      
#include 
      
       
namespace Ui {
class login;
}

class login : public QWidget
{
    Q_OBJECT

public:
    explicit login(QWidget *parent = 0);
    ~login();

private:
    Ui::login *ui;

protected:
    void mousePressEvent(QMouseEvent *);
    void mouseMoveEvent(QMouseEvent *);
    void paintEvent(QPaintEvent*);

private:
    QPoint dragPosition;
    QPixmap pic;
//    QSqlDatabase    database;
private slots:
    void OnLoginButtonPressed();
    void OnRefuseLogin();
signals:
    void login_request(QString account,QString password);


};

#endif // LOGIN_H
#ifndef UITREEWIDGETITEM_H
#define UITREEWIDGETITEM_H
#include
       
         class uiTreeWidgetItem :public QTreeWidgetItem { private: quint32 Id; QString Name; QString Sign; quint32 PicNumber; public: uiTreeWidgetItem(quint32 ID,QString& name,QString&sign,quint32 picNumber); quint32 ID(); QString name(); QString sign(); quint32 picNumber(); bool hasReceiveMessage; }; #endif // UITREEWIDGETITEM_H #include "client_ui.h" #include "ui_client_ui.h" #include
        
          #include
         
           #include
          
            #include"../TreeWidgetTest/mytreewidgetitem.h" #include"../MusicPlayer/no_focus_delegate.h" #include
           
             #include
            
              #include"../QChat_Dialog/dialog.h" #include"uitreewidgetitem.h" #include
             
               #include
              
                Client_UI::Client_UI(quint32 ID, QString &name, QString sign, quint32 picNumber, QWidget *parent) : QWidget(parent), ui(new Ui::Client_UI) { ui->setupUi(this); setWindowFlags(Qt::FramelessWindowHint);//设置窗体无边框 //setAttribute(Qt::WA_TranslucentBackground);//设置背景透明 initButton(); initContactorWiget(); ui->sign_label->setText(sign); ui->ID_label->setText(name+"("+QVariant(ID).toString()+")"); QPixmap pic("./head/"+QVariant(picNumber).toString()+".png"); ui->personal_iamge->setPixmap(pic); dialog = new Dialog; connect(dialog,SIGNAL(SendMessage(quint32,QString&)),this,SLOT(DispSendMessage(quint32,QString&))); connect(ui->close_button,SIGNAL(clicked(bool)),SLOT(close())); connect(ui->minimize_button,SIGNAL(clicked(bool)),this,SLOT(showMinimized())); connect(ui->contactor_widget,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this,SLOT(OnTreeWidgetItemDobuleClick(QTreeWidgetItem*,int))); connect(dialog,SIGNAL(ChatDialogClose()),SLOT(OnChatDialogClose())); connect(dialog,SIGNAL(CurrentChatClose(quint32)),SLOT(OnCurrentChatClose(quint32))); } Client_UI::~Client_UI() { delete ui; } void Client_UI::mousePressEvent(QMouseEvent * event) { if (event->button() == Qt::LeftButton) { dragPosition = event->globalPos() - frameGeometry().topLeft(); event->accept(); } } void Client_UI::mouseMoveEvent(QMouseEvent * event) { if (event->buttons() & Qt::LeftButton) { move(event->globalPos() - dragPosition); event->accept(); } } void Client_UI::initButton() { //minimize and close buttons QString minimize_button_style = QString("QPushButton#minimize_button{\ border-image: url(:/image/client_ui/images/client_ui/client_minimize_button.png)}\ QPushButton#minimize_button:hover{\ border-image: url(:/image/client_ui/images/client_ui/client_minimize_button_hover.png)}" ); QString close_button_style = QString("QPushButton#close_button{\ border-image: url(:/image/client_ui/images/client_ui/client_close_button.png)}\ QPushButton#close_button:hover{\ border-image: url(:/image/client_ui/images/client_ui/client_close_button_hover.png)}"); ui->minimize_button->setStyleSheet(minimize_button_style); ui->close_button->setStyleSheet(close_button_style); //contactor button QString contactor_button_style = QString("QPushButton#contactor_button{\ border-image: url(:/image/client_ui/images/client_ui/contactor.png)}\ QPushButton#contactor_button:hover{\ border-image: url(:/image/client_ui/images/client_ui/contactor_hover.png)}\ QPushButton#contactor_button:pressed{\ border-image: url(:/image/client_ui/images/client_ui/contactor_pressed.png)}" ); \ ui->contactor_button->setStyleSheet(contactor_button_style); //group button QString group_button_style = QString("QPushButton#group_button{\ border-image: url(:/image/client_ui/images/client_ui/group.png)}\ QPushButton#group_button:hover{\ border-image: url(:/image/client_ui/images/client_ui/group_hover.png)}\ QPushButton#group_button:pressed{\ border-image: url(:/image/client_ui/images/client_ui/group_pressed.png)}" ); \ ui->group_button->setStyleSheet(group_button_style); //search button QString search_button_style = QString("QPushButton#search_button{\ border-image: url(:/image/client_ui/images/client_ui/search_button.png)}\ QPushButton#search_button:hover{\ border-image: url(:/image/client_ui/images/client_ui/search_button_hover.png)}" ); \ ui->search_button->setStyleSheet(search_button_style); } void Client_UI::initContactorWiget() { QTreeWidget* tree=ui->contactor_widget; tree->setColumnCount(1); tree->setIndentation(10); tree->setHeaderHidden(true); // tree->setRootIsDecorated(false); tree->setColumnWidth(0,200); /* for(int i=0;i<3;++i){ tree->addTopLevelItem(new QTreeWidgetItem(QStringList(tr("item%1").arg(i)))); for(int j=0;j<3;++j){ myTreeWidgetItem* item=new myTreeWidgetItem; tree->topLevelItem(i)->addChild(new QTreeWidgetItem); tree->topLevelItem(i)->child(j)->setSizeHint(0,item->size()); tree->setItemWidget(tree->topLevelItem(i)->child(j),0,item); } } */ tree->horizontalScrollBar()->hide(); QFile file(":/QSS/my_scrollBar.qss"); file.open(QFile::ReadOnly); tree->verticalScrollBar()->setStyleSheet(file.readAll()); file.close(); file.setFileName(":/QSS/my_treeview.qss"); file.open(QFile::ReadOnly); tree->setStyleSheet(file.readAll()); file.close(); QFont font=tree->font(); font.setPixelSize(15); tree->setFont(font); tree->resizeColumnToContents(0); // tree->setItemDelegate(new NoFocusDelegate); } void Client_UI::create_list(QString& groupname) //创建列表 { ui->contactor_widget->addTopLevelItem(new QTreeWidgetItem(QStringList(groupname))); //listname_index<<(list_name+QVariant(listname_index.size()).toString()); } void Client_UI::add2list(QString& groupname, //分组名 quint32 ID, QString& name, //昵称 QString& sign, //个性签名 quint32 picNumber, //图片 bool online) //是否在线 { QPixmap pic("./head/"+QVariant(picNumber).toString()+".png"); myTreeWidgetItem* item = new myTreeWidgetItem(name,ID,sign,pic,online); QTreeWidget* tree = ui->contactor_widget; QTreeWidgetItem* toplevelItem; int i=0; while(i
               
                topLevelItemCount()){ toplevelItem = ui->contactor_widget->topLevelItem(i); if(toplevelItem->text(0)== groupname){ //找到列表 break; } ++i; } if(i == tree->topLevelItemCount()){ //列表不存在,插入列表 create_list(groupname); toplevelItem = ui->contactor_widget->topLevelItem(i); } //插入信息 int childIndex = toplevelItem->childCount(); //下一个child的index toplevelItem->addChild(new uiTreeWidgetItem(ID,name,sign,picNumber)); toplevelItem->child(childIndex)->setSizeHint(0,item->size()); //调整item的大小 tree->setItemWidget(toplevelItem->child(childIndex),0,item); } void Client_UI::DispReceiveMessage(quint32 ID, QString &Message) { QTreeWidget* tree = ui->contactor_widget; //这不仅是建立会话的逻辑,也是图标闪烁的逻辑 for(int i=0;i
                
                 topLevelItemCount();++i){ for(int j=0;j
                 
                  topLevelItem(i)->childCount();++j){ uiTreeWidgetItem* temp = (uiTreeWidgetItem*)(tree->topLevelItem(i)->child(j)); if(temp->ID() == ID){ QString tempstring =temp->name()+"("+QVariant(ID).toString()+")" +" "+QTime::currentTime().toString(); if(temp->hasReceiveMessage == false){ //如果还没建立对话 QPixmap pic("./head/"+QVariant(temp->picNumber()).toString()+".png"); dialog->addConversation(pic,ID,temp->name(),temp->sign()); temp->hasReceiveMessage = true; dialog->show(); dialog->AppendMessage(tempstring); dialog->AppendMessage(Message); QString space("\n"); dialog->AppendMessage(space); qDebug()<<"来新对话了"; } else{ //已经建立对话了 dialog->AppendMessage(tempstring,ID); dialog->AppendMessage(Message,ID); QString space("\n"); dialog->AppendMessage(space,ID); qDebug()<<"来消息了"; } return; } } } } void Client_UI::DispSendMessage(quint32 ID,QString& Message) { QString temp = ui->ID_label->text()+" "+QTime::currentTime().toString(); dialog->AppendMessage(temp); dialog->AppendMessage(Message); QString space("\n"); dialog->AppendMessage(space); emit SendMessage(ID,Message); } void Client_UI::OnTreeWidgetItemDobuleClick(QTreeWidgetItem *item, int column) { for(int i=0;i
                  
                   contactor_widget->topLevelItemCount();++i){ if(item == ui->contactor_widget->topLevelItem(i)){ return; } } dialog->show(); uiTreeWidgetItem* temp = (uiTreeWidgetItem*)(item); if(temp->hasReceiveMessage) return; QPixmap pic("./head/"+QVariant(temp->picNumber()).toString()+".png"); dialog->addConversation(pic,temp->ID(),temp->name(),temp->sign()); temp->hasReceiveMessage = true; } void Client_UI::OnChatDialogClose() { QTreeWidget* tree = ui->contactor_widget; for(int i=0;i
                   
                    topLevelItemCount();++i){ for(int j=0;j
                    
                     topLevelItem(i)->childCount();++j){ uiTreeWidgetItem* temp = (uiTreeWidgetItem*)(tree->topLevelItem(i)->child(j)); if(temp->hasReceiveMessage) temp->hasReceiveMessage = false; } } } void Client_UI::OnCurrentChatClose(quint32 ID) { QTreeWidget* tree = ui->contactor_widget; for(int i=0;i
                     
                      topLevelItemCount();++i){ for(int j=0;j
                      
                       topLevelItem(i)->childCount();++j){ uiTreeWidgetItem* temp = (uiTreeWidgetItem*)(tree->topLevelItem(i)->child(j)); if(temp->ID() == ID){ temp->hasReceiveMessage = false; return; } } } } 
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
        
       
      
     
    
   
#ifndef SENDCONTACTORTHREAD_H
#define SENDCONTACTORTHREAD_H
#include 
    
     
#include
     
      
#include
      
       
#include
       
        
#include
        
          #include"dboperation.h" //这是一个发送联系人列表的线程 class SendContactorThread:public QThread { Q_OBJECT public: SendContactorThread(quint32 ID); enum msgType{msg_memberinfomation=10,msg_createList}; QList
         
           data; //用来存储待发送的消息 // QThread interface protected: void run() Q_DECL_OVERRIDE; private: // QStringList grouplist; //分组名 quint32 ID; //ID号 quint32 index; qintptr socketDescriptor; //套接字 static QList
          
            vcuumNumberList;//维护一个可用连接名的列表 static int usedNumberCount; //总个数,包括已经消失的连接 signals: void DataReadyRead(QList
           
            ); private slots: void OnFinished(); }; #endif // SENDCONTACTORTHREAD_H #ifndef SERVER_H #define SERVER_H #include
            
              #include
             
               class DbOperation; class sendAddressThread; class Server:public QTcpServer { Q_OBJECT public: Server(QObject* parent=0); private: sendAddressThread* thread; QList
              
                clientlist;//维护一张客户端socket列表 QList
               
                 vacuumIndex;//维护当前空白的序号列表 DbOperation* dboperation;//数据库操作 protected: void incomingConnection(qintptr socketDescriptor) Q_DECL_OVERRIDE; // void addPendingConnection(TcpClientSocket* tcpsocket) Q_DECL_OVERRIDE; ~Server(); private slots: void OnLoginRequest(QString& account,QString& password,TcpClientSocket* socket); void OnClientDisconnected(TcpClientSocket* socket); void OnSendMessage(quint32 ID,QString& message,TcpClientSocket* socket); public: enum Server_msgType{msg_permitLogin,msg_refuseLogin,msg_FriendMessage,msg_systemMessage};//枚举消息类型 }; #endif // SERVER_H #ifndef SOCKETTHREAD_H #define SOCKETTHREAD_H #include 
                
                  #include 
                 
                   class QMutex; class SocketThread:public QThread { Q_OBJECT public: SocketThread(qintptr socketDescriptor,QObject* parent=0); void run() Q_DECL_OVERRIDE; private: qintptr socketDescriptor; signals: void error(QTcpSocket::SocketError socketError); }; #endif // SOCKETTHREAD_H #ifndef TCPCLIENTSOCKET_H #define TCPCLIENTSOCKET_H #include 
                  
                    class TcpClientSocket:public QTcpSocket { Q_OBJECT public: explicit TcpClientSocket(QObject* parent=0); enum Client_msgType{msg_login,msg_offLine,msg_SendMessage,msg_SearchFriend,msg_AddFriend};//枚举消息类型 quint32 id(); signals: void loginRequest(QString& account,QString& password,TcpClientSocket* socket); //登录请求 void offLine(); //下线 void SendMessage(quint32 ID,QString& message,TcpClientSocket* socket); //发送消息 void SearchFriend(QString& cmd,TcpClientSocket* socket);//查找好友 void AddFriend(QString& account,TcpClientSocket* socket);//添加好友 void SocketDisconnect(TcpClientSocket* socket); private: qint16 blockSize; //数据块大小 QString account; //账号 quint32 ID; //数字ID void TranslateMessage(); public: quint32 index; //在LIST中的编号 void SetID(quint32 id); private slots: void OnReceiveMessage(); void OnDisConnected(); void OnDataReadyRead(QList
                   
                     Datalist); }; #endif // TCPCLIENTSOCKET_H #ifndef DBOPERATION_H #define DBOPERATION_H #include 
                    
                      #include 
                     
                       //数据库操作类 class DbOperation :public QObject { Q_OBJECT public: explicit DbOperation(const QString& name,const QString& connectionName);//打开数据库 bool comparePassword(const QString& account, const QString& password, QSqlRecord *&record);//比较账号密码 void GetContactors(quint32 ID, QStringList* GroupList, QList
                      
                        *friendid);//获取联系人列表和成员 QSqlRecord GetUserInformation(quint32 ID);//获取用户信息 bool AddRecord(quint32 ID, const QString& account, const QString& password, bool online, const QString& Login_ip, const QString& name, const QString& sign, quint32 picNumber);//插入一条记录 bool changePassword(quint32 ID,const QString& password); //修改密码 bool changePic(quint32 ID,quint32 picNmuber);//修改图片 void setOnline(quint32 ID);//上线 void setOffline(quint32 ID);//下线 ~DbOperation(); private: QSqlDatabase db; signals: void OpenDataBaseError();//打开数据库错误 }; #endif // DBOPERATION_H 
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
        
       
      
     
    


Guess you like

Origin blog.csdn.net/qq_16952303/article/details/51570396
qq