1
0
forked from blue/squawk

better new message handling, subscription with adding new contact, out of roster contacts handling

This commit is contained in:
Blue 2019-06-18 18:08:03 +03:00
parent bb509be29a
commit b2699e0087
11 changed files with 100 additions and 23 deletions

View File

@ -18,7 +18,9 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
am(new QXmppMamManager()), am(new QXmppMamManager()),
contacts(), contacts(),
maxReconnectTimes(0), maxReconnectTimes(0),
reconnectTimes(0) reconnectTimes(0),
queuedContacts(),
outOfRosterContacts()
{ {
config.setUser(p_login); config.setUser(p_login);
config.setDomain(p_server); config.setDomain(p_server);
@ -166,6 +168,12 @@ void Core::Account::setReconnectTimes(unsigned int times)
void Core::Account::onRosterItemAdded(const QString& bareJid) void Core::Account::onRosterItemAdded(const QString& bareJid)
{ {
addedAccount(bareJid); addedAccount(bareJid);
std::map<QString, QString>::const_iterator itr = queuedContacts.find(bareJid);
if (itr != queuedContacts.end()) {
QXmppRosterManager& rm = client.rosterManager();
rm.subscribe(bareJid, itr->second);
queuedContacts.erase(itr);
}
} }
void Core::Account::onRosterItemChanged(const QString& bareJid) void Core::Account::onRosterItemChanged(const QString& bareJid)
@ -447,6 +455,7 @@ bool Core::Account::handleChatMessage(const QXmppMessage& msg, bool outgoing, bo
} else { } else {
cnt = new Contact(jid, name); cnt = new Contact(jid, name);
contacts.insert(std::make_pair(jid, cnt)); contacts.insert(std::make_pair(jid, cnt));
outOfRosterContacts.insert(jid);
cnt->setSubscriptionState(Shared::unknown); cnt->setSubscriptionState(Shared::unknown);
emit addContact(jid, "", QMap<QString, QVariant>({ emit addContact(jid, "", QMap<QString, QVariant>({
{"state", Shared::unknown} {"state", Shared::unknown}
@ -785,8 +794,14 @@ void Core::Account::unsubscribeFromContact(const QString& jid, const QString& re
void Core::Account::removeContactRequest(const QString& jid) void Core::Account::removeContactRequest(const QString& jid)
{ {
if (state == Shared::connected) { if (state == Shared::connected) {
QXmppRosterManager& rm = client.rosterManager(); std::set<QString>::const_iterator itr = outOfRosterContacts.find(jid);
rm.removeItem(jid); if (itr != outOfRosterContacts.end()) {
outOfRosterContacts.erase(itr);
onRosterItemRemoved(jid);
} else {
QXmppRosterManager& rm = client.rosterManager();
rm.removeItem(jid);
}
} else { } else {
qDebug() << "An attempt to remove contact " << jid << " from account " << name << " but the account is not in the connected state, skipping"; qDebug() << "An attempt to remove contact " << jid << " from account " << name << " but the account is not in the connected state, skipping";
} }
@ -796,8 +811,14 @@ void Core::Account::removeContactRequest(const QString& jid)
void Core::Account::addContactRequest(const QString& jid, const QString& name, const QSet<QString>& groups) void Core::Account::addContactRequest(const QString& jid, const QString& name, const QSet<QString>& groups)
{ {
if (state == Shared::connected) { if (state == Shared::connected) {
QXmppRosterManager& rm = client.rosterManager(); std::map<QString, QString>::const_iterator itr = queuedContacts.find(jid);
rm.addItem(jid, name, groups); if (itr != queuedContacts.end()) {
qDebug() << "An attempt to add contact " << jid << " to account " << name << " but the account is already queued for adding, skipping";
} else {
queuedContacts.insert(std::make_pair(jid, "")); //TODO need to add reason here;
QXmppRosterManager& rm = client.rosterManager();
rm.addItem(jid, name, groups);
}
} else { } else {
qDebug() << "An attempt to add contact " << jid << " to account " << name << " but the account is not in the connected state, skipping"; qDebug() << "An attempt to add contact " << jid << " to account " << name << " but the account is not in the connected state, skipping";
} }

View File

@ -78,6 +78,9 @@ private:
unsigned int maxReconnectTimes; unsigned int maxReconnectTimes;
unsigned int reconnectTimes; unsigned int reconnectTimes;
std::map<QString, QString> queuedContacts;
std::set<QString> outOfRosterContacts;
private slots: private slots:
void onClientConnected(); void onClientConnected();
void onClientDisconnected(); void onClientDisconnected();

View File

@ -8,6 +8,7 @@ set(CMAKE_AUTOUIC ON)
# Find the QtWidgets library # Find the QtWidgets library
find_package(Qt5Widgets CONFIG REQUIRED) find_package(Qt5Widgets CONFIG REQUIRED)
find_package(Qt5DBus CONFIG REQUIRED)
set(squawkUI_SRC set(squawkUI_SRC
squawk.cpp squawk.cpp
@ -29,6 +30,7 @@ add_library(squawkUI ${squawkUI_SRC})
# Use the Widgets module from Qt 5. # Use the Widgets module from Qt 5.
target_link_libraries(squawkUI Qt5::Widgets) target_link_libraries(squawkUI Qt5::Widgets)
target_link_libraries(squawkUI Qt5::DBus)
# Install the executable # Install the executable
install(TARGETS squawkUI DESTINATION lib) install(TARGETS squawkUI DESTINATION lib)

View File

@ -39,7 +39,7 @@ Conversation::Conversation(Models::Contact* p_contact, QWidget* parent):
m_ui->splitter->setSizes({300, 0}); m_ui->splitter->setSizes({300, 0});
m_ui->splitter->setStretchFactor(1, 0); m_ui->splitter->setStretchFactor(1, 0);
setName(p_contact->getName()); setName(p_contact->getContactName());
setState(p_contact->getAvailability()); setState(p_contact->getAvailability());
connect(contact, SIGNAL(childChanged(Models::Item*, int, int)), this, SLOT(onContactChanged(Models::Item*, int, int))); connect(contact, SIGNAL(childChanged(Models::Item*, int, int)), this, SLOT(onContactChanged(Models::Item*, int, int)));
@ -71,12 +71,8 @@ Conversation::~Conversation()
void Conversation::setName(const QString& name) void Conversation::setName(const QString& name)
{ {
if (name == "") { m_ui->nameLabel->setText(name);
m_ui->nameLabel->setText(getJid()); line->setPalName(getJid(), name);
} else {
m_ui->nameLabel->setText(name);
line->setPalName(getJid(), name);
}
} }
void Conversation::setState(Shared::Availability state) void Conversation::setState(Shared::Availability state)
@ -105,7 +101,7 @@ void Conversation::onContactChanged(Models::Item* item, int row, int col)
if (item == contact) { if (item == contact) {
switch (col) { switch (col) {
case 0: case 0:
setName(contact->getName()); setName(contact->getContactName());
break; break;
case 3: case 3:
setState(contact->getAvailability()); setState(contact->getAvailability());
@ -252,6 +248,7 @@ void Conversation::showEvent(QShowEvent* event)
requestingHistory = true; requestingHistory = true;
emit requestArchive(line->firstMessageId()); emit requestArchive(line->firstMessageId());
} }
emit shown();
QWidget::showEvent(event); QWidget::showEvent(event);
} }

View File

@ -62,6 +62,7 @@ public:
signals: signals:
void sendMessage(const Shared::Message& message); void sendMessage(const Shared::Message& message);
void requestArchive(const QString& before); void requestArchive(const QString& before);
void shown();
protected: protected:
void setState(Shared::Availability state); void setState(Shared::Availability state);

View File

@ -76,11 +76,7 @@ QVariant Models::Contact::data(int column) const
{ {
switch (column) { switch (column) {
case 0: case 0:
if (name == "") { return getContactName();
return jid;
} else {
return Item::data(column);
}
case 1: case 1:
return jid; return jid;
case 2: case 2:
@ -94,6 +90,15 @@ QVariant Models::Contact::data(int column) const
} }
} }
QString Models::Contact::getContactName() const
{
if (name == "") {
return jid;
} else {
return name;
}
}
void Models::Contact::update(const QString& field, const QVariant& value) void Models::Contact::update(const QString& field, const QVariant& value)
{ {
if (field == "name") { if (field == "name") {

View File

@ -36,6 +36,7 @@ public:
QString getAccountName() const; QString getAccountName() const;
QString getAccountJid() const; QString getAccountJid() const;
QString getAccountResource() const; QString getAccountResource() const;
QString getContactName() const;
void addMessage(const Shared::Message& data); void addMessage(const Shared::Message& data);
unsigned int getMessagesCount() const; unsigned int getMessagesCount() const;

View File

@ -556,3 +556,13 @@ void Models::Roster::removeAccount(const QString& account)
acc->deleteLater(); acc->deleteLater();
} }
QString Models::Roster::getContactName(const QString& account, const QString& jid)
{
std::multimap<ElId, Contact*>::const_iterator cItr = contacts.find({account, jid});
if (cItr == contacts.end()) {
qDebug() << "An attempt to get a name of non existing contact " << account << ":" << jid << ", skipping";
return "";
}
return cItr->second->getContactName();
}

View File

@ -35,6 +35,7 @@ public:
void removePresence(const QString& account, const QString& jid, const QString& name); void removePresence(const QString& account, const QString& jid, const QString& name);
void addMessage(const QString& account, const Shared::Message& data); void addMessage(const QString& account, const Shared::Message& data);
void dropMessages(const QString& account, const QString& jid); void dropMessages(const QString& account, const QString& jid);
QString getContactName(const QString& account, const QString& jid);
QVariant data ( const QModelIndex& index, int role ) const override; QVariant data ( const QModelIndex& index, int role ) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override; Qt::ItemFlags flags(const QModelIndex &index) const override;

View File

@ -9,7 +9,8 @@ Squawk::Squawk(QWidget *parent) :
accounts(0), accounts(0),
rosterModel(), rosterModel(),
conversations(), conversations(),
contextMenu(new QMenu()) contextMenu(new QMenu()),
dbus("org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications", QDBusConnection::sessionBus())
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
m_ui->roster->setModel(&rosterModel); m_ui->roster->setModel(&rosterModel);
@ -227,9 +228,9 @@ void Squawk::onRosterItemDoubleClicked(const QModelIndex& item)
connect(conv, SIGNAL(destroyed(QObject*)), this, SLOT(onConversationClosed(QObject*))); connect(conv, SIGNAL(destroyed(QObject*)), this, SLOT(onConversationClosed(QObject*)));
connect(conv, SIGNAL(sendMessage(const Shared::Message&)), this, SLOT(onConversationMessage(const Shared::Message&))); connect(conv, SIGNAL(sendMessage(const Shared::Message&)), this, SLOT(onConversationMessage(const Shared::Message&)));
connect(conv, SIGNAL(requestArchive(const QString&)), this, SLOT(onConversationRequestArchive(const QString&))); connect(conv, SIGNAL(requestArchive(const QString&)), this, SLOT(onConversationRequestArchive(const QString&)));
connect(conv, SIGNAL(shown()), this, SLOT(onConversationShown()));
conversations.insert(std::make_pair(id, conv)); conversations.insert(std::make_pair(id, conv));
rosterModel.dropMessages(account, jid);
conv->show(); conv->show();
@ -241,6 +242,12 @@ void Squawk::onRosterItemDoubleClicked(const QModelIndex& item)
} }
} }
void Squawk::onConversationShown()
{
Conversation* conv = static_cast<Conversation*>(sender());
rosterModel.dropMessages(conv->getAccount(), conv->getJid());
}
void Squawk::onConversationClosed(QObject* parent) void Squawk::onConversationClosed(QObject* parent)
{ {
Conversation* conv = static_cast<Conversation*>(sender()); Conversation* conv = static_cast<Conversation*>(sender());
@ -257,14 +264,38 @@ void Squawk::accountMessage(const QString& account, const Shared::Message& data)
const QString& from = data.getPenPalJid(); const QString& from = data.getPenPalJid();
Conversations::iterator itr = conversations.find({account, from}); Conversations::iterator itr = conversations.find({account, from});
if (itr != conversations.end()) { if (itr != conversations.end()) {
itr->second->addMessage(data); Conversation* conv = itr->second;
} else { conv->addMessage(data);
if (!data.getForwarded()) { QApplication::alert(conv);
if (conv->isMinimized()) {
rosterModel.addMessage(account, data); rosterModel.addMessage(account, data);
if (!data.getForwarded()) {
notify(account, data);
}
}
} else {
rosterModel.addMessage(account, data);
if (!data.getForwarded()) {
QApplication::alert(this);
notify(account, data);
} }
} }
} }
void Squawk::notify(const QString& account, const Shared::Message& msg)
{
QVariantList args;
args << QString(QCoreApplication::applicationName());
args << QVariant(QVariant::UInt); //TODO some normal id
args << QString("mail-message"); //TODO icon
args << QString(rosterModel.getContactName(account, msg.getPenPalJid()));
args << QString(msg.getBody());
args << QStringList();
args << QVariantMap();
args << 3000;
dbus.callWithArgumentList(QDBus::AutoDetect, "Notify", args);
}
void Squawk::onConversationMessage(const Shared::Message& msg) void Squawk::onConversationMessage(const Shared::Message& msg)
{ {
Conversation* conv = static_cast<Conversation*>(sender()); Conversation* conv = static_cast<Conversation*>(sender());
@ -299,6 +330,7 @@ void Squawk::removeAccount(const QString& account)
disconnect(conv, SIGNAL(destroyed(QObject*)), this, SLOT(onConversationClosed(QObject*))); disconnect(conv, SIGNAL(destroyed(QObject*)), this, SLOT(onConversationClosed(QObject*)));
disconnect(conv, SIGNAL(sendMessage(const Shared::Message&)), this, SLOT(onConversationMessage(const Shared::Message&))); disconnect(conv, SIGNAL(sendMessage(const Shared::Message&)), this, SLOT(onConversationMessage(const Shared::Message&)));
disconnect(conv, SIGNAL(requestArchive(const QString&)), this, SLOT(onConversationRequestArchive(const QString&))); disconnect(conv, SIGNAL(requestArchive(const QString&)), this, SLOT(onConversationRequestArchive(const QString&)));
disconnect(conv, SIGNAL(shown()), this, SLOT(onConversationShown()));
conv->close(); conv->close();
conversations.erase(lItr); conversations.erase(lItr);
} else { } else {

View File

@ -4,6 +4,7 @@
#include <QMainWindow> #include <QMainWindow>
#include <QScopedPointer> #include <QScopedPointer>
#include <QCloseEvent> #include <QCloseEvent>
#include <QtDBus/QDBusInterface>
#include <deque> #include <deque>
#include <map> #include <map>
#include <list> #include <list>
@ -65,9 +66,11 @@ private:
Models::Roster rosterModel; Models::Roster rosterModel;
Conversations conversations; Conversations conversations;
QMenu* contextMenu; QMenu* contextMenu;
QDBusInterface dbus;
protected: protected:
void closeEvent(QCloseEvent * event) override; void closeEvent(QCloseEvent * event) override;
void notify(const QString& account, const Shared::Message& msg);
private slots: private slots:
void onAccounts(); void onAccounts();
@ -81,6 +84,7 @@ private slots:
void onConversationMessage(const Shared::Message& msg); void onConversationMessage(const Shared::Message& msg);
void onConversationRequestArchive(const QString& before); void onConversationRequestArchive(const QString& before);
void onRosterContextMenu(const QPoint& point); void onRosterContextMenu(const QPoint& point);
void onConversationShown();
}; };