40.qt quick – high imitation wechat to realize LAN chat V4 Version (support GIF dynamic image expression package, message chat, drag and zoom window, support Linux compilation)

Time:2021-12-8

In the previous chapter37.qt quick – high imitation wechat to achieve LAN chat V3 Version (add login interface, UDP verification login, skin replacement, 3D rotation), we have achieved:

  • Add login interface
  • UDP verification login
  • Skin replacement
  • 3D rotation (switching between main interface and login interface)

Therefore, this chapter realizes:

  • Supports dragging and changing window size
  • You can chat alone or everyone in the chat room
  • Support sending and receiving GIF expression packages (support pasting and copying)
  • Automatically refresh the current number of friends online
  • It supports both Linux and windows compilation and operation

 

1. Interface display

The interface layout is as follows:

The screenshot of the interface is as follows:

The renderings are as follows:

It’s a little big. It may not load, but it has been uploaded to BiliBilihttps://www.bilibili.com/video/BV1Ao4y1S7zX

Since the amount of code is a little large, the key part is explained

 

2. Support Linux compilation

Here I cross compile to raspberry pie, and cancel 3D rotation under Linux, as shown in the following figure:

  The moving picture will not be uploaded. The video has been uploaded to BiliBili https://www.bilibili.com/video/BV1JU4y1H7xc/

 

3. GIF management in text

3.1 add a GIF in text

//Add a gif
void GifTextHandler::inset(QString fileName)
{
    if (!m_documnt)
        return;

    QTextCursor  cursor = QTextCursor(m_documnt->textDocument());
    cursor.setPosition(m_cursorStart);
    if (m_cursorStart > m_cursorEnd) {
        cursor.setPosition(0);
    } else if (m_cursorStart != m_cursorEnd)
        cursor.setPosition(m_cursorEnd, QTextCursor::KeepAnchor);

    addMovie(fileName); //  Load a GIF through qmovie
    QTextImageFormat imageFormat;
    imageFormat.setName(fileName);
    imageFormat.setWidth(m_width);
    imageFormat.setHeight(m_height);
    cursor.insertImage(imageFormat, QTextFrameFormat::InFlow);

}

After adding a GIF, how to manage the GIF? If I delete the GIF in the current text, the qmovie should also be released, otherwise it will overflow memory

 

three point two   Gif dynamic release and management

So read the text every 1 second. Check whether GIF still exists. If it does not exist, release qmovie:

QList list = m_movies.keys();
        for(int i=0;isetProperty("status",false);
        }

        QTextBlock block = m_documnt->textDocument()->firstBlock();
        QVector allFormats = m_documnt->textDocument()->allFormats();
        while(block.isValid()) {
             QTextBlockFormat blockFmt = block.blockFormat();
             for(QTextBlock::iterator it = block.begin(); !it.atEnd(); it++) {
                QTextCharFormat charFmt = it.fragment().charFormat();   //  Fragment is a class for storing text and location
                if (charFmt.objectType() == QTextFormat::ImageObject) {
                    QString file = charFmt.property(QTextFormat::ImageName).toString();
                    if (!m_movies.contains(file)) {
                        addMovie(file);
                    }
                    m_movies[file]->setProperty("status",true);
                   // qDebug()<property("status") == false) {
                    qDebug()<

If the text is released, the entire GIF table is traversed to release all:

Giftexthandler:: ~ giftexthandler() // release resources
{
    QList list = m_movies.keys();
    for(int i=0;i

 

three point three   text messaging

Since the text contains GIF diagram, we need to encode the text content (including GIF) and convert it into a string when sending. The code is as follows:

QString GifTextHandler::coding()
{
    QString ret("");
    QTextBlock block = m_documnt->textDocument()->firstBlock();
    QVector allFormats = m_documnt->textDocument()->allFormats();

    while(block.isValid()) {
         for(QTextBlock::iterator it = block.begin(); !it.atEnd(); it++) {
            QTextCharFormat charFmt = it.fragment().charFormat();   //  Fragment is a class for storing text and location
            if (charFmt.objectType() == QTextFormat::ImageObject) {
             ret.append("["+charFmt.property(QTextFormat::ImageName).toString().remove(GIF_PREFIXDIR)+"]");
            } else {
                ret.append(it.fragment().text());
            }
         }
         If (block. Next(). Isvalid()) // qtextblock is divided into each block by substitution behavior, so a newline character needs to be added after each block traversal
            ret.append("\r\n");

         block = block.next();
    }
    return ret;
}

 

three point four   Text reception

Since the received data is a string, we need to decode and display the GIF flag as a GIF graph. The code is as follows:

void GifTextHandler::encoding(QString text)
{
    if (!m_documnt) {
        qDebug()<textDocument());
    cursor.setPosition(0);
    QRegularExpression re("\\[\\d+\\.gif\\]");
    QRegularExpressionMatch match;
    int offset = 0;
    int fileNum;
    QString file;
    QString ret;
    while (offset < text.length()) {
        match = re.match(text,offset);
        if (match.hasMatch()) {
            sscanf(match.captured(0).toLocal8Bit(),"[%d.gif]", &fileNum);
            file = QString(GIF_PREFIXDIR+"%1.gif").arg(fileNum);
            cursor.insertText(text.mid(offset, match.capturedStart(0) - offset));   //  Add previous
            ret.append(text.mid(offset, match.capturedStart(0) - offset));
            addMovie(file);
            QTextImageFormat imageFormat;
            imageFormat.setName(file);
            imageFormat.setWidth(m_width);
            imageFormat.setHeight(m_height);
            cursor.insertImage(imageFormat, QTextFrameFormat::InFlow);
            offset = match.capturedEnd(0);
        } else {
            ret.append(text.mid(offset, text.length() - offset));
            cursor.insertText(text.mid(offset, text.length() - offset));   //  Add previous
            break;
        }
    }
}

 

 

4.C++   Qabstractlistmodel class

Listview is used in QML, and C + + model is used for model data (inherited from qabstractlistmodel)

Therefore, when a friend goes online, we need to add a line of friend data to the model and notify listview to refresh local data. The code is as follows:

void FriendModel::addFriend(MessageDesc* msg)
{
    for (int i=1; i < m_data.count(); i++) {
        if (m_data[i]->title() == msg->srcUser) {
            return;
        }
    }
    //Convert avatar arr data into JPG file
    QPixmap pixmap;
    QString str = AppCfg::getInstance()->read(AppCfg::FriendHeadDir).remove("file:///")+msg->srcUser+".jpg";
    qDebug()<headArr.length()<headArr.data(), msg->headArr.length());
    bool ret = pixmap.save(str);
    AppCfg::getInstance()->fileLogWrite(QString("addFriend str%1  str%2 ret%3").arg(str).arg(QUrl::fromLocalFile(str).toString()).
                                        arg(ret));

    beginInsertRows(QModelIndex(), 1, 1);   //  Since the chat room is always on top, it can only be inserted into line 2
    m_data.insert(1, new FriendChatData(msg->srcUser, QUrl::fromLocalFile(str).toString()));
    endInsertRows();
    Hintinsetchatroom ("\" "+ MSG - > srcuser +" \ "on" + qdatetime:: currentdatetime(). ToString ("HH: mm") + "online!");
}

When a friend goes offline, you need to delete the friend data. The code is as follows:

void FriendModel::removeFriend(MessageDesc* msg)
{
    for (int i=1; i < m_data.count(); i++) {
        if (m_data[i]->title() == msg->srcUser) {
            beginRemoveRows(QModelIndex(), i, i);

            //If the model of the chat interface is equal to the current offline friends, you need to release the chat model data and refresh the view
            if (m_chat != NULL && m_chat->data() == m_data[i]) {
                delete m_chat;
                m_chat = NULL;
                emit removeFriendcloseChat();
            }
            delete m_data[i];
            m_data.removeAt(i);
            endRemoveRows();
            Hintinsetchatroom ("\" "+ MSG - > srcuser +" \ "on" + qdatetime:: currentdatetime(). ToString ("HH: mm") + "offline!");
            break;
        }
    }
}

When sending and receiving messages, other friends can follow suit