more info about groups, tooltip fixes, logo corretions, invisible state, initiated fallback icons

This commit is contained in:
Blue 2019-06-22 23:37:22 +03:00
parent e456ba980d
commit 49aa99d4db
41 changed files with 1237 additions and 54 deletions

View file

@ -243,7 +243,16 @@ void Models::Contact::addMessage(const Shared::Message& data)
if (res.size() > 0) {
QMap<QString, Presence*>::iterator itr = presences.find(res);
if (itr == presences.end()) {
qDebug() << "An attempt to add message to the roster to the unknown resource " << res << " of contact " << jid << " in account " << getAccountName() << ", skipping";
// this is actually the place when I can spot someone's invisible presence, and there is nothing criminal in it, cuz the sender sent us a message
// therefore he have revealed himself
// the only issue is to find out when the sender is gone offline
Presence* pr = new Presence({});
pr->setName(res);
pr->setAvailability(Shared::invisible);
pr->setLastActivity(QDateTime::currentDateTime());
presences.insert(res, pr);
appendChild(pr);
pr->addMessage(data);
return;
}
itr.value()->addMessage(data);

105
ui/models/group.cpp Normal file
View file

@ -0,0 +1,105 @@
/*
* <one line to give the program's name and a brief idea of what it does.>
* Copyright (C) 2019 Юрий Губич <y.gubich@initi.ru>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "group.h"
#include "contact.h"
Models::Group::Group(const QMap<QString, QVariant>& data, Models::Item* parentItem):
Item(group, data, parentItem),
unreadMessages(0)
{
}
Models::Group::~Group()
{
}
void Models::Group::appendChild(Models::Item* child)
{
Item::appendChild(child);
connect(child, SIGNAL(childChanged(Models::Item*, int, int)), this, SLOT(refresh()));
changed(1);
refresh();
}
int Models::Group::columnCount() const
{
return 3;
}
QVariant Models::Group::data(int column) const
{
switch (column) {
case 0:
return getName();
case 1:
return QVariant((unsigned int)childItems.size());
case 2:
return unreadMessages;
default:
return QVariant();
}
}
void Models::Group::_removeChild(int index)
{
Item* child = childItems[index];
disconnect(child, SIGNAL(childChanged(Models::Item*, int, int)), this, SLOT(refresh()));
Item::_removeChild(index);
changed(1);
refresh();
}
unsigned int Models::Group::getUnreadMessages() const
{
return unreadMessages;
}
void Models::Group::setUnreadMessages(unsigned int amount)
{
if (unreadMessages != amount) {
unreadMessages = amount;
changed(2);
}
}
void Models::Group::refresh()
{
unsigned int newAmount(0);
for (std::deque<Models::Item*>::const_iterator itr = childItems.begin(), end = childItems.end(); itr != end; ++itr) {
Models::Contact* cnt = static_cast<Models::Contact*>(*itr);
newAmount += cnt->getMessagesCount();
}
setUnreadMessages(newAmount);
}
unsigned int Models::Group::getOnlineContacts() const
{
unsigned int amount(0);
for (std::deque<Models::Item*>::const_iterator itr = childItems.begin(), end = childItems.end(); itr != end; ++itr) {
Models::Contact* cnt = static_cast<Models::Contact*>(*itr);
if (cnt->getAvailability() != Shared::offline) {
++amount;
}
}
return amount;
}

54
ui/models/group.h Normal file
View file

@ -0,0 +1,54 @@
/*
* <one line to give the program's name and a brief idea of what it does.>
* Copyright (C) 2019 Юрий Губич <y.gubich@initi.ru>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef MODELS_GROUP_H
#define MODELS_GROUP_H
#include "item.h"
namespace Models {
class Group : public Models::Item
{
Q_OBJECT
public:
Group(const QMap<QString, QVariant> &data, Item *parentItem = 0);
~Group();
void appendChild(Models::Item* child) override;
int columnCount() const override;
QVariant data(int column) const override;
unsigned int getUnreadMessages() const;
unsigned int getOnlineContacts() const;
protected:
void _removeChild(int index) override;
void setUnreadMessages(unsigned int amount);
private slots:
void refresh();
private:
unsigned int unreadMessages;
};
}
#endif // MODELS_GROUP_H

View file

@ -52,7 +52,24 @@ QVariant Models::Roster::data (const QModelIndex& index, int role) const
switch (role) {
case Qt::DisplayRole:
{
result = item->data(index.column());
switch (item->type) {
case Item::group: {
Group* gr = static_cast<Group*>(item);
QString str("");
str += gr->getName();
unsigned int amount = gr->getUnreadMessages();
if (amount > 0) {
str += QString(" (") + "New messages" + ")";
}
result = str;
}
break;
default:
result = item->data(index.column());
break;
}
}
break;
case Qt::DecorationRole:
@ -98,12 +115,12 @@ QVariant Models::Roster::data (const QModelIndex& index, int role) const
switch (item->type) {
case Item::account: {
Account* acc = static_cast<Account*>(item);
result = QString(Shared::connectionStateNames[acc->getAvailability()]);
result = QString(Shared::availabilityNames[acc->getAvailability()]);
}
break;
case Item::contact: {
Contact* contact = static_cast<Contact*>(item);
QString str = QString("");
QString str("");
int mc = contact->getMessagesCount();
if (mc > 0) {
str += QString("New messages: ") + std::to_string(mc).c_str() + "\n";
@ -128,7 +145,7 @@ QVariant Models::Roster::data (const QModelIndex& index, int role) const
break;
case Item::presence: {
Presence* contact = static_cast<Presence*>(item);
QString str = QString("");
QString str("");
int mc = contact->getMessagesCount();
if (mc > 0) {
str += QString("New messages: ") + std::to_string(mc).c_str() + "\n";
@ -140,6 +157,18 @@ QVariant Models::Roster::data (const QModelIndex& index, int role) const
str += "\nStatus: " + s;
}
result = str;
}
break;
case Item::group: {
Group* gr = static_cast<Group*>(item);
unsigned int count = gr->getUnreadMessages();
QString str("");
if (count > 0) {
str += QString("New messages: ") + std::to_string(count).c_str() + "\n";
}
str += QString("Online contacts: ") + std::to_string(gr->getOnlineContacts()).c_str() + "\n";
str += QString("Total contacts: ") + std::to_string(gr->childCount()).c_str();
result = str;
}
break;
@ -275,7 +304,7 @@ void Models::Roster::onAccountDataChanged(const QModelIndex& tl, const QModelInd
void Models::Roster::addGroup(const QString& account, const QString& name)
{
ElId id(account, name);
std::map<ElId, Item*>::const_iterator gItr = groups.find(id);
std::map<ElId, Group*>::const_iterator gItr = groups.find(id);
if (gItr != groups.end()) {
qDebug() << "An attempt to add group " << name << " to account " << account <<" which already exists there, skipping";
return;
@ -283,7 +312,7 @@ void Models::Roster::addGroup(const QString& account, const QString& name)
std::map<QString, Account*>::iterator itr = accounts.find(account);
if (itr != accounts.end()) {
Account* acc = itr->second;
Item* group = new Item(Item::group, {{"name", name}});
Group* group = new Group({{"name", name}});
acc->appendChild(group);
groups.insert(std::make_pair(id, group));
} else {
@ -319,7 +348,7 @@ void Models::Roster::addContact(const QString& account, const QString& jid, cons
}
parent = acc;
} else {
std::map<ElId, Item*>::iterator itr = groups.find({account, group});
std::map<ElId, Group*>::iterator itr = groups.find({account, group});
if (itr == groups.end()) {
qDebug() << "An attempt to add a contact " << jid << " to non existing group " << group << ", skipping";
return;
@ -360,12 +389,12 @@ void Models::Roster::addContact(const QString& account, const QString& jid, cons
void Models::Roster::removeGroup(const QString& account, const QString& name)
{
ElId id(account, name);
std::map<ElId, Item*>::const_iterator gItr = groups.find(id);
std::map<ElId, Group*>::const_iterator gItr = groups.find(id);
if (gItr == groups.end()) {
qDebug() << "An attempt to remove group " << name << " from account " << account <<" which doesn't exist there, skipping";
return;
}
Item* item = gItr->second;
Group* item = gItr->second;
Item* parent = item->parentItem();
int row = item->row();
@ -448,12 +477,12 @@ void Models::Roster::removeContact(const QString& account, const QString& jid, c
ElId contactId(account, jid);
ElId groupId(account, group);
std::map<ElId, Item*>::iterator gItr = groups.find(groupId);
std::map<ElId, Group*>::iterator gItr = groups.find(groupId);
if (gItr == groups.end()) {
qDebug() << "An attempt to remove contact " << jid << " from non existing group " << group << " of account " << account <<", skipping";
return;
}
Item* gr = gItr->second;
Group* gr = gItr->second;
Contact* cont = 0;
std::multimap<ElId, Contact*>::iterator cBeg = contacts.lower_bound(contactId);
@ -598,10 +627,10 @@ void Models::Roster::removeAccount(const QString& account)
}
}
std::map<ElId, Item*>::const_iterator gItr = groups.begin();
std::map<ElId, Group*>::const_iterator gItr = groups.begin();
while (gItr != groups.end()) {
if (gItr->first.account == account) {
std::map<ElId, Item*>::const_iterator lItr = gItr;
std::map<ElId, Group*>::const_iterator lItr = gItr;
++gItr;
groups.erase(lItr);
} else {

View file

@ -10,6 +10,7 @@
#include "item.h"
#include "account.h"
#include "contact.h"
#include "group.h"
namespace Models
{
@ -50,7 +51,7 @@ public:
private:
Item* root;
std::map<QString, Account*> accounts;
std::map<ElId, Item*> groups;
std::map<ElId, Group*> groups;
std::multimap<ElId, Contact*> contacts;
private slots: