From 9c855553c5ace9bc20964dc1121f90bdd820ba66 Mon Sep 17 00:00:00 2001 From: blue Date: Sat, 18 Apr 2020 15:02:01 +0300 Subject: [PATCH] referencing seems to be working now --- ui/models/contact.cpp | 27 +++++++++++++++------------ ui/models/contact.h | 2 +- ui/models/group.cpp | 28 +++++++++++++++++++--------- ui/models/group.h | 2 +- ui/models/item.cpp | 24 ++++++++++++++++++++---- ui/models/item.h | 13 ++++++------- ui/models/reference.cpp | 20 +++++++++++++++----- ui/models/roster.cpp | 2 -- 8 files changed, 77 insertions(+), 41 deletions(-) diff --git a/ui/models/contact.cpp b/ui/models/contact.cpp index cc3caba..57744d8 100644 --- a/ui/models/contact.cpp +++ b/ui/models/contact.cpp @@ -226,9 +226,9 @@ void Models::Contact::_removeChild(int index) refresh(); } -void Models::Contact::appendChild(Models::Item* child) +void Models::Contact::_appendChild(Models::Item* child) { - Item::appendChild(child); + Item::_appendChild(child); connect(child, &Item::childChanged, this, &Contact::refresh); refresh(); } @@ -334,17 +334,20 @@ void Models::Contact::getMessages(Models::Contact::Messages& container) const void Models::Contact::toOfflineState() { - emit childIsAboutToBeRemoved(this, 0, childItems.size()); - for (std::deque::size_type i = 0; i < childItems.size(); ++i) { - Item* item = childItems[i]; - disconnect(item, &Item::childChanged, this, &Contact::refresh); - Item::_removeChild(i); - item->deleteLater(); + std::deque::size_type size = childItems.size(); + if (size > 0) { + emit childIsAboutToBeRemoved(this, 0, size - 1); + for (std::deque::size_type i = 0; i < size; ++i) { + Item* item = childItems[0]; + disconnect(item, &Item::childChanged, this, &Contact::refresh); + Item::_removeChild(0); + item->deleteLater(); + } + childItems.clear(); + presences.clear(); + emit childRemoved(); + refresh(); } - childItems.clear(); - presences.clear(); - emit childRemoved(); - refresh(); } QString Models::Contact::getDisplayedName() const diff --git a/ui/models/contact.h b/ui/models/contact.h index 39418ae..c8c99b5 100644 --- a/ui/models/contact.h +++ b/ui/models/contact.h @@ -57,7 +57,6 @@ public: void addPresence(const QString& name, const QMap& data); void removePresence(const QString& name); - void appendChild(Models::Item * child) override; QString getContactName() const; QString getStatus() const; @@ -72,6 +71,7 @@ public: protected: void _removeChild(int index) override; + void _appendChild(Models::Item * child) override; bool columnInvolvedInDisplay(int col) override; const Account* getParentAccount() const override; diff --git a/ui/models/group.cpp b/ui/models/group.cpp index 5cf411b..013ff13 100644 --- a/ui/models/group.cpp +++ b/ui/models/group.cpp @@ -30,9 +30,9 @@ Models::Group::~Group() { } -void Models::Group::appendChild(Models::Item* child) +void Models::Group::_appendChild(Models::Item* child) { - Item::appendChild(child); + Item::_appendChild(child); connect(child, &Item::childChanged, this, &Group::refresh); changed(1); refresh(); @@ -83,9 +83,14 @@ void Models::Group::refresh() { unsigned int newAmount(0); - for (std::deque::const_iterator itr = childItems.begin(), end = childItems.end(); itr != end; ++itr) { - Models::Contact* cnt = static_cast(*itr); - newAmount += cnt->getMessagesCount(); + for (Models::Item* item : childItems) { + if (item->type == reference) { + item = static_cast(item)->dereference(); + } + if (item->type == contact) { + Models::Contact* cnt = static_cast(item); + newAmount += cnt->getMessagesCount(); + } } setUnreadMessages(newAmount); @@ -95,10 +100,15 @@ unsigned int Models::Group::getOnlineContacts() const { unsigned int amount(0); - for (std::deque::const_iterator itr = childItems.begin(), end = childItems.end(); itr != end; ++itr) { - Models::Contact* cnt = static_cast(*itr); - if (cnt->getAvailability() != Shared::Availability::offline) { - ++amount; + for (Models::Item* item : childItems) { + if (item->type == reference) { + item = static_cast(item)->dereference(); + } + if (item->type == contact) { + Models::Contact* cnt = static_cast(item); + if (cnt->getAvailability() != Shared::Availability::offline) { + ++amount; + } } } diff --git a/ui/models/group.h b/ui/models/group.h index 7343b63..5a0baaf 100644 --- a/ui/models/group.h +++ b/ui/models/group.h @@ -32,7 +32,6 @@ public: Group(const QMap &data, Item *parentItem = 0); ~Group(); - void appendChild(Models::Item* child) override; int columnCount() const override; QVariant data(int column) const override; @@ -41,6 +40,7 @@ public: protected: void _removeChild(int index) override; + void _appendChild(Models::Item* child) override; void setUnreadMessages(unsigned int amount); private slots: diff --git a/ui/models/item.cpp b/ui/models/item.cpp index 566c26a..c5d6e2a 100644 --- a/ui/models/item.cpp +++ b/ui/models/item.cpp @@ -29,7 +29,9 @@ Models::Item::Item(Type p_type, const QMap &p_data, Item *p_p name(""), childItems(), parent(p_parent), - references() + references(), + destroyingByParent(false), + destroyingByOriginal(false) { QMap::const_iterator itr = p_data.find("name"); if (itr != p_data.end()) { @@ -48,15 +50,24 @@ Models::Item::Item(const Models::Item& other): Models::Item::~Item() { - for (Reference* ref : references) { - Item* parent = ref->parentItem(); + if (!destroyingByParent) { + Item* parent = parentItem(); if (parent != nullptr) { - parent->removeChild(ref->row()); + if (parent->type == reference) { + parent->Item::removeChild(row()); + } else { + parent->removeChild(row()); + } } + } + + for (Reference* ref : references) { + ref->destroyingByOriginal = true; delete ref; } for (Item* child : childItems) { + child->destroyingByParent = true; delete child; } } @@ -70,6 +81,11 @@ void Models::Item::setName(const QString& p_name) } void Models::Item::appendChild(Models::Item* child) +{ + _appendChild(child); +} + +void Models::Item::_appendChild(Models::Item* child) { bool moving = false; int newRow = 0; diff --git a/ui/models/item.h b/ui/models/item.h index 76f1780..4f3e29a 100644 --- a/ui/models/item.h +++ b/ui/models/item.h @@ -88,27 +88,26 @@ class Item : public QObject{ int getContact(const QString& jid) const; std::set::size_type referencesCount() const; - void addReference(Reference* ref); - void removeReference(Reference* ref); - protected: virtual void changed(int col); virtual void _removeChild(int index); + virtual void _appendChild(Item *child); virtual bool columnInvolvedInDisplay(int col); virtual const Account* getParentAccount() const; + void addReference(Reference* ref); + void removeReference(Reference* ref); protected slots: void onChildChanged(Models::Item* item, int row, int col); + virtual void toOfflineState(); protected: QString name; std::deque childItems; Item* parent; std::set references; - - protected slots: - virtual void toOfflineState(); - + bool destroyingByParent; + bool destroyingByOriginal; }; } diff --git a/ui/models/reference.cpp b/ui/models/reference.cpp index 26d6b94..cb8efad 100644 --- a/ui/models/reference.cpp +++ b/ui/models/reference.cpp @@ -29,7 +29,7 @@ Models::Reference::Reference(Models::Item* original, Models::Item* parent): cx(-1), c(false) { - connect(original, &Item::childChanged, this, &Reference::onChildChanged); + connect(original, &Item::childChanged, this, &Reference::onChildChanged, Qt::QueuedConnection); connect(original, &Item::childIsAboutToBeInserted, this, &Reference::onChildIsAboutToBeInserted); connect(original, &Item::childInserted, this, &Reference::onChildInserted); connect(original, &Item::childIsAboutToBeRemoved, this, &Reference::onChildIsAboutToBeRemoved); @@ -38,10 +38,20 @@ Models::Reference::Reference(Models::Item* original, Models::Item* parent): connect(original, &Item::childMoved, this, &Reference::onChildMoved); original->addReference(this); + + for (int i = 0; i < original->childCount(); i++) { + Reference* ref = new Reference(original->child(i)); + Item::appendChild(ref); + } } Models::Reference::~Reference() { + if (!destroyingByOriginal) { + original->removeReference(this); + } + + disconnect(original, &Item::childChanged, this, &Reference::onChildChanged); disconnect(original, &Item::childIsAboutToBeInserted, this, &Reference::onChildIsAboutToBeInserted); disconnect(original, &Item::childInserted, this, &Reference::onChildInserted); disconnect(original, &Item::childIsAboutToBeRemoved, this, &Reference::onChildIsAboutToBeRemoved); @@ -120,13 +130,13 @@ void Models::Reference::onChildInserted() void Models::Reference::onChildIsAboutToBeRemoved(Models::Item* parent, int first, int last) { if (parent == original) { + emit childIsAboutToBeRemoved(this, first, last); for (int i = first; i <= last; ++i) { - Reference* ref = static_cast(childItems[i]); - Item* orig = original->child(i); - orig->removeReference(ref); - Item::removeChild(i); + Reference* ref = static_cast(childItems[first]); + Item::_removeChild(first); delete ref; } + childRemoved(); } } diff --git a/ui/models/roster.cpp b/ui/models/roster.cpp index 91f1f74..75555ae 100644 --- a/ui/models/roster.cpp +++ b/ui/models/roster.cpp @@ -518,7 +518,6 @@ void Models::Roster::removeGroup(const QString& account, const QString& name) if (cont->referencesCount() == 1) { toInsert.push_back(ref); } else { - cont->removeReference(ref); delete ref; } } @@ -626,7 +625,6 @@ void Models::Roster::removeContact(const QString& account, const QString& jid, c qDebug() << "An attempt to remove last instance of contact" << jid << "from the group" << group << ", contact will be moved to ungrouped contacts of" << account; acc->appendChild(ref); } else { - cont->removeReference(ref); delete ref; }