forked from blue/squawk
better new message handling, subscription with adding new contact, out of roster contacts handling
This commit is contained in:
parent
bb509be29a
commit
b2699e0087
@ -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";
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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") {
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user