forked from blue/squawk
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:
parent
139c0de0e3
commit
0574d6f72b
@ -468,6 +468,7 @@ void Core::Account::logMessage(const QXmppMessage& msg, const QString& reason)
|
|||||||
qDebug() << "- state: " << msg.state();
|
qDebug() << "- state: " << msg.state();
|
||||||
qDebug() << "- stamp: " << msg.stamp();
|
qDebug() << "- stamp: " << msg.stamp();
|
||||||
qDebug() << "- id: " << msg.id();
|
qDebug() << "- id: " << msg.id();
|
||||||
|
qDebug() << "- outOfBandUrl: " << msg.outOfBandUrl();
|
||||||
qDebug() << "- isAttentionRequested: " << msg.isAttentionRequested();
|
qDebug() << "- isAttentionRequested: " << msg.isAttentionRequested();
|
||||||
qDebug() << "- isReceiptRequested: " << msg.isReceiptRequested();
|
qDebug() << "- isReceiptRequested: " << msg.isReceiptRequested();
|
||||||
qDebug() << "- receiptId: " << msg.receiptId();
|
qDebug() << "- receiptId: " << msg.receiptId();
|
||||||
@ -607,6 +608,7 @@ void Core::Account::initializeMessage(Shared::Message& target, const QXmppMessag
|
|||||||
target.setTo(source.to());
|
target.setTo(source.to());
|
||||||
target.setBody(source.body());
|
target.setBody(source.body());
|
||||||
target.setForwarded(forwarded);
|
target.setForwarded(forwarded);
|
||||||
|
target.setOutOfBandUrl(source.outOfBandUrl());
|
||||||
if (guessing) {
|
if (guessing) {
|
||||||
if (target.getFromJid() == getLogin() + "@" + getServer()) {
|
if (target.getFromJid() == getLogin() + "@" + getServer()) {
|
||||||
outgoing = true;
|
outgoing = true;
|
||||||
@ -624,7 +626,7 @@ void Core::Account::initializeMessage(Shared::Message& target, const QXmppMessag
|
|||||||
|
|
||||||
void Core::Account::onMamMessageReceived(const QString& queryId, const QXmppMessage& msg)
|
void Core::Account::onMamMessageReceived(const QString& queryId, const QXmppMessage& msg)
|
||||||
{
|
{
|
||||||
if (msg.id().size() > 0 && msg.body().size() > 0) {
|
if (msg.id().size() > 0 && (msg.body().size() > 0 || msg.outOfBandUrl().size() > 0)) {
|
||||||
std::map<QString, QString>::const_iterator itr = achiveQueries.find(queryId);
|
std::map<QString, QString>::const_iterator itr = achiveQueries.find(queryId);
|
||||||
QString jid = itr->second;
|
QString jid = itr->second;
|
||||||
RosterItem* item = 0;
|
RosterItem* item = 0;
|
||||||
|
@ -57,6 +57,7 @@ void Core::Archive::open(const QString& account)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mdb_env_set_maxdbs(environment, 4);
|
mdb_env_set_maxdbs(environment, 4);
|
||||||
|
mdb_env_set_mapsize(environment, 1UL * 1024UL * 1024UL * 1024UL);
|
||||||
mdb_env_open(environment, path.toStdString().c_str(), 0, 0664);
|
mdb_env_open(environment, path.toStdString().c_str(), 0, 0664);
|
||||||
|
|
||||||
MDB_txn *txn;
|
MDB_txn *txn;
|
||||||
|
@ -137,7 +137,7 @@ void Core::Conference::onRoomParticipantAdded(const QString& p_name)
|
|||||||
if (resource == jid) {
|
if (resource == jid) {
|
||||||
qDebug() << "Room" << jid << "is reporting of adding itself to the list participants. Not sure what to do with that yet, skipping";
|
qDebug() << "Room" << jid << "is reporting of adding itself to the list participants. Not sure what to do with that yet, skipping";
|
||||||
} else {
|
} else {
|
||||||
QXmppPresence pres = room->participantPresence(jid);
|
QXmppPresence pres = room->participantPresence(p_name);
|
||||||
QDateTime lastInteraction = pres.lastUserInteraction();
|
QDateTime lastInteraction = pres.lastUserInteraction();
|
||||||
if (!lastInteraction.isValid()) {
|
if (!lastInteraction.isValid()) {
|
||||||
lastInteraction = QDateTime::currentDateTime();
|
lastInteraction = QDateTime::currentDateTime();
|
||||||
@ -161,7 +161,7 @@ void Core::Conference::onRoomParticipantChanged(const QString& p_name)
|
|||||||
if (resource == jid) {
|
if (resource == jid) {
|
||||||
qDebug() << "Room" << jid << "is reporting of changing his own presence. Not sure what to do with that yet, skipping";
|
qDebug() << "Room" << jid << "is reporting of changing his own presence. Not sure what to do with that yet, skipping";
|
||||||
} else {
|
} else {
|
||||||
QXmppPresence pres = room->participantPresence(jid);
|
QXmppPresence pres = room->participantPresence(p_name);
|
||||||
QDateTime lastInteraction = pres.lastUserInteraction();
|
QDateTime lastInteraction = pres.lastUserInteraction();
|
||||||
if (!lastInteraction.isValid()) {
|
if (!lastInteraction.isValid()) {
|
||||||
lastInteraction = QDateTime::currentDateTime();
|
lastInteraction = QDateTime::currentDateTime();
|
||||||
|
@ -71,7 +71,7 @@ void Core::RosterItem::setName(const QString& n)
|
|||||||
|
|
||||||
void Core::RosterItem::addMessageToArchive(const Shared::Message& msg)
|
void Core::RosterItem::addMessageToArchive(const Shared::Message& msg)
|
||||||
{
|
{
|
||||||
if (msg.getId().size() > 0 && msg.getBody().size() > 0) {
|
if (msg.storable()) {
|
||||||
hisoryCache.push_back(msg);
|
hisoryCache.push_back(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -184,7 +184,7 @@ void Core::RosterItem::appendMessageToArchive(const Shared::Message& msg)
|
|||||||
{
|
{
|
||||||
const QString& id = msg.getId();
|
const QString& id = msg.getId();
|
||||||
if (id.size() > 0) {
|
if (id.size() > 0) {
|
||||||
if (msg.getBody().size() > 0) {
|
if (msg.storable()) {
|
||||||
switch (archiveState) {
|
switch (archiveState) {
|
||||||
case empty:
|
case empty:
|
||||||
if (archive->addElement(msg)) {
|
if (archive->addElement(msg)) {
|
||||||
|
22
global.cpp
22
global.cpp
@ -240,6 +240,7 @@ void Shared::Message::serialize(QDataStream& data) const
|
|||||||
data << t;
|
data << t;
|
||||||
data << outgoing;
|
data << outgoing;
|
||||||
data << forwarded;
|
data << forwarded;
|
||||||
|
data << oob;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shared::Message::deserialize(QDataStream& data)
|
void Shared::Message::deserialize(QDataStream& data)
|
||||||
@ -257,6 +258,7 @@ void Shared::Message::deserialize(QDataStream& data)
|
|||||||
type = static_cast<Type>(t);
|
type = static_cast<Type>(t);
|
||||||
data >> outgoing;
|
data >> outgoing;
|
||||||
data >> forwarded;
|
data >> forwarded;
|
||||||
|
data >> oob;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Shared::generateUUID()
|
QString Shared::generateUUID()
|
||||||
@ -274,6 +276,26 @@ void Shared::Message::setCurrentTime()
|
|||||||
time = QDateTime::currentDateTime();
|
time = QDateTime::currentDateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Shared::Message::getOutOfBandUrl() const
|
||||||
|
{
|
||||||
|
return oob;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shared::Message::hasOutOfBandUrl() const
|
||||||
|
{
|
||||||
|
return oob.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shared::Message::setOutOfBandUrl(const QString& url)
|
||||||
|
{
|
||||||
|
oob = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shared::Message::storable() const
|
||||||
|
{
|
||||||
|
return id.size() > 0 && (body.size() > 0 || oob.size()) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
QIcon Shared::availabilityIcon(Shared::Availability av, bool big)
|
QIcon Shared::availabilityIcon(Shared::Availability av, bool big)
|
||||||
{
|
{
|
||||||
const std::deque<QString>& fallback = QApplication::palette().window().color().lightnessF() > 0.5 ?
|
const std::deque<QString>& fallback = QApplication::palette().window().color().lightnessF() > 0.5 ?
|
||||||
|
5
global.h
5
global.h
@ -128,6 +128,7 @@ public:
|
|||||||
void setForwarded(bool fwd);
|
void setForwarded(bool fwd);
|
||||||
void setType(Type t);
|
void setType(Type t);
|
||||||
void setCurrentTime();
|
void setCurrentTime();
|
||||||
|
void setOutOfBandUrl(const QString& url);
|
||||||
|
|
||||||
QString getFrom() const;
|
QString getFrom() const;
|
||||||
QString getFromJid() const;
|
QString getFromJid() const;
|
||||||
@ -142,6 +143,9 @@ public:
|
|||||||
bool getOutgoing() const;
|
bool getOutgoing() const;
|
||||||
bool getForwarded() const;
|
bool getForwarded() const;
|
||||||
Type getType() const;
|
Type getType() const;
|
||||||
|
bool hasOutOfBandUrl() const;
|
||||||
|
bool storable() const;
|
||||||
|
QString getOutOfBandUrl() const;
|
||||||
|
|
||||||
QString getPenPalJid() const;
|
QString getPenPalJid() const;
|
||||||
QString getPenPalResource() const;
|
QString getPenPalResource() const;
|
||||||
@ -162,6 +166,7 @@ private:
|
|||||||
Type type;
|
Type type;
|
||||||
bool outgoing;
|
bool outgoing;
|
||||||
bool forwarded;
|
bool forwarded;
|
||||||
|
QString oob;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::deque<QString> fallbackAvailabilityThemeIconsLightBig = {
|
static const std::deque<QString> fallbackAvailabilityThemeIconsLightBig = {
|
||||||
|
2
main.cpp
2
main.cpp
@ -36,7 +36,7 @@ int main(int argc, char *argv[])
|
|||||||
QCoreApplication::setOrganizationName("Macaw");
|
QCoreApplication::setOrganizationName("Macaw");
|
||||||
QCoreApplication::setOrganizationDomain("macaw.me");
|
QCoreApplication::setOrganizationDomain("macaw.me");
|
||||||
QCoreApplication::setApplicationName("Squawk");
|
QCoreApplication::setApplicationName("Squawk");
|
||||||
QCoreApplication::setApplicationVersion("0.0.1");
|
QCoreApplication::setApplicationVersion("0.0.3");
|
||||||
|
|
||||||
QIcon icon;
|
QIcon icon;
|
||||||
icon.addFile(":images/logo.svg", QSize(16, 16));
|
icon.addFile(":images/logo.svg", QSize(16, 16));
|
||||||
|
@ -30,6 +30,7 @@ set(squawkUI_SRC
|
|||||||
widgets/accounts.cpp
|
widgets/accounts.cpp
|
||||||
widgets/account.cpp
|
widgets/account.cpp
|
||||||
widgets/joinconference.cpp
|
widgets/joinconference.cpp
|
||||||
|
widgets/message.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Tell CMake to create the helloworld executable
|
# Tell CMake to create the helloworld executable
|
||||||
|
@ -35,6 +35,8 @@ Conversation::Conversation(bool muc, const QString& mJid, const QString mRes, co
|
|||||||
line(new MessageLine(muc)),
|
line(new MessageLine(muc)),
|
||||||
m_ui(new Ui::Conversation()),
|
m_ui(new Ui::Conversation()),
|
||||||
ker(),
|
ker(),
|
||||||
|
res(),
|
||||||
|
vis(),
|
||||||
thread(),
|
thread(),
|
||||||
statusIcon(0),
|
statusIcon(0),
|
||||||
statusLabel(0),
|
statusLabel(0),
|
||||||
@ -51,6 +53,9 @@ Conversation::Conversation(bool muc, const QString& mJid, const QString mRes, co
|
|||||||
statusLabel = m_ui->statusLabel;
|
statusLabel = m_ui->statusLabel;
|
||||||
|
|
||||||
connect(&ker, SIGNAL(enterPressed()), this, SLOT(onEnterPressed()));
|
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(m_ui->sendButton, SIGNAL(clicked(bool)), this, SLOT(onEnterPressed()));
|
||||||
connect(line, SIGNAL(resize(int)), this, SLOT(onMessagesResize(int)));
|
connect(line, SIGNAL(resize(int)), this, SLOT(onMessagesResize(int)));
|
||||||
//connect(m_ui->attachButton, SIGNAL(clicked(bool)), this, SLOT(onAttach()));
|
//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();
|
QScrollBar* vs = m_ui->scrollArea->verticalScrollBar();
|
||||||
m_ui->scrollArea->setWidget(line);
|
m_ui->scrollArea->setWidget(line);
|
||||||
|
vs->installEventFilter(&vis);
|
||||||
vs->setBackgroundRole(QPalette::Base);
|
vs->setBackgroundRole(QPalette::Base);
|
||||||
vs->setAutoFillBackground(true);
|
vs->setAutoFillBackground(true);
|
||||||
connect(vs, SIGNAL(valueChanged(int)), this, SLOT(onSliderValueChanged(int)));
|
connect(vs, SIGNAL(valueChanged(int)), this, SLOT(onSliderValueChanged(int)));
|
||||||
|
m_ui->scrollArea->installEventFilter(&res);
|
||||||
|
|
||||||
applyVisualEffects();
|
applyVisualEffects();
|
||||||
}
|
}
|
||||||
@ -236,6 +243,7 @@ void Conversation::showEvent(QShowEvent* event)
|
|||||||
emit shown();
|
emit shown();
|
||||||
|
|
||||||
QWidget::showEvent(event);
|
QWidget::showEvent(event);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Conversation::onAttach()
|
void Conversation::onAttach()
|
||||||
@ -262,3 +270,49 @@ void Conversation::setStatus(const QString& status)
|
|||||||
{
|
{
|
||||||
statusLabel->setText(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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,31 @@ signals:
|
|||||||
void enterPressed();
|
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
|
class Conversation : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -75,6 +100,7 @@ protected slots:
|
|||||||
void onSliderValueChanged(int value);
|
void onSliderValueChanged(int value);
|
||||||
void onAttach();
|
void onAttach();
|
||||||
void onFileSelected();
|
void onFileSelected();
|
||||||
|
void onScrollResize();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const bool isMuc;
|
const bool isMuc;
|
||||||
@ -93,6 +119,8 @@ protected:
|
|||||||
MessageLine* line;
|
MessageLine* line;
|
||||||
QScopedPointer<Ui::Conversation> m_ui;
|
QScopedPointer<Ui::Conversation> m_ui;
|
||||||
KeyEnterReceiver ker;
|
KeyEnterReceiver ker;
|
||||||
|
Resizer res;
|
||||||
|
VisibilityCatcher vis;
|
||||||
QString thread;
|
QString thread;
|
||||||
QLabel* statusIcon;
|
QLabel* statusIcon;
|
||||||
QLabel* statusLabel;
|
QLabel* statusLabel;
|
||||||
|
@ -191,7 +191,7 @@
|
|||||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeAdjustPolicy">
|
<property name="sizeAdjustPolicy">
|
||||||
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
<enum>QAbstractScrollArea::AdjustIgnored</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="widgetResizable">
|
<property name="widgetResizable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -202,7 +202,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>572</width>
|
<width>572</width>
|
||||||
<height>116</height>
|
<height>123</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
@ -339,7 +339,8 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="mail-attachment-symbolic"/>
|
<iconset theme="mail-attachment-symbolic">
|
||||||
|
<normaloff>.</normaloff>.</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="flat">
|
<property name="flat">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
89
ui/widgets/message.cpp
Normal file
89
ui/widgets/message.cpp
Normal 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
53
ui/widgets/message.h
Normal 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
|
@ -18,17 +18,15 @@
|
|||||||
|
|
||||||
#include "messageline.h"
|
#include "messageline.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QGraphicsDropShadowEffect>
|
|
||||||
#include <cmath>
|
#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):
|
MessageLine::MessageLine(bool p_room, QWidget* parent):
|
||||||
QWidget(parent),
|
QWidget(parent),
|
||||||
messageIndex(),
|
messageIndex(),
|
||||||
messageOrder(),
|
messageOrder(),
|
||||||
layout(new QVBoxLayout()),
|
myMessages(),
|
||||||
|
palMessages(),
|
||||||
|
layout(new QVBoxLayout(this)),
|
||||||
myName(),
|
myName(),
|
||||||
palNames(),
|
palNames(),
|
||||||
views(),
|
views(),
|
||||||
@ -40,7 +38,6 @@ MessageLine::MessageLine(bool p_room, QWidget* parent):
|
|||||||
busyShown(false),
|
busyShown(false),
|
||||||
rotation()
|
rotation()
|
||||||
{
|
{
|
||||||
setLayout(layout);
|
|
||||||
setBackgroundRole(QPalette::Base);
|
setBackgroundRole(QPalette::Base);
|
||||||
layout->addStretch();
|
layout->addStretch();
|
||||||
|
|
||||||
@ -81,14 +78,56 @@ MessageLine::Position MessageLine::message(const Shared::Message& msg)
|
|||||||
return invalid;
|
return invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
Shared::Message* copy = new Shared::Message(msg);
|
QString sender;
|
||||||
std::pair<Order::const_iterator, bool> result = messageOrder.insert(std::make_pair(msg.getTime(), copy));
|
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) {
|
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";
|
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;
|
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
|
int index = std::distance<Order::const_iterator>(messageOrder.begin(), result.first); //need to make with binary indexed tree
|
||||||
Position res = invalid;
|
Position res = invalid;
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
@ -103,83 +142,11 @@ MessageLine::Position MessageLine::message(const Shared::Message& msg)
|
|||||||
index += 1;
|
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) {
|
if (res == end) {
|
||||||
layout->addLayout(hBox);
|
layout->addLayout(message);
|
||||||
} else {
|
} else {
|
||||||
layout->insertLayout(index, hBox);
|
layout->insertLayout(index, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@ -188,6 +155,9 @@ MessageLine::Position MessageLine::message(const Shared::Message& msg)
|
|||||||
void MessageLine::setMyName(const QString& name)
|
void MessageLine::setMyName(const QString& name)
|
||||||
{
|
{
|
||||||
myName = 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)
|
void MessageLine::setPalName(const QString& jid, const QString& name)
|
||||||
@ -198,6 +168,13 @@ void MessageLine::setPalName(const QString& jid, const QString& name)
|
|||||||
} else {
|
} else {
|
||||||
itr->second = name;
|
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)
|
void MessageLine::resizeEvent(QResizeEvent* event)
|
||||||
|
@ -29,7 +29,9 @@
|
|||||||
#include <QGraphicsView>
|
#include <QGraphicsView>
|
||||||
#include <QGraphicsPixmapItem>
|
#include <QGraphicsPixmapItem>
|
||||||
#include <QVariantAnimation>
|
#include <QVariantAnimation>
|
||||||
|
|
||||||
#include "../global.h"
|
#include "../global.h"
|
||||||
|
#include "message.h"
|
||||||
|
|
||||||
class MessageLine : public QWidget
|
class MessageLine : public QWidget
|
||||||
{
|
{
|
||||||
@ -66,10 +68,12 @@ private:
|
|||||||
return a->getTime() < b->getTime();
|
return a->getTime() < b->getTime();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
typedef std::map<QDateTime, Shared::Message*> Order;
|
typedef std::map<QDateTime, Message*> Order;
|
||||||
typedef std::map<QString, Shared::Message*> Index;
|
typedef std::map<QString, Message*> Index;
|
||||||
Index messageIndex;
|
Index messageIndex;
|
||||||
Order messageOrder;
|
Order messageOrder;
|
||||||
|
Index myMessages;
|
||||||
|
std::map<QString, Index> palMessages;
|
||||||
QVBoxLayout* layout;
|
QVBoxLayout* layout;
|
||||||
|
|
||||||
QString myName;
|
QString myName;
|
||||||
|
Loading…
Reference in New Issue
Block a user