very bad and basic archive support

This commit is contained in:
Blue 2019-04-13 23:38:20 +03:00
parent 48e735b0e9
commit fad72d8db2
11 changed files with 180 additions and 20 deletions

View File

@ -7,12 +7,14 @@ using namespace Core;
Account::Account(const QString& p_login, const QString& p_server, const QString& p_password, const QString& p_name, QObject* parent): Account::Account(const QString& p_login, const QString& p_server, const QString& p_password, const QString& p_name, QObject* parent):
QObject(parent), QObject(parent),
name(p_name), name(p_name),
achiveQueries(),
client(), client(),
config(), config(),
presence(), presence(),
state(Shared::disconnected), state(Shared::disconnected),
groups(), groups(),
cm(new QXmppCarbonManager()) cm(new QXmppCarbonManager()),
am(new QXmppMamManager())
{ {
config.setUser(p_login); config.setUser(p_login);
config.setDomain(p_server); config.setDomain(p_server);
@ -35,6 +37,12 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
QObject::connect(cm, SIGNAL(messageReceived(const QXmppMessage&)), this, SLOT(onCarbonMessageReceived(const QXmppMessage&))); QObject::connect(cm, SIGNAL(messageReceived(const QXmppMessage&)), this, SLOT(onCarbonMessageReceived(const QXmppMessage&)));
QObject::connect(cm, SIGNAL(messageSent(const QXmppMessage&)), this, SLOT(onCarbonMessageSent(const QXmppMessage&))); QObject::connect(cm, SIGNAL(messageSent(const QXmppMessage&)), this, SLOT(onCarbonMessageSent(const QXmppMessage&)));
client.addExtension(am);
QObject::connect(am, SIGNAL(archivedMessageReceived(const QString&, const QXmppMessage&)), this, SLOT(onMamMessageReceived(const QString&, const QXmppMessage&)));
QObject::connect(am, SIGNAL(resultsRecieved(const QString&, const QXmppResultSetReply&, bool)),
this, SLOT(onMamResultsReceived(const QString&, const QXmppResultSetReply&, bool)));
} }
Account::~Account() Account::~Account()
@ -397,15 +405,15 @@ void Core::Account::sendMessage(const Shared::Message& data)
void Core::Account::onCarbonMessageReceived(const QXmppMessage& msg) void Core::Account::onCarbonMessageReceived(const QXmppMessage& msg)
{ {
handleChatMessage(msg, false, true); handleChatMessage(msg, false, true);
} }
void Core::Account::onCarbonMessageSent(const QXmppMessage& msg) void Core::Account::onCarbonMessageSent(const QXmppMessage& msg)
{ {
handleChatMessage(msg, true, true); handleChatMessage(msg, true, true);
} }
bool Core::Account::handleChatMessage(const QXmppMessage& msg, bool outgoing, bool forwarded) bool Core::Account::handleChatMessage(const QXmppMessage& msg, bool outgoing, bool forwarded, bool guessing)
{ {
QString body(msg.body()); QString body(msg.body());
if (body.size() != 0) { if (body.size() != 0) {
@ -417,6 +425,13 @@ bool Core::Account::handleChatMessage(const QXmppMessage& msg, bool outgoing, bo
sMsg.setTo(msg.to()); sMsg.setTo(msg.to());
sMsg.setBody(body); sMsg.setBody(body);
sMsg.setForwarded(forwarded); sMsg.setForwarded(forwarded);
if (guessing) {
if (sMsg.getFromJid() == getLogin() + "@" + getServer()) {
outgoing = true;
} else {
outgoing = false;
}
}
sMsg.setOutgoing(outgoing); sMsg.setOutgoing(outgoing);
if (time.isValid()) { if (time.isValid()) {
sMsg.setTime(time); sMsg.setTime(time);
@ -435,3 +450,32 @@ bool Core::Account::handleChatMessage(const QXmppMessage& msg, bool outgoing, bo
} }
return false; return false;
} }
void Core::Account::onMamMessageReceived(const QString& bareJid, const QXmppMessage& msg)
{
handleChatMessage(msg, false, true, true);
}
void Core::Account::requestAchive(const QString& jid)
{
QXmppResultSetQuery query;
query.setMax(100);
QDateTime from = QDateTime::currentDateTime().addDays(-7);
QString q = am->retrieveArchivedMessages("", "", jid, from, QDateTime(), query);
achiveQueries.insert(std::make_pair(q, jid));
}
void Core::Account::onMamResultsReceived(const QString& queryId, const QXmppResultSetReply& resultSetReply, bool complete)
{
std::map<QString, QString>::const_iterator itr = achiveQueries.find(queryId);
QString jid = itr->second;
achiveQueries.erase(itr);
if (!complete) {
QXmppResultSetQuery q;
q.setAfter(resultSetReply.last());
q.setMax(100);
QString nQ = am->retrieveArchivedMessages("", "", jid, QDateTime::currentDateTime().addDays(-7), QDateTime(), q);
achiveQueries.insert(std::make_pair(nQ, jid));
}
}

View File

@ -7,6 +7,7 @@
#include <qxmpp/QXmppRosterManager.h> #include <qxmpp/QXmppRosterManager.h>
#include <qxmpp/QXmppCarbonManager.h> #include <qxmpp/QXmppCarbonManager.h>
#include <qxmpp/QXmppMamManager.h>
#include <qxmpp/QXmppClient.h> #include <qxmpp/QXmppClient.h>
#include "../global.h" #include "../global.h"
@ -39,6 +40,7 @@ public:
void setAvailability(Shared::Availability avail); void setAvailability(Shared::Availability avail);
QString getFullJid() const; QString getFullJid() const;
void sendMessage(const Shared::Message& data); void sendMessage(const Shared::Message& data);
void requestAchive(const QString& jid);
signals: signals:
void connectionStateChanged(int); void connectionStateChanged(int);
@ -55,12 +57,14 @@ signals:
private: private:
QString name; QString name;
std::map<QString, QString> achiveQueries;
QXmppClient client; QXmppClient client;
QXmppConfiguration config; QXmppConfiguration config;
QXmppPresence presence; QXmppPresence presence;
Shared::ConnectionState state; Shared::ConnectionState state;
std::map<QString, std::set<QString>> groups; std::map<QString, std::set<QString>> groups;
QXmppCarbonManager* cm; QXmppCarbonManager* cm;
QXmppMamManager* am;
private slots: private slots:
void onClientConnected(); void onClientConnected();
@ -74,10 +78,12 @@ private slots:
void onMessageReceived(const QXmppMessage& message); void onMessageReceived(const QXmppMessage& message);
void onCarbonMessageReceived(const QXmppMessage& message); void onCarbonMessageReceived(const QXmppMessage& message);
void onCarbonMessageSent(const QXmppMessage& message); void onCarbonMessageSent(const QXmppMessage& message);
void onMamMessageReceived(const QString& bareJid, const QXmppMessage& message);
void onMamResultsReceived(const QString &queryId, const QXmppResultSetReply &resultSetReply, bool complete);
private: private:
void addedAccount(const QString &bareJid); void addedAccount(const QString &bareJid);
bool handleChatMessage(const QXmppMessage& msg, bool outgoing = false, bool forwarded = false); bool handleChatMessage(const QXmppMessage& msg, bool outgoing = false, bool forwarded = false, bool guessing = false);
}; };
} }

View File

@ -220,3 +220,13 @@ void Core::Squawk::sendMessage(const QString& account, const Shared::Message& da
itr->second->sendMessage(data); itr->second->sendMessage(data);
} }
void Core::Squawk::requestArchive(const QString& account, const QString& jid)
{
AccountsMap::const_iterator itr = amap.find(account);
if (itr == amap.end()) {
qDebug("An attempt to request an archive of non existing account, skipping");
return;
}
itr->second->requestAchive(jid);
}

View File

@ -45,6 +45,7 @@ public slots:
void disconnectAccount(const QString& account); void disconnectAccount(const QString& account);
void changeState(int state); void changeState(int state);
void sendMessage(const QString& account, const Shared::Message& data); void sendMessage(const QString& account, const Shared::Message& data);
void requestArchive(const QString& account, const QString& jid);
private: private:
typedef std::deque<Account*> Accounts; typedef std::deque<Account*> Accounts;

View File

@ -35,6 +35,7 @@ int main(int argc, char *argv[])
QObject::connect(&w, SIGNAL(disconnectAccount(const QString&)), squawk, SLOT(disconnectAccount(const QString&))); QObject::connect(&w, SIGNAL(disconnectAccount(const QString&)), squawk, SLOT(disconnectAccount(const QString&)));
QObject::connect(&w, SIGNAL(changeState(int)), squawk, SLOT(changeState(int))); QObject::connect(&w, SIGNAL(changeState(int)), squawk, SLOT(changeState(int)));
QObject::connect(&w, SIGNAL(sendMessage(const QString&, const Shared::Message&)), squawk, SLOT(sendMessage(const QString&, const Shared::Message&))); QObject::connect(&w, SIGNAL(sendMessage(const QString&, const Shared::Message&)), squawk, SLOT(sendMessage(const QString&, const Shared::Message&)));
QObject::connect(&w, SIGNAL(requestArchive(const QString&, const QString&)), squawk, SLOT(requestArchive(const QString&, const QString&)));
QObject::connect(squawk, SIGNAL(newAccount(const QMap<QString, QVariant>&)), &w, SLOT(newAccount(const QMap<QString, QVariant>&))); QObject::connect(squawk, SIGNAL(newAccount(const QMap<QString, QVariant>&)), &w, SLOT(newAccount(const QMap<QString, QVariant>&)));
QObject::connect(squawk, SIGNAL(accountAvailabilityChanged(const QString&, int)), &w, SLOT(accountAvailabilityChanged(const QString&, int))); QObject::connect(squawk, SIGNAL(accountAvailabilityChanged(const QString&, int)), &w, SLOT(accountAvailabilityChanged(const QString&, int)));

View File

@ -24,11 +24,12 @@
Conversation::Conversation(Models::Contact* p_contact, QWidget* parent): Conversation::Conversation(Models::Contact* p_contact, QWidget* parent):
QWidget(parent), QWidget(parent),
contact(p_contact), contact(p_contact),
m_ui(new Ui::Conversation),
line(new MessageLine()), line(new MessageLine()),
m_ui(new Ui::Conversation()),
ker(), ker(),
activePalResource(), activePalResource(),
thread() thread(),
scroll(nothing)
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
m_ui->splitter->setSizes({300, 0}); m_ui->splitter->setSizes({300, 0});
@ -51,9 +52,11 @@ Conversation::Conversation(Models::Contact* p_contact, QWidget* parent):
} }
line->setMyName(p_contact->getAccountName()); line->setMyName(p_contact->getAccountName());
connect(line, SIGNAL(resize(int)), this, SLOT(onMessagesResize(int)));
m_ui->scrollArea->setWidget(line); m_ui->scrollArea->setWidget(line);
m_ui->scrollArea->verticalScrollBar()->setBackgroundRole(QPalette::Base); m_ui->scrollArea->verticalScrollBar()->setBackgroundRole(QPalette::Base);
m_ui->scrollArea->verticalScrollBar()->setAutoFillBackground(true);;
} }
Conversation::~Conversation() Conversation::~Conversation()
@ -110,10 +113,17 @@ void Conversation::addMessage(const Shared::Message& data)
{ {
int pos = m_ui->scrollArea->verticalScrollBar()->sliderPosition(); int pos = m_ui->scrollArea->verticalScrollBar()->sliderPosition();
int max = m_ui->scrollArea->verticalScrollBar()->maximum(); int max = m_ui->scrollArea->verticalScrollBar()->maximum();
line->message(data); MessageLine::Position place = line->message(data);
if (place == MessageLine::invalid) {
return;
}
if (pos == max) { if (scroll == nothing) {
m_ui->scrollArea->verticalScrollBar()->setSliderPosition(m_ui->scrollArea->verticalScrollBar()->maximum()); if (pos == max) {
scroll = down;
} else if (place != MessageLine::end) { //todo make some better handling of that situation
scroll = keep;
}
} }
if (!data.getOutgoing()) { if (!data.getOutgoing()) {
const QString& res = data.getPenPalResource(); const QString& res = data.getPenPalResource();
@ -172,13 +182,28 @@ void Conversation::onEnterPressed()
Shared::Message msg(Shared::Message::chat); Shared::Message msg(Shared::Message::chat);
msg.setFromJid(aJid); msg.setFromJid(aJid);
msg.setFromResource(contact->getAccountResource()); msg.setFromResource(contact->getAccountResource());
qDebug() << "sending message from " << contact->getAccountResource();
msg.setToJid(contact->getJid()); msg.setToJid(contact->getJid());
msg.setToResource(activePalResource); msg.setToResource(activePalResource);
msg.setBody(body); msg.setBody(body);
msg.setOutgoing(true); msg.setOutgoing(true);
msg.generateRandomId(); msg.generateRandomId();
line->message(msg); addMessage(msg);
emit sendMessage(msg); emit sendMessage(msg);
} }
} }
void Conversation::onMessagesResize(int amount)
{
switch (scroll) {
case down:
m_ui->scrollArea->verticalScrollBar()->setValue(m_ui->scrollArea->verticalScrollBar()->maximum());
break;
case keep:
m_ui->scrollArea->verticalScrollBar()->setValue(m_ui->scrollArea->verticalScrollBar()->value() - amount);
break;
default:
break;
}
scroll = nothing;
}

View File

@ -68,14 +68,21 @@ protected:
protected slots: protected slots:
void onContactChanged(Models::Item* item, int row, int col); void onContactChanged(Models::Item* item, int row, int col);
void onEnterPressed(); void onEnterPressed();
void onMessagesResize(int amount);
private: private:
enum Scroll {
nothing,
keep,
down
};
Models::Contact* contact; Models::Contact* contact;
MessageLine* line; MessageLine* line;
QScopedPointer<Ui::Conversation> m_ui; QScopedPointer<Ui::Conversation> m_ui;
KeyEnterReceiver ker; KeyEnterReceiver ker;
QString activePalResource; QString activePalResource;
QString thread; QString thread;
Scroll scroll;
}; };
#endif // CONVERSATION_H #endif // CONVERSATION_H

View File

@ -17,6 +17,7 @@
*/ */
#include "messageline.h" #include "messageline.h"
#include <QDebug>
MessageLine::MessageLine(QWidget* parent): MessageLine::MessageLine(QWidget* parent):
QWidget(parent), QWidget(parent),
@ -24,7 +25,8 @@ MessageLine::MessageLine(QWidget* parent):
messageOrder(), messageOrder(),
layout(new QVBoxLayout()), layout(new QVBoxLayout()),
myName(), myName(),
palNames() palNames(),
views()
{ {
setLayout(layout); setLayout(layout);
setBackgroundRole(QPalette::Base); setBackgroundRole(QPalette::Base);
@ -33,10 +35,38 @@ MessageLine::MessageLine(QWidget* parent):
MessageLine::~MessageLine() MessageLine::~MessageLine()
{ {
for (Index::const_iterator itr = messageIndex.begin(), end = messageIndex.end(); itr != end; ++itr) {
delete itr->second;
}
} }
void MessageLine::message(const Shared::Message& msg) MessageLine::Position MessageLine::message(const Shared::Message& msg)
{ {
QString id = msg.getId();
Index::iterator itr = messageIndex.find(id);
if (itr != messageIndex.end()) {
qDebug() << "received more then one message with the same id, skipping yet the new one";
return invalid;
}
Shared::Message* copy = new Shared::Message(msg);
std::pair<Order::const_iterator, bool> result = messageOrder.insert(std::make_pair(msg.getTime(), copy));
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;
return invalid;
}
messageIndex.insert(std::make_pair(id, copy));
int index = std::distance<Order::const_iterator>(messageOrder.begin(), result.first); //need to make with binary indexed tree
Position res = invalid;
if (index == 0) {
res = beggining;
} else if (index == messageIndex.size() - 1) {
res = end;
} else {
res = middle;
}
QVBoxLayout* vBox = new QVBoxLayout(); QVBoxLayout* vBox = new QVBoxLayout();
QHBoxLayout* hBox = new QHBoxLayout(); QHBoxLayout* hBox = new QHBoxLayout();
QWidget* message = new QWidget(); QWidget* message = new QWidget();
@ -73,7 +103,13 @@ void MessageLine::message(const Shared::Message& msg)
hBox->addStretch(); hBox->addStretch();
} }
layout->addLayout(hBox); if (res == end) {
layout->addLayout(hBox);
} else {
layout->insertLayout(index, hBox);
}
return res;
} }
void MessageLine::setMyName(const QString& name) void MessageLine::setMyName(const QString& name)
@ -90,3 +126,9 @@ void MessageLine::setPalName(const QString& jid, const QString& name)
itr->second = name; itr->second = name;
} }
} }
void MessageLine::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
emit resize(event->size().height() - event->oldSize().height());
}

View File

@ -21,30 +21,52 @@
#include <QWidget> #include <QWidget>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel> #include <QLabel>
#include <QResizeEvent>
#include "../global.h" #include "../global.h"
#include "../order.h"
class MessageLine : public QWidget class MessageLine : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
enum Position {
beggining,
middle,
end,
invalid
};
MessageLine(QWidget* parent = 0); MessageLine(QWidget* parent = 0);
~MessageLine(); ~MessageLine();
void message(const Shared::Message& msg); Position message(const Shared::Message& msg);
void setMyName(const QString& name); void setMyName(const QString& name);
void setPalName(const QString& jid, const QString& name); void setPalName(const QString& jid, const QString& name);
signals:
void resize(int amount);
protected:
void resizeEvent(QResizeEvent * event) override;
private: private:
typedef W::Order<Shared::Message*> Order; struct Comparator {
std::map<QString, Shared::Message*> messageIndex; bool operator()(const Shared::Message& a, const Shared::Message& b) const {
return a.getTime() < b.getTime();
}
bool operator()(const Shared::Message* a, const Shared::Message* b) const {
return a->getTime() < b->getTime();
}
};
typedef std::map<QDateTime, Shared::Message*> Order;
typedef std::map<QString, Shared::Message*> Index;
Index messageIndex;
Order messageOrder; Order messageOrder;
QVBoxLayout* layout; QVBoxLayout* layout;
QString myName; QString myName;
std::map<QString, QString> palNames; std::map<QString, QString> palNames;
std::deque<QHBoxLayout*> views;
}; };
#endif // MESSAGELINE_H #endif // MESSAGELINE_H

View File

@ -198,6 +198,7 @@ void Squawk::onRosterItemDoubleClicked(const QModelIndex& item)
if (res.size() > 0) { if (res.size() > 0) {
itr->second->setPalResource(res); itr->second->setPalResource(res);
} }
requestArchive(account, jid);
} }
} }
} }

View File

@ -31,6 +31,7 @@ signals:
void disconnectAccount(const QString&); void disconnectAccount(const QString&);
void changeState(int state); void changeState(int state);
void sendMessage(const QString& account, const Shared::Message& data); void sendMessage(const QString& account, const Shared::Message& data);
void requestArchive(const QString& account, const QString& jid);
public slots: public slots:
void newAccount(const QMap<QString, QVariant>& account); void newAccount(const QMap<QString, QVariant>& account);