From bb509be29a1b0c0c31b31bbbb24a66bccff28e28 Mon Sep 17 00:00:00 2001 From: blue Date: Sat, 15 Jun 2019 18:29:15 +0300 Subject: [PATCH] adding and removing contacts, rester testing --- core/account.cpp | 41 +++++++++---- core/account.h | 1 + core/squawk.cpp | 11 ++++ core/squawk.h | 1 + main.cpp | 5 ++ ui/CMakeLists.txt | 1 + ui/accounts.cpp | 1 + ui/models/accounts.cpp | 15 +++++ ui/models/accounts.h | 3 + ui/models/roster.cpp | 11 +++- ui/newcontact.cpp | 78 +++++++++++++++++++++++++ ui/newcontact.h | 54 +++++++++++++++++ ui/newcontact.ui | 129 +++++++++++++++++++++++++++++++++++++++++ ui/squawk.cpp | 32 ++++++++++ ui/squawk.h | 5 ++ ui/squawk.ui | 15 ++++- 16 files changed, 389 insertions(+), 14 deletions(-) create mode 100644 ui/newcontact.cpp create mode 100644 ui/newcontact.h create mode 100644 ui/newcontact.ui diff --git a/core/account.cpp b/core/account.cpp index dfa2191..6062c10 100644 --- a/core/account.cpp +++ b/core/account.cpp @@ -195,11 +195,14 @@ void Core::Account::onRosterItemRemoved(const QString& bareJid) return; } Contact* contact = itr->second; + contacts.erase(itr); QSet cGroups = contact->getGroups(); for (QSet::const_iterator itr = cGroups.begin(), end = cGroups.end(); itr != end; ++itr) { removeFromGroup(bareJid, *itr); } emit removeContact(bareJid); + + contact->deleteLater(); } void Core::Account::addedAccount(const QString& jid) @@ -240,17 +243,22 @@ void Core::Account::addedAccount(const QString& jid) if (grCount == 0) { emit addContact(jid, "", cData); } - - QObject::connect(contact, SIGNAL(groupAdded(const QString&)), this, SLOT(onContactGroupAdded(const QString&))); - QObject::connect(contact, SIGNAL(groupRemoved(const QString&)), this, SLOT(onContactGroupRemoved(const QString&))); - QObject::connect(contact, SIGNAL(nameChanged(const QString&)), this, SLOT(onContactNameChanged(const QString&))); - QObject::connect(contact, SIGNAL(subscriptionStateChanged(Shared::SubscriptionState)), - this, SLOT(onContactSubscriptionStateChanged(Shared::SubscriptionState))); - QObject::connect(contact, SIGNAL(needHistory(const QString&, const QString&)), this, SLOT(onContactNeedHistory(const QString&, const QString&))); - QObject::connect(contact, SIGNAL(historyResponse(const std::list&)), this, SLOT(onContactHistoryResponse(const std::list&))); + handleNewContact(contact); } } +void Core::Account::handleNewContact(Core::Contact* contact) +{ + QObject::connect(contact, SIGNAL(groupAdded(const QString&)), this, SLOT(onContactGroupAdded(const QString&))); + QObject::connect(contact, SIGNAL(groupRemoved(const QString&)), this, SLOT(onContactGroupRemoved(const QString&))); + QObject::connect(contact, SIGNAL(nameChanged(const QString&)), this, SLOT(onContactNameChanged(const QString&))); + QObject::connect(contact, SIGNAL(subscriptionStateChanged(Shared::SubscriptionState)), + this, SLOT(onContactSubscriptionStateChanged(Shared::SubscriptionState))); + QObject::connect(contact, SIGNAL(needHistory(const QString&, const QString&)), this, SLOT(onContactNeedHistory(const QString&, const QString&))); + QObject::connect(contact, SIGNAL(historyResponse(const std::list&)), this, SLOT(onContactHistoryResponse(const std::list&))); +} + + void Core::Account::onPresenceReceived(const QXmppPresence& presence) { QString id = presence.from(); @@ -431,8 +439,21 @@ bool Core::Account::handleChatMessage(const QXmppMessage& msg, bool outgoing, bo const QString& id(msg.id()); Shared::Message sMsg(Shared::Message::chat); initializeMessage(sMsg, msg, outgoing, forwarded, guessing); - std::map::const_iterator itr = contacts.find(sMsg.getPenPalJid()); - itr->second->appendMessageToArchive(sMsg); + QString jid = sMsg.getPenPalJid(); + std::map::const_iterator itr = contacts.find(jid); + Contact* cnt; + if (itr != contacts.end()) { + cnt = itr->second; + } else { + cnt = new Contact(jid, name); + contacts.insert(std::make_pair(jid, cnt)); + cnt->setSubscriptionState(Shared::unknown); + emit addContact(jid, "", QMap({ + {"state", Shared::unknown} + })); + handleNewContact(cnt); + } + cnt->appendMessageToArchive(sMsg); emit message(sMsg); diff --git a/core/account.h b/core/account.h index fb2b7d8..1bac071 100644 --- a/core/account.h +++ b/core/account.h @@ -107,6 +107,7 @@ private slots: private: void addedAccount(const QString &bareJid); + void handleNewContact(Contact* contact); bool handleChatMessage(const QXmppMessage& msg, bool outgoing = false, bool forwarded = false, bool guessing = false); void addToGroup(const QString& jid, const QString& group); void removeFromGroup(const QString& jid, const QString& group); diff --git a/core/squawk.cpp b/core/squawk.cpp index e776a20..d53a1c3 100644 --- a/core/squawk.cpp +++ b/core/squawk.cpp @@ -365,3 +365,14 @@ void Core::Squawk::removeContactRequest(const QString& account, const QString& j itr->second->removeContactRequest(jid); } + +void Core::Squawk::addContactRequest(const QString& account, const QString& jid, const QString& name, const QSet& groups) +{ + AccountsMap::const_iterator itr = amap.find(account); + if (itr == amap.end()) { + qDebug("An attempt to add contact to a non existing account, skipping"); + return; + } + + itr->second->addContactRequest(jid, name, groups); +} diff --git a/core/squawk.h b/core/squawk.h index 9126fe3..fa65fa8 100644 --- a/core/squawk.h +++ b/core/squawk.h @@ -52,6 +52,7 @@ public slots: void subscribeContact(const QString& account, const QString& jid, const QString& reason); void unsubscribeContact(const QString& account, const QString& jid, const QString& reason); void removeContactRequest(const QString& account, const QString& jid); + void addContactRequest(const QString& account, const QString& jid, const QString& name, const QSet& groups); private: typedef std::deque Accounts; diff --git a/main.cpp b/main.cpp index dfe8f8a..28c0779 100644 --- a/main.cpp +++ b/main.cpp @@ -10,6 +10,7 @@ int main(int argc, char *argv[]) { qRegisterMetaType("Shared::Message"); qRegisterMetaType>("std::list"); + qRegisterMetaType>("QSet"); QApplication app(argc, argv); SignalCatcher sc(&app); @@ -45,6 +46,10 @@ int main(int argc, char *argv[]) squawk, SLOT(subscribeContact(const QString&, const QString&, const QString&))); QObject::connect(&w, SIGNAL(unsubscribeContact(const QString&, const QString&, const QString&)), squawk, SLOT(unsubscribeContact(const QString&, const QString&, const QString&))); + QObject::connect(&w, SIGNAL(addContactRequest(const QString&, const QString&, const QString&, const QSet&)), + squawk, SLOT(addContactRequest(const QString&, const QString&, const QString&, const QSet&))); + QObject::connect(&w, SIGNAL(removeContactRequest(const QString&, const QString&)), + squawk, SLOT(removeContactRequest(const QString&, const QString&))); QObject::connect(squawk, SIGNAL(newAccount(const QMap&)), &w, SLOT(newAccount(const QMap&))); QObject::connect(squawk, SIGNAL(addContact(const QString&, const QString&, const QString&, const QMap&)), diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index c5f7a42..d70e04b 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -21,6 +21,7 @@ set(squawkUI_SRC models/presence.cpp conversation.cpp messageline.cpp + newcontact.cpp ) # Tell CMake to create the helloworld executable diff --git a/ui/accounts.cpp b/ui/accounts.cpp index 6123c98..043ebb2 100644 --- a/ui/accounts.cpp +++ b/ui/accounts.cpp @@ -42,6 +42,7 @@ void Accounts::onAccountAccepted() emit newAccount(map); } + acc->deleteLater(); editing = false; } diff --git a/ui/models/accounts.cpp b/ui/models/accounts.cpp index 7edd888..e64e2c3 100644 --- a/ui/models/accounts.cpp +++ b/ui/models/accounts.cpp @@ -66,6 +66,8 @@ void Models::Accounts::addAccount(Account* account) accs.push_back(account); connect(account, SIGNAL(childChanged(Models::Item*, int, int)), this, SLOT(onAccountChanged(Models::Item*, int, int))); endInsertRows(); + + emit sizeChanged(accs.size()); } void Models::Accounts::onAccountChanged(Item* item, int row, int col) @@ -93,4 +95,17 @@ void Models::Accounts::removeAccount(int index) disconnect(account, SIGNAL(childChanged(Models::Item*, int, int)), this, SLOT(onAccountChanged(Models::Item*, int, int))); accs.erase(accs.begin() + index); endRemoveRows(); + + emit sizeChanged(accs.size()); +} + +std::deque Models::Accounts::getNames() const +{ + std::deque res; + + for (std::deque::const_iterator i = accs.begin(), end = accs.end(); i != end; ++i) { + res.push_back((*i)->getName()); + } + + return res; } diff --git a/ui/models/accounts.h b/ui/models/accounts.h index 3718acd..dd88ab9 100644 --- a/ui/models/accounts.h +++ b/ui/models/accounts.h @@ -25,8 +25,11 @@ public: Account* getAccount(int index); + std::deque getNames() const; + signals: void changed(); + void sizeChanged(unsigned int size); private: std::deque accs; diff --git a/ui/models/roster.cpp b/ui/models/roster.cpp index 9d75ef1..beda4c1 100644 --- a/ui/models/roster.cpp +++ b/ui/models/roster.cpp @@ -260,6 +260,7 @@ void Models::Roster::addContact(const QString& account, const QString& jid, cons qDebug() << "An attempt to add a contact " << jid << " ungrouped to non the account " << account << " for the second time, skipping"; return; } + itr++; } parent = acc; } else { @@ -345,7 +346,8 @@ void Models::Roster::removeGroup(const QString& account, const QString& name) } } - delete item; + item->deleteLater(); + groups.erase(gItr); } void Models::Roster::changeContact(const QString& account, const QString& jid, const QMap& data) @@ -366,6 +368,7 @@ void Models::Roster::removeContact(const QString& account, const QString& jid) ElId id(account, jid); std::multimap::iterator cBeg = contacts.lower_bound(id); std::multimap::iterator cEnd = contacts.upper_bound(id); + std::multimap::iterator cpBeg = cBeg; QSet toRemove; for (; cBeg != cEnd; ++cBeg) { @@ -376,8 +379,9 @@ void Models::Roster::removeContact(const QString& account, const QString& jid) } parent->removeChild(contact->row()); - delete contact; + contact->deleteLater(); } + contacts.erase(cpBeg, cEnd); for (QSet::const_iterator itr = toRemove.begin(), end = toRemove.end(); itr != end; ++itr) { removeGroup(account, *itr); @@ -402,6 +406,7 @@ void Models::Roster::removeContact(const QString& account, const QString& jid, c for (;cBeg != cEnd; ++cBeg) { if (cBeg->second->parentItem() == gr) { cont = cBeg->second; + contacts.erase(cBeg); break; } } @@ -412,7 +417,7 @@ void Models::Roster::removeContact(const QString& account, const QString& jid, c } gr->removeChild(cont->row()); - delete cont; + cont->deleteLater(); if (gr->childCount() == 0) { removeGroup(account, group); diff --git a/ui/newcontact.cpp b/ui/newcontact.cpp new file mode 100644 index 0000000..7399474 --- /dev/null +++ b/ui/newcontact.cpp @@ -0,0 +1,78 @@ +/* + * + * Copyright (C) 2019 Юрий Губич + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "newcontact.h" +#include "ui_newcontact.h" +#include + +NewContact::NewContact(const Models::Accounts* accounts, QWidget* parent): + QDialog(parent), + m_ui(new Ui::NewContact()) +{ + m_ui->setupUi ( this ); + std::deque names = accounts->getNames(); + + for (std::deque::const_iterator i = names.begin(), end = names.end(); i != end; i++) { + m_ui->account->addItem(*i); + } + + m_ui->account->setCurrentIndex(0); +} + +NewContact::NewContact(const QString& acc, const Models::Accounts* accounts, QWidget* parent): + QDialog(parent), + m_ui(new Ui::NewContact()) +{ + + m_ui->setupUi ( this ); + std::deque names = accounts->getNames(); + + int index = 0; + bool found = false; + for (std::deque::const_iterator i = names.begin(), end = names.end(); i != end; i++) { + const QString& name = *i; + m_ui->account->addItem(name); + if (!found) { + if (name == acc) { + found = true; + } else { + index++; + } + } + } + + if (!found) { + qDebug() << "Couldn't find a correct account among available accounts creating NewContact dialog, setting to 0"; + } + + m_ui->account->setCurrentIndex(index); +} + +NewContact::~NewContact() +{ +} + +NewContact::Data NewContact::value() const +{ + return { + m_ui->jid->text(), + m_ui->name->text(), + m_ui->account->currentText(), + {} + }; +} diff --git a/ui/newcontact.h b/ui/newcontact.h new file mode 100644 index 0000000..2c18812 --- /dev/null +++ b/ui/newcontact.h @@ -0,0 +1,54 @@ +/* + * + * Copyright (C) 2019 Юрий Губич + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef NEWCONTACT_H +#define NEWCONTACT_H + +#include +#include +#include + +#include "models/accounts.h" + +namespace Ui +{ +class NewContact; +} + +class NewContact : public QDialog +{ + Q_OBJECT +public: + struct Data { + QString jid; + QString name; + QString account; + QSet groups; + }; + + NewContact(const Models::Accounts* accounts, QWidget* parent = 0); + NewContact(const QString& acc, const Models::Accounts* accounts, QWidget* parent = 0); + ~NewContact(); + + Data value() const; + +private: + QScopedPointer m_ui; +}; + +#endif // NEWCONTACT_H diff --git a/ui/newcontact.ui b/ui/newcontact.ui new file mode 100644 index 0000000..923397d --- /dev/null +++ b/ui/newcontact.ui @@ -0,0 +1,129 @@ + + + NewContact + + + + 0 + 0 + 376 + 222 + + + + NewContact + + + + + + + + Account + + + + + + + An account that is going to have new contact + + + + + + + JID + + + + + + + Jabber id of your new contact + + + name@server.dmn + + + + + + + Name + + + + + + + The way this new contact will be labeled in your roster (optional) + + + John Smith + + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + NewContact + accept() + + + 20 + 20 + + + 20 + 20 + + + + + buttonBox + rejected() + NewContact + reject() + + + 20 + 20 + + + 20 + 20 + + + + + diff --git a/ui/squawk.cpp b/ui/squawk.cpp index d2599aa..1d45a27 100644 --- a/ui/squawk.cpp +++ b/ui/squawk.cpp @@ -21,9 +21,12 @@ Squawk::Squawk(QWidget *parent) : m_ui->comboBox->setCurrentIndex(Shared::offline); connect(m_ui->actionAccounts, SIGNAL(triggered()), this, SLOT(onAccounts())); + connect(m_ui->actionAddContact, SIGNAL(triggered()), this, SLOT(onNewContact())); connect(m_ui->comboBox, SIGNAL(activated(int)), this, SLOT(onComboboxActivated(int))); connect(m_ui->roster, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(onRosterItemDoubleClicked(const QModelIndex&))); connect(m_ui->roster, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(onRosterContextMenu(const QPoint&))); + + connect(rosterModel.accountsModel, SIGNAL(sizeChanged(unsigned int)), this, SLOT(onAccountsSizeChanged(unsigned int))); //m_ui->mainToolBar->addWidget(m_ui->comboBox); } @@ -51,6 +54,35 @@ void Squawk::onAccounts() } } +void Squawk::onAccountsSizeChanged(unsigned int size) +{ + if (size > 0) { + m_ui->actionAddContact->setEnabled(true); + } else { + m_ui->actionAddContact->setEnabled(false); + } +} + +void Squawk::onNewContact() +{ + NewContact* nc = new NewContact(rosterModel.accountsModel, this); + + connect(nc, SIGNAL(accepted()), this, SLOT(onNewContactAccepted())); + connect(nc, SIGNAL(rejected()), nc, SLOT(deleteLater())); + + nc->exec(); +} + +void Squawk::onNewContactAccepted() +{ + NewContact* nc = static_cast(sender()); + NewContact::Data value = nc->value(); + + emit addContactRequest(value.account, value.jid, value.name, value.groups); + + nc->deleteLater(); +} + void Squawk::closeEvent(QCloseEvent* event) { if (accounts != 0) { diff --git a/ui/squawk.h b/ui/squawk.h index 5d8a4ee..081965d 100644 --- a/ui/squawk.h +++ b/ui/squawk.h @@ -11,6 +11,7 @@ #include "accounts.h" #include "conversation.h" #include "models/roster.h" +#include "newcontact.h" #include "../global.h" @@ -38,6 +39,7 @@ signals: void subscribeContact(const QString& account, const QString& jid, const QString& reason); void unsubscribeContact(const QString& account, const QString& jid, const QString& reason); void removeContactRequest(const QString& account, const QString& jid); + void addContactRequest(const QString& account, const QString& jid, const QString& name, const QSet& groups); public slots: void newAccount(const QMap& account); @@ -69,6 +71,9 @@ protected: private slots: void onAccounts(); + void onNewContact(); + void onNewContactAccepted(); + void onAccountsSizeChanged(unsigned int size); void onAccountsClosed(QObject* parent = 0); void onConversationClosed(QObject* parent = 0); void onComboboxActivated(int index); diff --git a/ui/squawk.ui b/ui/squawk.ui index cf51038..a137729 100644 --- a/ui/squawk.ui +++ b/ui/squawk.ui @@ -80,6 +80,7 @@ File + @@ -96,12 +97,24 @@ - + + .. Quit + + + false + + + + + + Add contact + +