2019-03-29 14:54:34 +00:00
|
|
|
#include "squawk.h"
|
|
|
|
#include "ui_squawk.h"
|
2019-04-02 15:46:18 +00:00
|
|
|
#include <QDebug>
|
2019-04-07 20:14:15 +00:00
|
|
|
#include <QIcon>
|
2019-03-29 14:54:34 +00:00
|
|
|
|
|
|
|
Squawk::Squawk(QWidget *parent) :
|
|
|
|
QMainWindow(parent),
|
|
|
|
m_ui(new Ui::Squawk),
|
2019-03-30 20:13:13 +00:00
|
|
|
accounts(0),
|
2019-04-09 15:04:08 +00:00
|
|
|
rosterModel(),
|
|
|
|
conversations()
|
2019-03-29 14:54:34 +00:00
|
|
|
{
|
|
|
|
m_ui->setupUi(this);
|
2019-03-31 21:05:09 +00:00
|
|
|
m_ui->roster->setModel(&rosterModel);
|
2019-03-29 14:54:34 +00:00
|
|
|
|
2019-04-07 20:14:15 +00:00
|
|
|
for (int i = 0; i < Shared::availabilityNames.size(); ++i) {
|
|
|
|
m_ui->comboBox->addItem(QIcon::fromTheme(Shared::availabilityThemeIcons[i]), Shared::availabilityNames[i]);
|
|
|
|
}
|
|
|
|
m_ui->comboBox->setCurrentIndex(Shared::offline);
|
|
|
|
|
2019-04-02 15:46:18 +00:00
|
|
|
connect(m_ui->actionAccounts, SIGNAL(triggered()), this, SLOT(onAccounts()));
|
2019-03-31 21:05:09 +00:00
|
|
|
connect(m_ui->comboBox, SIGNAL(activated(int)), this, SLOT(onComboboxActivated(int)));
|
2019-04-09 15:04:08 +00:00
|
|
|
connect(m_ui->roster, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(onRosterItemDoubleClicked(const QModelIndex&)));
|
2019-03-31 21:05:09 +00:00
|
|
|
//m_ui->mainToolBar->addWidget(m_ui->comboBox);
|
2019-03-29 14:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Squawk::~Squawk() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Squawk::onAccounts()
|
|
|
|
{
|
|
|
|
if (accounts == 0) {
|
2019-04-03 18:15:36 +00:00
|
|
|
accounts = new Accounts(rosterModel.accountsModel, this);
|
2019-03-29 14:54:34 +00:00
|
|
|
accounts->setAttribute(Qt::WA_DeleteOnClose);
|
|
|
|
connect(accounts, SIGNAL(destroyed(QObject*)), this, SLOT(onAccountsClosed(QObject*)));
|
2019-03-30 20:13:13 +00:00
|
|
|
connect(accounts, SIGNAL(newAccount(const QMap<QString, QVariant>&)), this, SIGNAL(newAccountRequest(const QMap<QString, QVariant>&)));
|
2019-05-24 14:46:34 +00:00
|
|
|
connect(accounts, SIGNAL(changeAccount(const QString&, const QMap<QString, QVariant>&)), this, SIGNAL(modifyAccountRequest(const QString&, const QMap<QString, QVariant>&)));
|
2019-03-30 20:13:13 +00:00
|
|
|
|
2019-03-29 14:54:34 +00:00
|
|
|
accounts->show();
|
|
|
|
} else {
|
2019-03-30 20:13:13 +00:00
|
|
|
accounts->show();
|
|
|
|
accounts->raise();
|
|
|
|
accounts->activateWindow();
|
2019-03-29 14:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Squawk::closeEvent(QCloseEvent* event)
|
|
|
|
{
|
|
|
|
if (accounts != 0) {
|
|
|
|
accounts->close();
|
|
|
|
}
|
2019-04-09 15:04:08 +00:00
|
|
|
for (Conversations::const_iterator itr = conversations.begin(), end = conversations.end(); itr != end; ++itr) {
|
|
|
|
disconnect(itr->second, SIGNAL(destroyed(QObject*)), this, SLOT(onConversationClosed(QObject*)));
|
|
|
|
itr->second->close();
|
|
|
|
}
|
|
|
|
conversations.clear();
|
2019-03-29 14:54:34 +00:00
|
|
|
|
|
|
|
QMainWindow::closeEvent(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Squawk::onAccountsClosed(QObject* parent)
|
|
|
|
{
|
|
|
|
accounts = 0;
|
|
|
|
}
|
2019-03-30 20:13:13 +00:00
|
|
|
|
|
|
|
void Squawk::newAccount(const QMap<QString, QVariant>& account)
|
|
|
|
{
|
2019-03-31 21:05:09 +00:00
|
|
|
rosterModel.addAccount(account);
|
2019-03-30 20:13:13 +00:00
|
|
|
}
|
2019-03-31 21:05:09 +00:00
|
|
|
|
|
|
|
void Squawk::onComboboxActivated(int index)
|
|
|
|
{
|
2019-04-07 20:14:15 +00:00
|
|
|
if (index != Shared::offline) {
|
2019-04-03 18:15:36 +00:00
|
|
|
int size = rosterModel.accountsModel->rowCount(QModelIndex());
|
|
|
|
if (size > 0) {
|
2019-04-07 20:14:15 +00:00
|
|
|
emit changeState(index);
|
2019-04-03 18:15:36 +00:00
|
|
|
for (int i = 0; i < size; ++i) {
|
|
|
|
Models::Account* acc = rosterModel.accountsModel->getAccount(i);
|
|
|
|
if (acc->getState() == Shared::disconnected) {
|
|
|
|
emit connectAccount(acc->getName());
|
2019-03-31 21:05:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2019-04-07 20:14:15 +00:00
|
|
|
m_ui->comboBox->setCurrentIndex(Shared::offline);
|
2019-03-31 21:05:09 +00:00
|
|
|
}
|
2019-04-07 20:14:15 +00:00
|
|
|
} else {
|
|
|
|
emit changeState(index);
|
2019-04-03 18:15:36 +00:00
|
|
|
int size = rosterModel.accountsModel->rowCount(QModelIndex());
|
|
|
|
for (int i = 0; i != size; ++i) {
|
|
|
|
Models::Account* acc = rosterModel.accountsModel->getAccount(i);
|
|
|
|
if (acc->getState() != Shared::disconnected) {
|
|
|
|
emit disconnectAccount(acc->getName());
|
2019-03-31 21:05:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-24 14:46:34 +00:00
|
|
|
void Squawk::changeAccount(const QString& account, const QMap<QString, QVariant>& data)
|
2019-03-31 21:05:09 +00:00
|
|
|
{
|
2019-05-24 14:46:34 +00:00
|
|
|
for (QMap<QString, QVariant>::const_iterator itr = data.begin(), end = data.end(); itr != end; ++itr) {
|
|
|
|
QString attr = itr.key();
|
|
|
|
rosterModel.updateAccount(account, attr, *itr);
|
|
|
|
}
|
2019-04-07 20:14:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Squawk::addContact(const QString& account, const QString& jid, const QString& group, const QMap<QString, QVariant>& data)
|
|
|
|
{
|
|
|
|
rosterModel.addContact(account, jid, group, data);
|
2019-04-03 21:23:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Squawk::addGroup(const QString& account, const QString& name)
|
|
|
|
{
|
|
|
|
rosterModel.addGroup(account, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Squawk::removeGroup(const QString& account, const QString& name)
|
|
|
|
{
|
2019-04-06 10:14:32 +00:00
|
|
|
rosterModel.removeGroup(account, name);
|
2019-04-03 21:23:51 +00:00
|
|
|
}
|
|
|
|
|
2019-04-07 20:14:15 +00:00
|
|
|
void Squawk::changeContact(const QString& account, const QString& jid, const QMap<QString, QVariant>& data)
|
2019-04-06 10:14:32 +00:00
|
|
|
{
|
2019-04-07 20:14:15 +00:00
|
|
|
rosterModel.changeContact(account, jid, data);
|
2019-04-06 10:14:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Squawk::removeContact(const QString& account, const QString& jid)
|
|
|
|
{
|
|
|
|
rosterModel.removeContact(account, jid);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Squawk::removeContact(const QString& account, const QString& jid, const QString& group)
|
|
|
|
{
|
|
|
|
rosterModel.removeContact(account, jid, group);
|
|
|
|
}
|
2019-04-03 21:23:51 +00:00
|
|
|
|
2019-04-07 14:02:41 +00:00
|
|
|
void Squawk::addPresence(const QString& account, const QString& jid, const QString& name, const QMap<QString, QVariant>& data)
|
|
|
|
{
|
|
|
|
rosterModel.addPresence(account, jid, name, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Squawk::removePresence(const QString& account, const QString& jid, const QString& name)
|
|
|
|
{
|
|
|
|
rosterModel.removePresence(account, jid, name);
|
|
|
|
}
|
|
|
|
|
2019-04-07 20:14:15 +00:00
|
|
|
void Squawk::stateChanged(int state)
|
|
|
|
{
|
|
|
|
m_ui->comboBox->setCurrentIndex(state);
|
|
|
|
}
|
2019-04-03 21:23:51 +00:00
|
|
|
|
2019-04-09 15:04:08 +00:00
|
|
|
void Squawk::onRosterItemDoubleClicked(const QModelIndex& item)
|
|
|
|
{
|
|
|
|
if (item.isValid()) {
|
|
|
|
Models::Item* node = static_cast<Models::Item*>(item.internalPointer());
|
|
|
|
Models::Contact* contact = 0;
|
2019-04-12 15:22:10 +00:00
|
|
|
QString res;
|
2019-04-09 15:04:08 +00:00
|
|
|
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());
|
2019-04-12 15:22:10 +00:00
|
|
|
res = node->getName();
|
2019-04-09 15:04:08 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
m_ui->roster->expand(item);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (contact != 0) {
|
|
|
|
QString jid = contact->getJid();
|
|
|
|
QString account = contact->getAccountName();
|
|
|
|
Models::Roster::ElId id(account, jid);
|
|
|
|
Conversations::const_iterator itr = conversations.find(id);
|
|
|
|
if (itr != conversations.end()) {
|
|
|
|
itr->second->show();
|
|
|
|
itr->second->raise();
|
|
|
|
itr->second->activateWindow();
|
2019-04-12 15:22:10 +00:00
|
|
|
|
|
|
|
if (res.size() > 0) {
|
|
|
|
itr->second->setPalResource(res);
|
|
|
|
}
|
2019-04-09 15:04:08 +00:00
|
|
|
} else {
|
|
|
|
Conversation* conv = new Conversation(contact);
|
|
|
|
|
|
|
|
conv->setAttribute(Qt::WA_DeleteOnClose);
|
|
|
|
connect(conv, SIGNAL(destroyed(QObject*)), this, SLOT(onConversationClosed(QObject*)));
|
2019-04-11 14:58:59 +00:00
|
|
|
connect(conv, SIGNAL(sendMessage(const Shared::Message&)), this, SLOT(onConversationMessage(const Shared::Message&)));
|
2019-05-15 17:36:37 +00:00
|
|
|
connect(conv, SIGNAL(requestArchive(const QString&)), this, SLOT(onConversationRequestArchive(const QString&)));
|
2019-04-09 15:04:08 +00:00
|
|
|
|
|
|
|
conversations.insert(std::make_pair(id, conv));
|
2019-04-09 22:01:25 +00:00
|
|
|
rosterModel.dropMessages(account, jid);
|
2019-04-09 15:04:08 +00:00
|
|
|
|
|
|
|
conv->show();
|
2019-04-12 15:22:10 +00:00
|
|
|
|
|
|
|
if (res.size() > 0) {
|
|
|
|
itr->second->setPalResource(res);
|
|
|
|
}
|
2019-04-09 15:04:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Squawk::onConversationClosed(QObject* parent)
|
|
|
|
{
|
|
|
|
Conversation* conv = static_cast<Conversation*>(sender());
|
|
|
|
Conversations::const_iterator itr = conversations.find({conv->getAccount(), conv->getJid()});
|
|
|
|
if (itr == conversations.end()) {
|
|
|
|
qDebug() << "Conversation has been closed but can not be found among other opened conversations, application is most probably going to crash";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
conversations.erase(itr);
|
|
|
|
}
|
2019-04-09 22:01:25 +00:00
|
|
|
|
2019-04-11 14:58:59 +00:00
|
|
|
void Squawk::accountMessage(const QString& account, const Shared::Message& data)
|
2019-04-09 22:01:25 +00:00
|
|
|
{
|
2019-04-11 14:58:59 +00:00
|
|
|
const QString& from = data.getPenPalJid();
|
2019-04-09 22:01:25 +00:00
|
|
|
Conversations::iterator itr = conversations.find({account, from});
|
|
|
|
if (itr != conversations.end()) {
|
|
|
|
itr->second->addMessage(data);
|
|
|
|
} else {
|
2019-04-12 15:22:10 +00:00
|
|
|
if (!data.getForwarded()) {
|
|
|
|
rosterModel.addMessage(account, data);
|
|
|
|
}
|
2019-04-09 22:01:25 +00:00
|
|
|
}
|
|
|
|
}
|
2019-04-10 20:53:42 +00:00
|
|
|
|
2019-04-11 14:58:59 +00:00
|
|
|
void Squawk::onConversationMessage(const Shared::Message& msg)
|
2019-04-10 20:53:42 +00:00
|
|
|
{
|
|
|
|
Conversation* conv = static_cast<Conversation*>(sender());
|
2019-04-11 14:58:59 +00:00
|
|
|
|
|
|
|
emit sendMessage(conv->getAccount(), msg);
|
2019-04-10 20:53:42 +00:00
|
|
|
}
|
2019-05-15 17:36:37 +00:00
|
|
|
|
|
|
|
void Squawk::onConversationRequestArchive(const QString& before)
|
|
|
|
{
|
|
|
|
Conversation* conv = static_cast<Conversation*>(sender());
|
|
|
|
requestArchive(conv->getAccount(), conv->getJid(), 20, before); //TODO amount as a settings value
|
|
|
|
}
|
|
|
|
|
|
|
|
void Squawk::responseArchive(const QString& account, const QString& jid, const std::list<Shared::Message>& list)
|
|
|
|
{
|
|
|
|
Models::Roster::ElId id(account, jid);
|
|
|
|
|
|
|
|
Conversations::const_iterator itr = conversations.find(id);
|
|
|
|
if (itr != conversations.end()) {
|
|
|
|
itr->second->responseArchive(list);
|
|
|
|
}
|
|
|
|
}
|