diff --git a/CMakeLists.txt b/CMakeLists.txt index d52b8f7..1541e44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,8 @@ else() resource.qrc sessionfriendarea.h sessionfriendarea.cpp debug.h + messageshowarea.h messageshowarea.cpp + messageeditarea.h messageeditarea.cpp ) endif() endif() diff --git a/mainwidget.cpp b/mainwidget.cpp index 16a54e6..1979681 100644 --- a/mainwidget.cpp +++ b/mainwidget.cpp @@ -61,7 +61,7 @@ void MainWidget::initMainWindow() windowLeft->setFixedWidth(70); - windowMid->setFixedWidth(310); + windowMid->setFixedWidth(820); windowRight->setMinimumWidth(900); windowLeft->setStyleSheet("QWidget { background-color: rgb(46, 46, 46); }"); @@ -163,7 +163,57 @@ void MainWidget::initMidWindow() void MainWidget::initRightWindow() { + //创建右侧窗口的布局管理器 + QVBoxLayout* vlayout = new QVBoxLayout(); + vlayout->setSpacing(0); + vlayout->setContentsMargins(0, 0, 0, 0); + vlayout->setAlignment(Qt::AlignTop); + windowRight->setLayout(vlayout); + //创建上方的标题栏 + QWidget* titleWidget = new QWidget(); + titleWidget->setFixedHeight(62); + titleWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + titleWidget->setObjectName("titleWidget"); + titleWidget->setStyleSheet(R"(#titleWidget { border-bottom: 1px solid rgb(230, 230, 230); + border-left: 1px solid rgb(230, 230, 230); } + )"); + vlayout->addWidget(titleWidget); + + //给标题栏添加 label 和 button + QHBoxLayout* hlayout = new QHBoxLayout(); + hlayout->setSpacing(0); + hlayout->setContentsMargins(10, 0, 10, 0); + titleWidget->setLayout(hlayout); + + QLabel* sessionTitleLabel = new QLabel(); + sessionTitleLabel->setStyleSheet("QLabel { font-size: 22px; border-bottom: 1px solid rgb(230, 230, 230); }"); + +#if TEST_UI + //为了测试仅填充从服务器获取的数据 + sessionTitleLabel->setText("TEST TITLE"); +#endif + + hlayout->addWidget(sessionTitleLabel); + + QPushButton* extraBtn = new QPushButton(); + extraBtn->setFixedSize(30, 30); + extraBtn->setIconSize(QSize(30, 30)); + extraBtn->setIcon(QIcon(":/resource/image/more.png")); + extraBtn->setStyleSheet(R"(QPushButton { border: none; background-color: transparent; } + QPushButton:pressed { background-color: rgb(210, 210 ,210); } + )"); + hlayout->addWidget(extraBtn); + + + //添加消息展示区 + messageShowArea = new MessageShowArea(); + vlayout->addWidget(messageShowArea); + + //添加消息编辑区 + messageEditArea = new MessageEditArea(); + //确保消息编辑区处于窗口正下方 + vlayout->addWidget(messageEditArea, 0, Qt::AlignBottom); } void MainWidget::initSignalSlot() diff --git a/mainwidget.h b/mainwidget.h index 45db1a1..d11f35d 100644 --- a/mainwidget.h +++ b/mainwidget.h @@ -5,6 +5,10 @@ #include #include +#include "debug.h" +#include "messageeditarea.h" +#include "messageshowarea.h" + QT_BEGIN_NAMESPACE namespace Ui { class MainWidget; @@ -48,6 +52,12 @@ private: //添加好友按钮 QPushButton* addFriendBtn; + //消息展示区 + MessageShowArea* messageShowArea; + + //消息编辑区 + MessageEditArea* messageEditArea; + enum ActiveTab { SESSION_LIST, FRIEND_LIST, diff --git a/messageeditarea.cpp b/messageeditarea.cpp new file mode 100644 index 0000000..0e4d0f5 --- /dev/null +++ b/messageeditarea.cpp @@ -0,0 +1,5 @@ +#include "messageeditarea.h" + +MessageEditArea::MessageEditArea(QWidget *parent) + : QWidget{parent} +{} diff --git a/messageeditarea.h b/messageeditarea.h new file mode 100644 index 0000000..8638e13 --- /dev/null +++ b/messageeditarea.h @@ -0,0 +1,15 @@ +#ifndef MESSAGEEDITAREA_H +#define MESSAGEEDITAREA_H + +#include + +class MessageEditArea : public QWidget +{ + Q_OBJECT +public: + explicit MessageEditArea(QWidget *parent = nullptr); + +signals: +}; + +#endif // MESSAGEEDITAREA_H diff --git a/messageshowarea.cpp b/messageshowarea.cpp new file mode 100644 index 0000000..ce06939 --- /dev/null +++ b/messageshowarea.cpp @@ -0,0 +1,71 @@ +#include "messageshowarea.h" + +MessageShowArea::MessageShowArea() { + //初始化基本属性 + this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + this->setWidgetResizable(true); + + //设置滚动条样式 + this->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 2px; background-color: rgb(240, 240, 240); }"); + this->horizontalScrollBar()->setStyleSheet("QScrollBar:horizontal { height: 0; }"); + this->setStyleSheet("QScrollArea { border: none; }"); + + //创建container这样的widget,作为包含内部元素的容器 + container = new QWidget(); + this->setWidget(container); + + //给container添加界面布局管理器 + QVBoxLayout* layout = new QVBoxLayout(); + layout->setSpacing(0); + layout->setContentsMargins(0, 0, 0, 0); + container->setLayout(layout); +} + +//////////////////////////////////////////// +/// 表示一个消息元素 +//////////////////////////////////////////// +MessageItem::MessageItem(bool isLeft) + :isLeft(isLeft) +{ + +} + +MessageItem *MessageItem::makeMessageItem(bool isLeft, const Message &message) +{ + //创建对象和布局管理器 + MessageItem* messageItem = new MessageItem(isLeft); + QGridLayout* layout = new QGridLayout(); + layout->setSpacing(0); + layout->setContentsMargins(0, 0, 0, 0); + + //这个message最低不能低于100 + messageItem->setMinimumHeight(100); + messageItem->setLayout(layout); + + //创建头像 + QPushButton* avatarBtn = new QPushButton(); + avatarBtn->setFixedSize(40, 40); + avatarBtn->setIconSize(QSize(40, 40)); + avatarBtn->setIcon(message.sender.avatar); + if(isLeft) { + layout->addWidget(avatarBtn, 0, 0, 2, 1, Qt::AlignTop | Qt::AlignLeft); + } else { + layout->addWidget(avatarBtn, 0, 1, 2, 1, Qt::AlignTop | Qt::AlignRight); + } + + //创建名字和时间 + QLabel* nameLabel = new QLabel(); + nameLabel->setText(message.sender.nickname + " | " + message.time); + nameLabel->setAlignment(Qt::AlignBottom); + nameLabel->setStyleSheet("QLabel { font-size: 12px; color: rgb(178, 178, 178); }"); + if(isLeft) { + layout->addWidget(nameLabel, 0, 1); + } else { + layout->addWidget(nameLabel, 0, 0, Qt::AlignRight); + } + + //创建消息体 + + + return messageItem; +} diff --git a/messageshowarea.h b/messageshowarea.h new file mode 100644 index 0000000..81d1e94 --- /dev/null +++ b/messageshowarea.h @@ -0,0 +1,45 @@ +#ifndef MESSAGESHOWAREA_H +#define MESSAGESHOWAREA_H + +#include +#include +#include +#include +#include +#include + +#include "model/data.h" + +//.h文件中,不宜使用namespace xxx +using model::Message; + +//////////////////////////////////////////// +/// 表示消息展示区 +//////////////////////////////////////////// +class MessageShowArea : public QScrollArea +{ + Q_OBJECT +public: + MessageShowArea(); + +private: + QWidget* container; +}; + +//////////////////////////////////////////// +/// 表示一个消息元素 +/// 我们可能考虑要同时支持文本,文件,图片,视频,语音 +//////////////////////////////////////////// +class MessageItem : public QWidget { +public: + //isLeft表示当前的这个消息是否是左侧的消息 + MessageItem(bool isLeft); + + //通过工厂方法创建MessageItem实例 + static MessageItem* makeMessageItem(bool isLeft, const Message& message); + +private: + bool isLeft; +}; + +#endif // MESSAGESHOWAREA_H diff --git a/sessionfriendarea.cpp b/sessionfriendarea.cpp index 557c16a..fdb98c5 100644 --- a/sessionfriendarea.cpp +++ b/sessionfriendarea.cpp @@ -49,7 +49,7 @@ SessionFriendArea::SessionFriendArea(QWidget *parent) // 把widget创建出来 container = new QWidget(); - container->setFixedWidth(310); + container->setMinimumWidth(310); this->setWidget(container); //给这个widget添加布局管理器方便后续添加元素进去 @@ -68,6 +68,8 @@ SessionFriendArea::SessionFriendArea(QWidget *parent) // } //构造一些临时数据作为界面调试的依据 + + #if TEST_UI QIcon icon(":/resource/image/defaultAv.png"); for(int i = 0; i < 30; i++) { @@ -81,8 +83,10 @@ SessionFriendItem::SessionFriendItem(QWidget* owner, const QIcon& avatar, const :owner(owner) { this->setFixedHeight(70); + this->setStyleSheet("QWidget { background-color: rgb(231, 231, 231); }"); + //创建网格布局管理器 QGridLayout* layout = new QGridLayout(); layout->setContentsMargins(20, 0, 0, 0); @@ -104,21 +108,22 @@ SessionFriendItem::SessionFriendItem(QWidget* owner, const QIcon& avatar, const //创建名字 QLabel* nameLabel = new QLabel(); nameLabel->setText(name); - nameLabel->setStyleSheet("QLabel { font-size: 18px; fontweight: 600; }"); + nameLabel->setStyleSheet("QLabel { font-size: 18px; font-weight: 600; }"); nameLabel->setFixedHeight(35); nameLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); //创建消息预览的label QLabel* messageLabel = new QLabel(); messageLabel->setText(text); - messageLabel->setStyleSheet("QLabel { font-size: 18px; fontweight: 600; }"); + messageLabel->setStyleSheet("QLabel { font-size: 18px; font-weight: 600; }"); messageLabel->setFixedHeight(35); messageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + //添加到网格布局 layout->addWidget(avatarBtn, 0, 0, 2, 2); - layout->addWidget(nameLabel, 0, 2, 1, 1); - layout->addWidget(messageLabel, 1, 2, 1, 1); + layout->addWidget(nameLabel, 0, 2, 1, 8); + layout->addWidget(messageLabel, 1, 2, 1, 8); } void SessionFriendItem::paintEvent(QPaintEvent *event) @@ -178,6 +183,15 @@ void SessionFriendItem::select() //点击时修改背景色 this->setStyleSheet("QWidget { background-color: rgb(210, 210, 210); }"); this->selected = true; + + //调用Active + this->active(); +} + +void SessionFriendItem::active() +{ + //父类不写 + //并不需要实现任何逻辑 } void SessionFriendArea::clear() @@ -251,6 +265,12 @@ SessionItem::SessionItem(QWidget *owner, const QString &chatSessionId, const QIc } +void SessionItem::active() +{ + //点击之后,要加载会话历史消息的列表 + LOG() << "click SessionItem... chatSessionId: " << chatSessionId; +} + //////////////////////////////////////// /// 好友Item的实现 //////////////////////////////////////// @@ -261,6 +281,12 @@ FriendItem::FriendItem(QWidget *owner, const QString &userId, const QIcon &avata } +void FriendItem::active() +{ + //点击之后,要激活对应的会话列元素 + LOG() << "click FriendItem... userId: " << userId; +} + //////////////////////////////////////// /// 好友申请Item的实现 //////////////////////////////////////// @@ -268,5 +294,26 @@ ApplyItem::ApplyItem(QWidget *owner, const QString &userId, const QIcon &avatar, const QString &name) :SessionFriendItem(owner, avatar, name, ""), userId(userId) { + //移除父类的messageLabel + QGridLayout* layout = dynamic_cast(this->layout()); + layout->removeWidget(messageLabel); + //要记得释放内存,否则会内存泄露 + // delete messageLabel; + + //创建两个按钮 + QPushButton* acceptBtn = new QPushButton(); + acceptBtn->setText("同意"); + QPushButton* rejectBtn = new QPushButton(); + rejectBtn->setText("拒绝"); + + //添加到布局管理器中 + layout->addWidget(acceptBtn, 1, 2, 1, 1); + layout->addWidget(rejectBtn, 1, 3, 1, 1); } + +void ApplyItem::active() +{ + //本就不需要实现任何内容 + LOG() << "click ApplyItem... userId: " << userId; +} diff --git a/sessionfriendarea.h b/sessionfriendarea.h index 03c8407..9e2cc31 100644 --- a/sessionfriendarea.h +++ b/sessionfriendarea.h @@ -15,7 +15,7 @@ #include #include #include "model/data.h" - +#include //////////////////////////////////////// @@ -73,12 +73,18 @@ public: void select(); + //Active实现Item被点击后的业务逻辑 + virtual void active(); + private: //owner 就是指向了 SessionFriendArea QWidget* owner; //表示当前的Item是否是选中的状态(选中时其背景色会有所不同) bool selected = false; + +protected: + QLabel* messageLabel; }; //////////////////////////////////////// @@ -88,7 +94,10 @@ class SessionItem : public SessionFriendItem { Q_OBJECT public: - SessionItem(QWidget* owner, const QString& chatSessionId, const QIcon& avatar, const QString& name, const QString& lastmessage); + SessionItem(QWidget* owner, const QString& chatSessionId, const QIcon& avatar, + const QString& name, const QString& lastmessage); + + void active() override; private: //当前会话Id QString chatSessionId; @@ -102,6 +111,7 @@ class FriendItem : public SessionFriendItem { Q_OBJECT public: FriendItem(QWidget* owner, const QString& userId, const QIcon& avatar, const QString& name, const QString& description); + void active() override; private: // 好友的用户Id QString userId; @@ -115,6 +125,7 @@ class ApplyItem : public SessionFriendItem { public: ApplyItem(QWidget* owner, const QString& userId, const QIcon& avatar, const QString& name); + void active() override; private: //好友申请Id QString userId;