fix for presences in MUCs, fix for memory limit in message history, fix for message line resizing, started working on messages

This commit is contained in:
Blue 2019-09-10 17:33:39 +03:00
parent 139c0de0e3
commit 0574d6f72b
15 changed files with 332 additions and 95 deletions

View file

@ -35,6 +35,8 @@ Conversation::Conversation(bool muc, const QString& mJid, const QString mRes, co
line(new MessageLine(muc)),
m_ui(new Ui::Conversation()),
ker(),
res(),
vis(),
thread(),
statusIcon(0),
statusLabel(0),
@ -51,6 +53,9 @@ Conversation::Conversation(bool muc, const QString& mJid, const QString mRes, co
statusLabel = m_ui->statusLabel;
connect(&ker, SIGNAL(enterPressed()), this, SLOT(onEnterPressed()));
connect(&res, SIGNAL(resized()), this, SLOT(onScrollResize()));
connect(&vis, SIGNAL(shown()), this, SLOT(onScrollResize()));
connect(&vis, SIGNAL(hidden()), this, SLOT(onScrollResize()));
connect(m_ui->sendButton, SIGNAL(clicked(bool)), this, SLOT(onEnterPressed()));
connect(line, SIGNAL(resize(int)), this, SLOT(onMessagesResize(int)));
//connect(m_ui->attachButton, SIGNAL(clicked(bool)), this, SLOT(onAttach()));
@ -59,9 +64,11 @@ Conversation::Conversation(bool muc, const QString& mJid, const QString mRes, co
QScrollBar* vs = m_ui->scrollArea->verticalScrollBar();
m_ui->scrollArea->setWidget(line);
vs->installEventFilter(&vis);
vs->setBackgroundRole(QPalette::Base);
vs->setAutoFillBackground(true);
connect(vs, SIGNAL(valueChanged(int)), this, SLOT(onSliderValueChanged(int)));
m_ui->scrollArea->installEventFilter(&res);
applyVisualEffects();
}
@ -236,6 +243,7 @@ void Conversation::showEvent(QShowEvent* event)
emit shown();
QWidget::showEvent(event);
}
void Conversation::onAttach()
@ -262,3 +270,49 @@ void Conversation::setStatus(const QString& status)
{
statusLabel->setText(status);
}
void Conversation::onScrollResize()
{
if (everShown) {
int size = m_ui->scrollArea->width();
QScrollBar* bar = m_ui->scrollArea->verticalScrollBar();
if (bar->isVisible()) {
size -= bar->width();
}
line->setMaximumWidth(size);
}
}
Resizer::Resizer(QWidget* parent):
QObject(parent)
{
}
bool Resizer::eventFilter(QObject* obj, QEvent* event)
{
if (event->type() == QEvent::Resize) {
emit resized();
}
return false;
}
bool VisibilityCatcher::eventFilter(QObject* obj, QEvent* event)
{
if (event->type() == QEvent::Show) {
emit shown();
}
if (event->type() == QEvent::Hide) {
emit hidden();
}
return false;
}
VisibilityCatcher::VisibilityCatcher(QWidget* parent):
QObject(parent)
{
}

View file

@ -42,6 +42,31 @@ signals:
void enterPressed();
};
class Resizer : public QObject {
Q_OBJECT
public:
Resizer(QWidget* parent = nullptr);
protected:
bool eventFilter(QObject* obj, QEvent* event) override;
signals:
void resized();
};
class VisibilityCatcher : public QObject {
Q_OBJECT
public:
VisibilityCatcher(QWidget* parent = nullptr);
protected:
bool eventFilter(QObject* obj, QEvent* event) override;
signals:
void hidden();
void shown();
};
class Conversation : public QWidget
{
Q_OBJECT
@ -75,6 +100,7 @@ protected slots:
void onSliderValueChanged(int value);
void onAttach();
void onFileSelected();
void onScrollResize();
public:
const bool isMuc;
@ -93,6 +119,8 @@ protected:
MessageLine* line;
QScopedPointer<Ui::Conversation> m_ui;
KeyEnterReceiver ker;
Resizer res;
VisibilityCatcher vis;
QString thread;
QLabel* statusIcon;
QLabel* statusLabel;

View file

@ -191,7 +191,7 @@
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
<enum>QAbstractScrollArea::AdjustIgnored</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
@ -202,7 +202,7 @@
<x>0</x>
<y>0</y>
<width>572</width>
<height>116</height>
<height>123</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
@ -339,7 +339,8 @@
<string/>
</property>
<property name="icon">
<iconset theme="mail-attachment-symbolic"/>
<iconset theme="mail-attachment-symbolic">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="flat">
<bool>true</bool>

89
ui/widgets/message.cpp Normal file
View file

@ -0,0 +1,89 @@
/*
* Squawk messenger.
* Copyright (C) 2019 Yury Gubich <blue@macaw.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QDebug>
#include "message.h"
const QRegExp urlReg("^(?!<img\\ssrc=\")((?:https?|ftp)://\\S+)");
const QRegExp imgReg("((?:https?|ftp)://\\S+\\.(?:jpg|jpeg|png|svg|gif))");
Message::Message(const Shared::Message& source, bool outgoing, const QString& p_sender, QWidget* parent):
QHBoxLayout(parent),
msg(source),
body(new QWidget()),
bodyLayout(new QVBoxLayout(body)),
date(new QLabel(msg.getTime().toLocalTime().toString())),
sender(new QLabel(p_sender)),
text(new QLabel()),
shadow(new QGraphicsDropShadowEffect())
{
body->setBackgroundRole(QPalette::AlternateBase);
body->setAutoFillBackground(true);
QString bd = msg.getBody();
//bd.replace(imgReg, "<img src=\"\\1\"/>");
bd.replace(urlReg, "<a href=\"\\1\">\\1</a>");
text->setText(bd);;
text->setTextInteractionFlags(text->textInteractionFlags() | Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
text->setWordWrap(true);
text->setOpenExternalLinks(true);
QFont dFont = date->font();
dFont.setItalic(true);
dFont.setPointSize(dFont.pointSize() - 2);
date->setFont(dFont);
date->setForegroundRole(QPalette::ToolTipText);
QFont f;
f.setBold(true);
sender->setFont(f);
bodyLayout->addWidget(sender);
bodyLayout->addWidget(text);
bodyLayout->addWidget(date);
shadow->setBlurRadius(10);
shadow->setXOffset(1);
shadow->setYOffset(1);
shadow->setColor(Qt::black);
body->setGraphicsEffect(shadow);
if (outgoing) {
addWidget(body);
addStretch();
} else {
sender->setAlignment(Qt::AlignRight);
date->setAlignment(Qt::AlignRight);
addStretch();
addWidget(body);
}
}
Message::~Message()
{
}
QString Message::getId() const
{
return msg.getId();
}
void Message::setSender(const QString& p_sender)
{
sender->setText(p_sender);
}

53
ui/widgets/message.h Normal file
View file

@ -0,0 +1,53 @@
/*
* Squawk messenger.
* Copyright (C) 2019 Yury Gubich <blue@macaw.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MESSAGE_H
#define MESSAGE_H
#include <QWidget>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <QGraphicsDropShadowEffect>
#include "../../global.h"
/**
* @todo write docs
*/
class Message : public QHBoxLayout
{
Q_OBJECT
public:
Message(const Shared::Message& source, bool outgoing, const QString& sender, QWidget* parent = nullptr);
~Message();
void setSender(const QString& sender);
QString getId() const;
private:
Shared::Message msg;
QWidget* body;
QVBoxLayout* bodyLayout;
QLabel* date;
QLabel* sender;
QLabel* text;
QGraphicsDropShadowEffect* shadow;
};
#endif // MESSAGE_H

View file

@ -18,17 +18,15 @@
#include "messageline.h"
#include <QDebug>
#include <QGraphicsDropShadowEffect>
#include <cmath>
const QRegExp urlReg("^(?!<img\\ssrc=\")((?:https?|ftp)://\\S+)");
const QRegExp imgReg("((?:https?|ftp)://\\S+\\.(?:jpg|jpeg|png|svg|gif))");
MessageLine::MessageLine(bool p_room, QWidget* parent):
QWidget(parent),
messageIndex(),
messageOrder(),
layout(new QVBoxLayout()),
myMessages(),
palMessages(),
layout(new QVBoxLayout(this)),
myName(),
palNames(),
views(),
@ -40,7 +38,6 @@ MessageLine::MessageLine(bool p_room, QWidget* parent):
busyShown(false),
rotation()
{
setLayout(layout);
setBackgroundRole(QPalette::Base);
layout->addStretch();
@ -81,14 +78,56 @@ MessageLine::Position MessageLine::message(const Shared::Message& msg)
return invalid;
}
Shared::Message* copy = new Shared::Message(msg);
std::pair<Order::const_iterator, bool> result = messageOrder.insert(std::make_pair(msg.getTime(), copy));
QString sender;
bool outgoing;
if (room) {
if (msg.getFromResource() == myName) {
sender = myName;
outgoing = false;
} else {
sender = msg.getFromResource();
outgoing = true;
}
} else {
if (msg.getOutgoing()) {
sender = myName;
outgoing = false;
} else {
QString jid = msg.getFromJid();
std::map<QString, QString>::iterator itr = palNames.find(jid);
if (itr != palNames.end()) {
sender = itr->second;
} else {
sender = jid;
}
outgoing = true;
}
}
Message* message = new Message(msg, outgoing, sender);
std::pair<Order::const_iterator, bool> result = messageOrder.insert(std::make_pair(msg.getTime(), message));
if (!result.second) {
qDebug() << "Error appending a message into a message list - seems like the time of that message exactly matches the time of some other message, can't put them in order, skipping yet";
delete copy;
delete message;
return invalid;
}
messageIndex.insert(std::make_pair(id, copy));
if (outgoing) {
if (room) {
} else {
QString jid = msg.getFromJid();
std::map<QString, Index>::iterator pItr = palMessages.find(jid);
if (pItr == palMessages.end()) {
pItr = palMessages.insert(std::make_pair(jid, Index())).first;
}
pItr->second.insert(std::make_pair(id, message));
}
} else {
myMessages.insert(std::make_pair(id, message));
}
messageIndex.insert(std::make_pair(id, message));
int index = std::distance<Order::const_iterator>(messageOrder.begin(), result.first); //need to make with binary indexed tree
Position res = invalid;
if (index == 0) {
@ -103,83 +142,11 @@ MessageLine::Position MessageLine::message(const Shared::Message& msg)
index += 1;
}
QVBoxLayout* vBox = new QVBoxLayout();
QHBoxLayout* hBox = new QHBoxLayout();
QWidget* message = new QWidget();
message->setLayout(vBox);
message->setBackgroundRole(QPalette::AlternateBase);
message->setAutoFillBackground(true);
QString bd = msg.getBody();
//bd.replace(imgReg, "<img src=\"\\1\"/>");
bd.replace(urlReg, "<a href=\"\\1\">\\1</a>");
QLabel* body = new QLabel(bd);
body->setTextInteractionFlags(body->textInteractionFlags() | Qt::TextSelectableByMouse);
QLabel* sender = new QLabel();
QLabel* time = new QLabel(msg.getTime().toLocalTime().toString());
QFont dFont = time->font();
dFont.setItalic(true);
dFont.setPointSize(dFont.pointSize() - 2);
time->setFont(dFont);
time->setForegroundRole(QPalette::ToolTipText);
QFont f;
f.setBold(true);
sender->setFont(f);
body->setWordWrap(true);
body->setOpenExternalLinks(true);
vBox->addWidget(sender);
vBox->addWidget(body);
vBox->addWidget(time);
QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect;
effect->setBlurRadius(10);
effect->setXOffset(1);
effect->setYOffset(1);
effect->setColor(Qt::black);
message->setGraphicsEffect(effect);
if (room) {
if (msg.getFromResource() == myName) {
//body->setAlignment(Qt::AlignRight);
sender->setAlignment(Qt::AlignRight);
time->setAlignment(Qt::AlignRight);
sender->setText(myName);
hBox->addStretch();
hBox->addWidget(message);
} else {
sender->setText(msg.getFromResource());
hBox->addWidget(message);
hBox->addStretch();
}
} else {
if (msg.getOutgoing()) {
//body->setAlignment(Qt::AlignRight);
sender->setAlignment(Qt::AlignRight);
time->setAlignment(Qt::AlignRight);
sender->setText(myName);
hBox->addStretch();
hBox->addWidget(message);
} else {
QString jid = msg.getFromJid();
std::map<QString, QString>::iterator itr = palNames.find(jid);
if (itr != palNames.end()) {
sender->setText(itr->second);
} else {
sender->setText(jid);
}
hBox->addWidget(message);
hBox->addStretch();
}
}
if (res == end) {
layout->addLayout(hBox);
layout->addLayout(message);
} else {
layout->insertLayout(index, hBox);
layout->insertLayout(index, message);
}
return res;
@ -188,6 +155,9 @@ MessageLine::Position MessageLine::message(const Shared::Message& msg)
void MessageLine::setMyName(const QString& name)
{
myName = name;
for (Index::const_iterator itr = myMessages.begin(), end = myMessages.end(); itr != end; ++itr) {
itr->second->setSender(name);
}
}
void MessageLine::setPalName(const QString& jid, const QString& name)
@ -198,6 +168,13 @@ void MessageLine::setPalName(const QString& jid, const QString& name)
} else {
itr->second = name;
}
std::map<QString, Index>::iterator pItr = palMessages.find(jid);
if (pItr != palMessages.end()) {
for (Index::const_iterator itr = pItr->second.begin(), end = pItr->second.end(); itr != end; ++itr) {
itr->second->setSender(name);
}
}
}
void MessageLine::resizeEvent(QResizeEvent* event)

View file

@ -29,7 +29,9 @@
#include <QGraphicsView>
#include <QGraphicsPixmapItem>
#include <QVariantAnimation>
#include "../global.h"
#include "message.h"
class MessageLine : public QWidget
{
@ -66,10 +68,12 @@ private:
return a->getTime() < b->getTime();
}
};
typedef std::map<QDateTime, Shared::Message*> Order;
typedef std::map<QString, Shared::Message*> Index;
typedef std::map<QDateTime, Message*> Order;
typedef std::map<QString, Message*> Index;
Index messageIndex;
Order messageOrder;
Index myMessages;
std::map<QString, Index> palMessages;
QVBoxLayout* layout;
QString myName;