improve ui and add historymessagewidget model

This commit is contained in:
xyz
2025-06-06 17:33:29 +08:00
parent 62460933aa
commit 0811720e4d
6 changed files with 319 additions and 38 deletions

1
.gitignore vendored
View File

@ -5,6 +5,7 @@ CMakeLists.txt.user
.idea/
.vscode/
.vs/
Android/
*.iml
*.suo
*.vsidx

View File

@ -18,33 +18,6 @@ else()
set(QT_VERSION_MAJOR 6)
endif()
#set(PROJECT_SOURCES
# main.cpp
# mainwidget.cpp
# mainwidget.h
# mainwidget.ui
# model/data.h
# resource.qrc
# sessionfriendarea.h
# sessionfriendarea.cpp
# debug.h
# messageshowarea.h
# messageshowarea.cpp
# messageeditarea.h
# messageeditarea.cpp
# SelfInfoWidget.h
# SelfInfoWidget.cpp
# userinfowidget.h
# userinfowidget.cpp
# sessiondetailwidget.h
# sessiondetailwidget.cpp
# choosefrienddialog.h
# choosefrienddialog.cpp
# groupsessiondetailwidget.h
# groupsessiondetailwidget.cpp
#)
file(GLOB PROJECT_SOURCES
model/*.h
*.cpp
@ -53,14 +26,20 @@ file(GLOB PROJECT_SOURCES
*.qrc
)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
if(ANDROID)
# Android 平台:附加 Android 可部署资源
qt_add_executable(ClientChat
MANUAL_FINALIZATION
${PROJECT_SOURCES}
)
# 指定自定义的 Android 部署目录
set_property(TARGET ClientChat APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
else()
if(ANDROID)
add_library(ClientChat SHARED ${PROJECT_SOURCES})
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(ClientChat
MANUAL_FINALIZATION
${PROJECT_SOURCES}
)
else()
add_executable(ClientChat ${PROJECT_SOURCES})
endif()
@ -68,13 +47,12 @@ endif()
target_link_libraries(ClientChat PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
include(GNUInstallDirs)
install(TARGETS ClientChat
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
if(QT_VERSION_MAJOR EQUAL 6)
if(${QT_VERSION_MAJOR} EQUAL 6)
qt_finalize_executable(ClientChat)
endif()
include(GNUInstallDirs)
install(TARGETS ClientChat
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

238
historymessagewidget.cpp Normal file
View File

@ -0,0 +1,238 @@
#include "historymessagewidget.h"
//工厂函数
HistoryItem* HistoryItem::makeHistoryItem(const Message& message)
{
// 1. 创建出对象
HistoryItem* item = new HistoryItem();
item->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
// 2. 创建布局
QGridLayout* layout = new QGridLayout();
layout->setVerticalSpacing(0);
layout->setHorizontalSpacing(10);
layout->setContentsMargins(0, 0, 0, 0);
item->setLayout(layout);
// 3. 创建头像
QPushButton* avatarBtn = new QPushButton();
avatarBtn->setFixedSize(40, 40);
avatarBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
avatarBtn->setIconSize(QSize(40, 40));
// 当前消息发送者的头像
avatarBtn->setIcon(message.sender.avatar);
avatarBtn->setStyleSheet("QPushButton { border: none; }");
// 4. 创建昵称和时间
QLabel* nameLabel = new QLabel();
nameLabel->setText(message.sender.nickname + " | " + message.time);
nameLabel->setFixedHeight(20); // 高度设置为头像高度的一半
nameLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
// 5. 消息内容部分
QWidget* contentWidget = nullptr;
if (message.messageType == model::MessageType::TEXT_TYPE) {
// 文本消息
QLabel* label = new QLabel();
label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
label->setWordWrap(true);
label->setText(QString(message.content));
label->adjustSize(); // 设置让 label 能够自动调整大小
contentWidget = label;
}
else if (message.messageType == model::MessageType::IMAGE_TYPE) {
// 图片消息
//contentWidget = new ImageButton(message.fileId, message.content);
}
else if (message.messageType == model::MessageType::FILE_TYPE) {
// 文件消息
//contentWidget = new FileLabel(message.fileId, message.fileName);
}
else if (message.messageType == model::MessageType::SPEECH_TYPE) {
// 语音消息
//contentWidget = new SpeechLabel(message.fileId);
}
else {
LOG() << "错误的消息类型! messageType=" << message.messageType;
}
// 6. 把上述控件添加到布局中
layout->addWidget(avatarBtn, 0, 0, 2, 1);
layout->addWidget(nameLabel, 0, 1, 1, 1);
layout->addWidget(contentWidget, 1, 1, 5, 1);
return item;
}
HistoryMessageWidget::HistoryMessageWidget(QWidget *parent)
: QDialog(parent)
{
// 1. 设置窗口本身属性
this->setFixedSize(600, 600);
this->setWindowTitle("历史消息");
this->setWindowIcon(QIcon(":/resource/image/logo.png"));
this->setStyleSheet("QWidget { background-color: rgb(255, 255, 255); }");
this->setAttribute(Qt::WA_DeleteOnClose);
// 2. 创建布局管理器.
QGridLayout* layout = new QGridLayout();
layout->setSpacing(10);
layout->setContentsMargins(30, 30, 30, 0);
this->setLayout(layout);
// 3. 创建单选按钮
keyRadioBtn = new QRadioButton();
timeRadioBtn = new QRadioButton();
keyRadioBtn->setText("按关键词查询");
timeRadioBtn->setText("按时间查询");
// 默认按照关键词查询
keyRadioBtn->setChecked(true);
layout->addWidget(keyRadioBtn, 0, 0, 1, 2);
layout->addWidget(timeRadioBtn, 0, 2, 1, 2);
// 4. 创建搜索框
searchEdit = new QLineEdit();
searchEdit->setFixedHeight(50);
searchEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
searchEdit->setPlaceholderText("要搜索的关键词");
searchEdit->setStyleSheet("QLineEdit { border: none; border-radius: 10px; color: rgb(129, 129, 129); background-color: rgb(240, 240, 240); font-size: 16px; padding-left: 10px; }");
layout->addWidget(searchEdit, 1, 0, 1, 8);
// 5. 创建搜索按钮
QPushButton* searchBtn = new QPushButton();
searchBtn->setFixedSize(50, 50);
searchBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
searchBtn->setIconSize(QSize(30, 30));
searchBtn->setIcon(QIcon(":/resource/image/search.png"));
QString btnStyle = "QPushButton { border: none; background-color: rgb(240, 240, 240); border-radius: 10px; }";
btnStyle += "QPushButton:pressed { background-color: rgb(220, 220, 220); }";
searchBtn->setStyleSheet(btnStyle);
layout->addWidget(searchBtn, 1, 8, 1, 1);
// 6. 创建时间相关的部分控件, 初始情况下要隐藏
QLabel* begTag = new QLabel();
begTag->setText("开始时间");
QLabel* endTag = new QLabel();
endTag->setText("结束时间");
begTimeEdit = new QDateTimeEdit();
endTimeEdit = new QDateTimeEdit();
begTimeEdit->setStyleSheet("QDateTimeEdit { color: rgb(0, 0, 0); } ");
endTimeEdit->setStyleSheet("QDateTimeEdit { color: rgb(0, 0, 0); } ");
// [联调新增]
begTimeEdit->setDisplayFormat("yyyy-MM-dd hh:mm");
endTimeEdit->setDisplayFormat("yyyy-MM-dd hh:mm");
begTimeEdit->setFixedHeight(40);
endTimeEdit->setFixedHeight(40);
begTag->hide();
endTag->hide();
begTimeEdit->hide();
endTimeEdit->hide();
// 7. 创建滚动区域
initScrollArea(layout);
// 8. 设置槽函数
connect(keyRadioBtn, &QRadioButton::clicked, this, [=]() {
// 把时间相关的控件, 隐藏起来
layout->removeWidget(begTag);
layout->removeWidget(begTimeEdit);
layout->removeWidget(endTag);
layout->removeWidget(endTimeEdit);
begTag->hide();
begTimeEdit->hide();
endTag->hide();
endTimeEdit->hide();
// 把关键词搜索框显示加入布局
layout->addWidget(searchEdit, 1, 0, 1, 8);
searchEdit->show();
});
connect(timeRadioBtn, &QRadioButton::clicked, this, [=]() {
// 关键词搜索框隐藏并从布局中删除掉.
layout->removeWidget(searchEdit);
searchEdit->hide();
// 把时间相关的控件, 添加到布局中, 并且进行显示.
layout->addWidget(begTag, 1, 0, 1, 1);
layout->addWidget(begTimeEdit, 1, 1, 1, 3);
layout->addWidget(endTag, 1, 4, 1, 1);
layout->addWidget(endTimeEdit, 1, 5, 1, 3);
begTag->show();
begTimeEdit->show();
endTag->show();
endTimeEdit->show();
});
//connect(searchBtn, &QPushButton::clicked, this, &HistoryMessageWidget::clickSearchBtn);
// 构造测试数据
#if TEST_UI
for (int i = 0; i < 30; ++i) {
// 注意此处代码和前面的差别.
// 前面有个代码, UserInfo 必须要 new 出来才能构造. 当时 Item 对象里, 持有了 const UserInfo& , 不是 new 的话
// 就可能使引用指向的对象失效的.
// 此处后续的代码, 都是按照传值的方式来使用 message 的内容, 不 new 也行.
model::UserInfo sender;
sender.userId = "";
sender.nickname = "张三" + QString::number(i);
sender.avatar = QIcon(":/resource/image/defaultAvatar.png");
sender.description = "";
sender.phone = "18612345678";
Message message = Message::makeMessage(model::MessageType::TEXT_TYPE, "", sender, QString("消息内容" + QString::number(i)).toUtf8(), "");
this->addHistoryMessage(message);
}
#endif
}
void HistoryMessageWidget::addHistoryMessage(const Message& message)
{
HistoryItem* item = HistoryItem::makeHistoryItem(message);
container->layout()->addWidget(item);
}
void HistoryMessageWidget::clear()
{
QVBoxLayout* layout = dynamic_cast<QVBoxLayout*>(container->layout());
for (int i = layout->count() - 1; i >= 0; i--) {
//之前使用的是takeat效果和这个是一样的
QWidget* w = layout->itemAt(i)->widget();
if (w == nullptr) {
continue;
}
layout->removeWidget(w);
w->deleteLater();
}
}
void HistoryMessageWidget::initScrollArea(QGridLayout* layout)
{
// 1. 创建滚动区域对象
QScrollArea* scrollArea = new QScrollArea();
scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
scrollArea->setWidgetResizable(true);
scrollArea->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 2px; background-color: rgb(255, 255, 255); }");
scrollArea->horizontalScrollBar()->setStyleSheet("QScrollBar:horizontal { height: 0; }");
scrollArea->setStyleSheet("QScrollArea { border: none; }");
// 2. 创建 QWidget, 持有要加入的新的内容
container = new QWidget();
scrollArea->setWidget(container);
// 3. 创建 container 中的布局管理器.
QVBoxLayout* vlayout = new QVBoxLayout();
vlayout->setSpacing(10);
vlayout->setContentsMargins(0, 0, 0, 0);
vlayout->setAlignment(Qt::AlignTop);
container->setLayout(vlayout);
// 4. 把滚动区加入到整个 layout 中
layout->addWidget(scrollArea, 2, 0, 1, 9);
}

58
historymessagewidget.h Normal file
View File

@ -0,0 +1,58 @@
#pragma once
#include <QDialog>
#include <QGridLayout>
#include <QRadioButton>
#include <QLineEdit>
#include <QPushButton>
#include <QLabel>
#include <QDateTimeEdit>
#include <QScrollArea>
#include <QScrollBar>
#include <QFileDialog>
#include "debug.h"
#include "model/data.h"
using model::Message;
////////////////////////////////////////////////////////////////////
/// 表示一个历史消息元素
////////////////////////////////////////////////////////////////////
class HistoryItem : public QWidget {
Q_OBJECT
public:
HistoryItem() {}
static HistoryItem* makeHistoryItem(const Message& message);
};
////////////////////////////////////////////////////////////////////
/// 展示历史消息窗口
////////////////////////////////////////////////////////////////////
class HistoryMessageWidget : public QDialog
{
Q_OBJECT
public:
HistoryMessageWidget(QWidget *parent);
//在窗口中添加一个历史消息
void addHistoryMessage(const Message& message);
//清空窗口中所有的历史消息
void clear();
private:
void initScrollArea(QGridLayout* layout);
QRadioButton* keyRadioBtn;
QRadioButton* timeRadioBtn;
QLineEdit* searchEdit;
QDateTimeEdit* begTimeEdit;
QDateTimeEdit* endTimeEdit;
//持有所有的历史消息结果的容器对象
QWidget* container;
};

View File

@ -177,6 +177,10 @@ MessageEditArea::MessageEditArea(QWidget *parent)
vlayout->addWidget(sendTextButton, 0, Qt::AlignRight | Qt::AlignVCenter);
connect(showHistoryBtn, &QPushButton::clicked, this, [=]() {
HistoryMessageWidget* historyMessageWidget = new HistoryMessageWidget(this);
historyMessageWidget->exec();
});
}

View File

@ -11,6 +11,8 @@
//#include <qpropertyanimation.h>
//#include <QEvent>
#include "historymessagewidget.h"
//编辑消息的区域
class MessageEditArea : public QWidget
{