Carbon copies basic support
This commit is contained in:
parent
6e9e100188
commit
48e735b0e9
@ -25,6 +25,7 @@ add_subdirectory(core)
|
||||
|
||||
target_link_libraries(squawk squawkUI)
|
||||
target_link_libraries(squawk squawkCORE)
|
||||
target_link_libraries(squawk uuid)
|
||||
|
||||
# Install the executable
|
||||
install(TARGETS squawk DESTINATION bin)
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "account.h"
|
||||
#include <qxmpp/QXmppRosterManager.h>
|
||||
#include <qxmpp/QXmppMessage.h>
|
||||
#include <QDateTime>
|
||||
|
||||
@ -12,7 +11,8 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
|
||||
config(),
|
||||
presence(),
|
||||
state(Shared::disconnected),
|
||||
groups()
|
||||
groups(),
|
||||
cm(new QXmppCarbonManager())
|
||||
{
|
||||
config.setUser(p_login);
|
||||
config.setDomain(p_server);
|
||||
@ -30,6 +30,11 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
|
||||
QObject::connect(&rm, SIGNAL(itemRemoved(const QString&)), this, SLOT(onRosterItemRemoved(const QString&)));
|
||||
QObject::connect(&rm, SIGNAL(itemChanged(const QString&)), this, SLOT(onRosterItemChanged(const QString&)));
|
||||
//QObject::connect(&rm, SIGNAL(presenceChanged(const QString&, const QString&)), this, SLOT(onRosterPresenceChanged(const QString&, const QString&)));
|
||||
|
||||
client.addExtension(cm);
|
||||
|
||||
QObject::connect(cm, SIGNAL(messageReceived(const QXmppMessage&)), this, SLOT(onCarbonMessageReceived(const QXmppMessage&)));
|
||||
QObject::connect(cm, SIGNAL(messageSent(const QXmppMessage&)), this, SLOT(onCarbonMessageSent(const QXmppMessage&)));
|
||||
}
|
||||
|
||||
Account::~Account()
|
||||
@ -65,6 +70,7 @@ void Core::Account::onClientConnected()
|
||||
{
|
||||
if (state == Shared::connecting) {
|
||||
state = Shared::connected;
|
||||
cm->setCarbonsEnabled(true);
|
||||
emit connectionStateChanged(state);
|
||||
} else {
|
||||
qDebug("Something weird had happened - xmpp client reported about successful connection but account wasn't in connecting state");
|
||||
@ -335,36 +341,13 @@ void Core::Account::setResource(const QString& p_resource)
|
||||
|
||||
void Core::Account::onMessageReceived(const QXmppMessage& msg)
|
||||
{
|
||||
QString from = msg.from();
|
||||
QString to = msg.to();
|
||||
bool handled = false;
|
||||
switch (msg.type()) {
|
||||
case QXmppMessage::Normal:
|
||||
qDebug() << "received a message with type \"Normal\", not sure what to do with it now, skipping";
|
||||
break;
|
||||
case QXmppMessage::Chat:{
|
||||
QString body(msg.body());
|
||||
if (body.size() != 0) {
|
||||
QString id(msg.id());
|
||||
QDateTime time(msg.stamp());
|
||||
Shared::Message sMsg(Shared::Message::chat);
|
||||
sMsg.setId(id);
|
||||
sMsg.setFrom(from);
|
||||
sMsg.setTo(to);
|
||||
sMsg.setBody(body);
|
||||
if (time.isValid()) {
|
||||
sMsg.setTime(time);
|
||||
}
|
||||
emit message(sMsg);
|
||||
|
||||
if (msg.isReceiptRequested() && id.size() > 0) {
|
||||
QXmppMessage receipt(getFullJid(), from, "");
|
||||
receipt.setReceiptId(id);
|
||||
client.sendPacket(receipt);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
case QXmppMessage::Chat:
|
||||
handled = handleChatMessage(msg);
|
||||
break;
|
||||
case QXmppMessage::GroupChat:
|
||||
qDebug() << "received a message with type \"GroupChat\", not sure what to do with it now, skipping";
|
||||
@ -377,10 +360,9 @@ void Core::Account::onMessageReceived(const QXmppMessage& msg)
|
||||
break;
|
||||
}
|
||||
if (!handled) {
|
||||
|
||||
qDebug() << "Message wasn't handled: ";
|
||||
qDebug() << "- from: " << from;
|
||||
qDebug() << "- to: " << to;
|
||||
qDebug() << "- from: " << msg.from();
|
||||
qDebug() << "- to: " << msg.to();
|
||||
qDebug() << "- body: " << msg.body();
|
||||
qDebug() << "- type: " << msg.type();
|
||||
qDebug() << "- state: " << msg.state();
|
||||
@ -404,9 +386,52 @@ QString Core::Account::getFullJid() const
|
||||
void Core::Account::sendMessage(const Shared::Message& data)
|
||||
{
|
||||
if (state == Shared::connected) {
|
||||
client.sendMessage(data.getTo(), data.getBody());
|
||||
QXmppMessage msg(data.getFrom(), data.getTo(), data.getBody(), data.getThread());
|
||||
msg.setId(data.getId());
|
||||
msg.setType(static_cast<QXmppMessage::Type>(data.getType())); //it is safe here, my type is compatible
|
||||
client.sendPacket(msg);
|
||||
} else {
|
||||
qDebug() << "An attempt to send message with not connected account " << name << ", skipping";
|
||||
}
|
||||
}
|
||||
|
||||
void Core::Account::onCarbonMessageReceived(const QXmppMessage& msg)
|
||||
{
|
||||
handleChatMessage(msg, false, true);
|
||||
}
|
||||
|
||||
void Core::Account::onCarbonMessageSent(const QXmppMessage& msg)
|
||||
{
|
||||
handleChatMessage(msg, true, true);
|
||||
}
|
||||
|
||||
bool Core::Account::handleChatMessage(const QXmppMessage& msg, bool outgoing, bool forwarded)
|
||||
{
|
||||
QString body(msg.body());
|
||||
if (body.size() != 0) {
|
||||
QString id(msg.id());
|
||||
QDateTime time(msg.stamp());
|
||||
Shared::Message sMsg(Shared::Message::chat);
|
||||
sMsg.setId(id);
|
||||
sMsg.setFrom(msg.from());
|
||||
sMsg.setTo(msg.to());
|
||||
sMsg.setBody(body);
|
||||
sMsg.setForwarded(forwarded);
|
||||
sMsg.setOutgoing(outgoing);
|
||||
if (time.isValid()) {
|
||||
sMsg.setTime(time);
|
||||
}
|
||||
emit message(sMsg);
|
||||
|
||||
if (!forwarded && !outgoing) {
|
||||
if (msg.isReceiptRequested() && id.size() > 0) {
|
||||
QXmppMessage receipt(getFullJid(), msg.from(), "");
|
||||
receipt.setReceiptId(id);
|
||||
client.sendPacket(receipt);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <qxmpp/QXmppRosterManager.h>
|
||||
#include <qxmpp/QXmppCarbonManager.h>
|
||||
#include <qxmpp/QXmppClient.h>
|
||||
#include "../global.h"
|
||||
|
||||
@ -58,6 +60,7 @@ private:
|
||||
QXmppPresence presence;
|
||||
Shared::ConnectionState state;
|
||||
std::map<QString, std::set<QString>> groups;
|
||||
QXmppCarbonManager* cm;
|
||||
|
||||
private slots:
|
||||
void onClientConnected();
|
||||
@ -69,9 +72,12 @@ private slots:
|
||||
void onRosterPresenceChanged(const QString& bareJid, const QString& resource);
|
||||
void onPresenceReceived(const QXmppPresence& presence);
|
||||
void onMessageReceived(const QXmppMessage& message);
|
||||
void onCarbonMessageReceived(const QXmppMessage& message);
|
||||
void onCarbonMessageSent(const QXmppMessage& message);
|
||||
|
||||
private:
|
||||
void addedAccount(const QString &bareJid);
|
||||
bool handleChatMessage(const QXmppMessage& msg, bool outgoing = false, bool forwarded = false);
|
||||
};
|
||||
|
||||
}
|
||||
|
48
global.cpp
48
global.cpp
@ -1,4 +1,5 @@
|
||||
#include "global.h"
|
||||
#include <uuid/uuid.h>
|
||||
|
||||
Shared::Message::Message(Shared::Message::Type p_type):
|
||||
jFrom(),
|
||||
@ -8,8 +9,10 @@ Shared::Message::Message(Shared::Message::Type p_type):
|
||||
id(),
|
||||
body(),
|
||||
time(),
|
||||
thread(),
|
||||
type(p_type),
|
||||
outgoing(false)
|
||||
outgoing(false),
|
||||
forwarded(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -21,8 +24,10 @@ Shared::Message::Message():
|
||||
id(),
|
||||
body(),
|
||||
time(),
|
||||
thread(),
|
||||
type(Message::normal),
|
||||
outgoing(false)
|
||||
outgoing(false),
|
||||
forwarded(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -164,3 +169,42 @@ void Shared::Message::setOutgoing(bool og)
|
||||
outgoing = og;
|
||||
}
|
||||
|
||||
bool Shared::Message::getForwarded() const
|
||||
{
|
||||
return forwarded;
|
||||
}
|
||||
|
||||
void Shared::Message::generateRandomId()
|
||||
{
|
||||
uuid_t uuid;
|
||||
uuid_generate(uuid);
|
||||
|
||||
char uuid_str[37];
|
||||
uuid_unparse_lower(uuid, uuid_str);
|
||||
id = uuid_str;
|
||||
}
|
||||
|
||||
QString Shared::Message::getThread() const
|
||||
{
|
||||
return thread;
|
||||
}
|
||||
|
||||
void Shared::Message::setForwarded(bool fwd)
|
||||
{
|
||||
forwarded = fwd;
|
||||
}
|
||||
|
||||
void Shared::Message::setThread(const QString& p_body)
|
||||
{
|
||||
thread = p_body;
|
||||
}
|
||||
|
||||
Shared::Message::Type Shared::Message::getType() const
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void Shared::Message::setType(Shared::Message::Type t)
|
||||
{
|
||||
type = t;
|
||||
}
|
||||
|
9
global.h
9
global.h
@ -73,7 +73,10 @@ public:
|
||||
void setTime(const QDateTime& p_time);
|
||||
void setId(const QString& p_id);
|
||||
void setBody(const QString& p_body);
|
||||
void setThread(const QString& p_body);
|
||||
void setOutgoing(bool og);
|
||||
void setForwarded(bool fwd);
|
||||
void setType(Type t);
|
||||
|
||||
QString getFrom() const;
|
||||
QString getFromJid() const;
|
||||
@ -84,10 +87,14 @@ public:
|
||||
QDateTime getTime() const;
|
||||
QString getId() const;
|
||||
QString getBody() const;
|
||||
QString getThread() const;
|
||||
bool getOutgoing() const;
|
||||
bool getForwarded() const;
|
||||
Type getType() const;
|
||||
|
||||
QString getPenPalJid() const;
|
||||
QString getPenPalResource() const;
|
||||
void generateRandomId();
|
||||
|
||||
private:
|
||||
QString jFrom;
|
||||
@ -97,8 +104,10 @@ private:
|
||||
QString id;
|
||||
QString body;
|
||||
QDateTime time;
|
||||
QString thread;
|
||||
Type type;
|
||||
bool outgoing;
|
||||
bool forwarded;
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -19,13 +19,16 @@
|
||||
#include "conversation.h"
|
||||
#include "ui_conversation.h"
|
||||
#include <QDebug>
|
||||
#include <QScrollBar>
|
||||
|
||||
Conversation::Conversation(Models::Contact* p_contact, QWidget* parent):
|
||||
QWidget(parent),
|
||||
contact(p_contact),
|
||||
m_ui(new Ui::Conversation),
|
||||
line(new MessageLine()),
|
||||
ker()
|
||||
ker(),
|
||||
activePalResource(),
|
||||
thread()
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
m_ui->splitter->setSizes({300, 0});
|
||||
@ -47,7 +50,10 @@ Conversation::Conversation(Models::Contact* p_contact, QWidget* parent):
|
||||
addMessage(*itr);
|
||||
}
|
||||
|
||||
line->setMyName(p_contact->getAccountName());
|
||||
|
||||
m_ui->scrollArea->setWidget(line);
|
||||
m_ui->scrollArea->verticalScrollBar()->setBackgroundRole(QPalette::Base);
|
||||
}
|
||||
|
||||
Conversation::~Conversation()
|
||||
@ -61,6 +67,7 @@ void Conversation::setName(const QString& name)
|
||||
m_ui->nameLabel->setText(getJid());
|
||||
} else {
|
||||
m_ui->nameLabel->setText(name);
|
||||
line->setPalName(getJid(), name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +108,19 @@ void Conversation::onContactChanged(Models::Item* item, int row, int col)
|
||||
|
||||
void Conversation::addMessage(const Shared::Message& data)
|
||||
{
|
||||
int pos = m_ui->scrollArea->verticalScrollBar()->sliderPosition();
|
||||
int max = m_ui->scrollArea->verticalScrollBar()->maximum();
|
||||
line->message(data);
|
||||
|
||||
if (pos == max) {
|
||||
m_ui->scrollArea->verticalScrollBar()->setSliderPosition(m_ui->scrollArea->verticalScrollBar()->maximum());
|
||||
}
|
||||
if (!data.getOutgoing()) {
|
||||
const QString& res = data.getPenPalResource();
|
||||
if (res.size() > 0) {
|
||||
setPalResource(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KeyEnterReceiver::KeyEnterReceiver(QObject* parent): QObject(parent), ownEvent(false) {}
|
||||
@ -133,17 +152,33 @@ bool KeyEnterReceiver::eventFilter(QObject* obj, QEvent* event)
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
QString Conversation::getPalResource() const
|
||||
{
|
||||
return activePalResource;
|
||||
}
|
||||
|
||||
void Conversation::setPalResource(const QString& res)
|
||||
{
|
||||
activePalResource = res;
|
||||
}
|
||||
|
||||
void Conversation::onEnterPressed()
|
||||
{
|
||||
QString body(m_ui->messageEditor->toPlainText());
|
||||
const QString& aJid = contact->getAccountJid();
|
||||
m_ui->messageEditor->clear();
|
||||
Shared::Message msg(Shared::Message::chat);
|
||||
msg.setFromJid(aJid);
|
||||
msg.setFromResource(contact->getAccountResource());
|
||||
msg.setTo(contact->getJid());
|
||||
msg.setBody(body);
|
||||
msg.setOutgoing(true);
|
||||
line->message(msg);
|
||||
emit sendMessage(msg);
|
||||
|
||||
if (body.size() > 0) {
|
||||
const QString& aJid = contact->getAccountJid();
|
||||
m_ui->messageEditor->clear();
|
||||
Shared::Message msg(Shared::Message::chat);
|
||||
msg.setFromJid(aJid);
|
||||
msg.setFromResource(contact->getAccountResource());
|
||||
qDebug() << "sending message from " << contact->getAccountResource();
|
||||
msg.setToJid(contact->getJid());
|
||||
msg.setToResource(activePalResource);
|
||||
msg.setBody(body);
|
||||
msg.setOutgoing(true);
|
||||
msg.generateRandomId();
|
||||
line->message(msg);
|
||||
emit sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
@ -52,8 +52,11 @@ public:
|
||||
|
||||
QString getJid() const;
|
||||
QString getAccount() const;
|
||||
QString getPalResource() const;
|
||||
void addMessage(const Shared::Message& data);
|
||||
|
||||
void setPalResource(const QString& res);
|
||||
|
||||
signals:
|
||||
void sendMessage(const Shared::Message& message);
|
||||
|
||||
@ -71,6 +74,8 @@ private:
|
||||
MessageLine* line;
|
||||
QScopedPointer<Ui::Conversation> m_ui;
|
||||
KeyEnterReceiver ker;
|
||||
QString activePalResource;
|
||||
QString thread;
|
||||
};
|
||||
|
||||
#endif // CONVERSATION_H
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* <one line to give the program's name and a brief idea of what it does.>
|
||||
* Copyright (C) 2019 Юрий Губич <y.gubich@initi.ru>
|
||||
* 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
|
||||
@ -22,7 +22,9 @@ MessageLine::MessageLine(QWidget* parent):
|
||||
QWidget(parent),
|
||||
messageIndex(),
|
||||
messageOrder(),
|
||||
layout(new QVBoxLayout())
|
||||
layout(new QVBoxLayout()),
|
||||
myName(),
|
||||
palNames()
|
||||
{
|
||||
setLayout(layout);
|
||||
setBackgroundRole(QPalette::Base);
|
||||
@ -39,12 +41,11 @@ void MessageLine::message(const Shared::Message& msg)
|
||||
QHBoxLayout* hBox = new QHBoxLayout();
|
||||
QWidget* message = new QWidget();
|
||||
message->setLayout(vBox);
|
||||
//message->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
message->setBackgroundRole(QPalette::AlternateBase);
|
||||
message->setAutoFillBackground(true);;
|
||||
|
||||
QLabel* body = new QLabel(msg.getBody());
|
||||
QLabel* sender = new QLabel(msg.getFrom());
|
||||
QLabel* sender = new QLabel();
|
||||
QFont f;
|
||||
f.setBold(true);
|
||||
sender->setFont(f);
|
||||
@ -57,9 +58,17 @@ void MessageLine::message(const Shared::Message& msg)
|
||||
if (msg.getOutgoing()) {
|
||||
body->setAlignment(Qt::AlignRight);
|
||||
sender->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();
|
||||
}
|
||||
@ -67,3 +76,17 @@ void MessageLine::message(const Shared::Message& msg)
|
||||
layout->addLayout(hBox);
|
||||
}
|
||||
|
||||
void MessageLine::setMyName(const QString& name)
|
||||
{
|
||||
myName = name;
|
||||
}
|
||||
|
||||
void MessageLine::setPalName(const QString& jid, const QString& name)
|
||||
{
|
||||
std::map<QString, QString>::iterator itr = palNames.find(jid);
|
||||
if (itr == palNames.end()) {
|
||||
palNames.insert(std::make_pair(jid, name));
|
||||
} else {
|
||||
itr->second = name;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* <one line to give the program's name and a brief idea of what it does.>
|
||||
* Copyright (C) 2019 Юрий Губич <y.gubich@initi.ru>
|
||||
* 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
|
||||
@ -34,12 +34,17 @@ public:
|
||||
~MessageLine();
|
||||
|
||||
void message(const Shared::Message& msg);
|
||||
void setMyName(const QString& name);
|
||||
void setPalName(const QString& jid, const QString& name);
|
||||
|
||||
private:
|
||||
typedef W::Order<Shared::Message*> Order;
|
||||
std::map<QString, Shared::Message*> messageIndex;
|
||||
Order messageOrder;
|
||||
QVBoxLayout* layout;
|
||||
|
||||
QString myName;
|
||||
std::map<QString, QString> palNames;
|
||||
};
|
||||
|
||||
#endif // MESSAGELINE_H
|
||||
|
@ -156,12 +156,14 @@ void Squawk::onRosterItemDoubleClicked(const QModelIndex& item)
|
||||
if (item.isValid()) {
|
||||
Models::Item* node = static_cast<Models::Item*>(item.internalPointer());
|
||||
Models::Contact* contact = 0;
|
||||
QString res;
|
||||
switch (node->type) {
|
||||
case Models::Item::contact:
|
||||
contact = static_cast<Models::Contact*>(node);
|
||||
break;
|
||||
case Models::Item::presence:
|
||||
contact = static_cast<Models::Contact*>(node->parentItem());
|
||||
res = node->getName();
|
||||
break;
|
||||
default:
|
||||
m_ui->roster->expand(item);
|
||||
@ -177,6 +179,10 @@ void Squawk::onRosterItemDoubleClicked(const QModelIndex& item)
|
||||
itr->second->show();
|
||||
itr->second->raise();
|
||||
itr->second->activateWindow();
|
||||
|
||||
if (res.size() > 0) {
|
||||
itr->second->setPalResource(res);
|
||||
}
|
||||
} else {
|
||||
Conversation* conv = new Conversation(contact);
|
||||
|
||||
@ -188,6 +194,10 @@ void Squawk::onRosterItemDoubleClicked(const QModelIndex& item)
|
||||
rosterModel.dropMessages(account, jid);
|
||||
|
||||
conv->show();
|
||||
|
||||
if (res.size() > 0) {
|
||||
itr->second->setPalResource(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -209,11 +219,11 @@ void Squawk::accountMessage(const QString& account, const Shared::Message& data)
|
||||
const QString& from = data.getPenPalJid();
|
||||
Conversations::iterator itr = conversations.find({account, from});
|
||||
if (itr != conversations.end()) {
|
||||
qDebug() << "adding message";
|
||||
itr->second->addMessage(data);
|
||||
} else {
|
||||
qDebug() << "pending message";
|
||||
rosterModel.addMessage(account, data);
|
||||
if (!data.getForwarded()) {
|
||||
rosterModel.addMessage(account, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user