Lower the complexity of the group filtering algorithm (#380)
The old algorithm during filtering will check every room if it's part of the group. O(N*G) The room ids for a group are now stored in a map for faster lookup so the search can be completed in a single pass. O(N)
This commit is contained in:
parent
9d718fccf4
commit
54c7eb374a
|
@ -514,9 +514,9 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
|||
current_community_ = groupId;
|
||||
|
||||
if (groupId == "world")
|
||||
room_list_->setFilterRooms(false);
|
||||
room_list_->removeFilter();
|
||||
else
|
||||
room_list_->setRoomFilter(communitiesList_->roomList(groupId));
|
||||
room_list_->applyFilter(communitiesList_->roomList(groupId));
|
||||
});
|
||||
|
||||
connect(¬ificationsManager,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "CommunitiesList.h"
|
||||
#include "Cache.h"
|
||||
#include "CommunitiesList.h"
|
||||
#include "Logging.h"
|
||||
#include "MatrixClient.h"
|
||||
|
||||
|
@ -83,7 +83,7 @@ CommunitiesList::addCommunity(const std::string &group_id)
|
|||
connect(this,
|
||||
&CommunitiesList::groupRoomsRetrieved,
|
||||
this,
|
||||
[this](const QString &id, const std::vector<QString> &rooms) {
|
||||
[this](const QString &id, const std::map<QString, bool> &rooms) {
|
||||
if (communities_.find(id) == communities_.end())
|
||||
return;
|
||||
|
||||
|
@ -109,9 +109,9 @@ CommunitiesList::addCommunity(const std::string &group_id)
|
|||
return;
|
||||
}
|
||||
|
||||
std::vector<QString> room_ids;
|
||||
std::map<QString, bool> room_ids;
|
||||
for (const auto &room : res.at("chunk"))
|
||||
room_ids.push_back(QString::fromStdString(room.at("room_id")));
|
||||
room_ids.emplace(QString::fromStdString(room.at("room_id")), true);
|
||||
|
||||
emit groupRoomsRetrieved(id, room_ids);
|
||||
});
|
||||
|
@ -185,7 +185,7 @@ CommunitiesList::fetchCommunityAvatar(const QString &id, const QString &avatarUr
|
|||
});
|
||||
}
|
||||
|
||||
std::vector<QString>
|
||||
std::map<QString, bool>
|
||||
CommunitiesList::roomList(const QString &id) const
|
||||
{
|
||||
if (communityExists(id))
|
||||
|
|
|
@ -18,13 +18,13 @@ public:
|
|||
|
||||
void addCommunity(const std::string &id);
|
||||
void removeCommunity(const QString &id) { communities_.erase(id); };
|
||||
std::vector<QString> roomList(const QString &id) const;
|
||||
std::map<QString, bool> roomList(const QString &id) const;
|
||||
|
||||
signals:
|
||||
void communityChanged(const QString &id);
|
||||
void avatarRetrieved(const QString &id, const QPixmap &img);
|
||||
void groupProfileRetrieved(const QString &group_id, const mtx::responses::GroupProfile &);
|
||||
void groupRoomsRetrieved(const QString &group_id, const std::vector<QString> &res);
|
||||
void groupRoomsRetrieved(const QString &group_id, const std::map<QString, bool> &res);
|
||||
|
||||
public slots:
|
||||
void updateCommunityAvatar(const QString &id, const QPixmap &img);
|
||||
|
|
|
@ -32,8 +32,8 @@ public:
|
|||
bool isPressed() const { return isPressed_; }
|
||||
void setAvatar(const QImage &img);
|
||||
|
||||
void setRooms(std::vector<QString> room_ids) { room_ids_ = std::move(room_ids); }
|
||||
std::vector<QString> rooms() const { return room_ids_; }
|
||||
void setRooms(std::map<QString, bool> room_ids) { room_ids_ = std::move(room_ids); }
|
||||
std::map<QString, bool> rooms() const { return room_ids_; }
|
||||
|
||||
QColor highlightedBackgroundColor() const { return highlightedBackgroundColor_; }
|
||||
QColor hoverBackgroundColor() const { return hoverBackgroundColor_; }
|
||||
|
@ -69,7 +69,7 @@ private:
|
|||
|
||||
QString resolveName() const;
|
||||
|
||||
std::vector<QString> room_ids_;
|
||||
std::map<QString, bool> room_ids_;
|
||||
|
||||
QString name_;
|
||||
QString groupId_;
|
||||
|
|
|
@ -56,6 +56,8 @@ RoomList::RoomList(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
|||
scrollArea_->setWidget(scrollAreaContents_);
|
||||
topLayout_->addWidget(scrollArea_);
|
||||
|
||||
qRegisterMetaType<std::map<QString, bool>>();
|
||||
|
||||
connect(this, &RoomList::updateRoomAvatarCb, this, &RoomList::updateRoomAvatar);
|
||||
}
|
||||
|
||||
|
@ -340,10 +342,21 @@ RoomList::closeJoinRoomDialog(bool isJoining, QString roomAlias)
|
|||
}
|
||||
|
||||
void
|
||||
RoomList::setFilterRooms(bool isFilteringEnabled)
|
||||
RoomList::removeFilter()
|
||||
{
|
||||
for (int i = 0; i < contentsLayout_->count(); i++) {
|
||||
// If roomFilter_ contains the room for the current RoomInfoListItem,
|
||||
auto widget =
|
||||
qobject_cast<RoomInfoListItem *>(contentsLayout_->itemAt(i)->widget());
|
||||
if (widget)
|
||||
widget->show();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RoomList::applyFilter(const std::map<QString, bool> &filter)
|
||||
{
|
||||
for (int i = 0; i < contentsLayout_->count(); i++) {
|
||||
// If filter contains the room for the current RoomInfoListItem,
|
||||
// show the list item, otherwise hide it
|
||||
auto listitem =
|
||||
qobject_cast<RoomInfoListItem *>(contentsLayout_->itemAt(i)->widget());
|
||||
|
@ -351,29 +364,30 @@ RoomList::setFilterRooms(bool isFilteringEnabled)
|
|||
if (!listitem)
|
||||
continue;
|
||||
|
||||
if (!isFilteringEnabled || filterItemExists(listitem->roomId()))
|
||||
if (filter.find(listitem->roomId()) != filter.end())
|
||||
listitem->show();
|
||||
else
|
||||
listitem->hide();
|
||||
}
|
||||
|
||||
if (isFilteringEnabled && !filterItemExists(selectedRoom_)) {
|
||||
RoomInfoListItem *firstVisibleRoom = nullptr;
|
||||
// If the already selected room is part of the group, make sure it's visible.
|
||||
if (!selectedRoom_.isEmpty() && (filter.find(selectedRoom_) != filter.end()))
|
||||
return;
|
||||
|
||||
selectFirstVisibleRoom();
|
||||
}
|
||||
|
||||
void
|
||||
RoomList::selectFirstVisibleRoom()
|
||||
{
|
||||
for (int i = 0; i < contentsLayout_->count(); i++) {
|
||||
QWidget *item = contentsLayout_->itemAt(i)->widget();
|
||||
auto item = qobject_cast<RoomInfoListItem *>(contentsLayout_->itemAt(i)->widget());
|
||||
|
||||
if (item != nullptr && item->isVisible()) {
|
||||
firstVisibleRoom = qobject_cast<RoomInfoListItem *>(item);
|
||||
if (item && item->isVisible()) {
|
||||
highlightSelectedRoom(item->roomId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstVisibleRoom != nullptr)
|
||||
highlightSelectedRoom(firstVisibleRoom->roomId());
|
||||
} else {
|
||||
scrollArea_->ensureWidgetVisible(rooms_[selectedRoom_].data());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -404,13 +418,6 @@ RoomList::updateRoom(const QString &room_id, const RoomInfo &info)
|
|||
room->update();
|
||||
}
|
||||
|
||||
void
|
||||
RoomList::setRoomFilter(std::vector<QString> room_ids)
|
||||
{
|
||||
roomFilter_ = room_ids;
|
||||
setFilterRooms(true);
|
||||
}
|
||||
|
||||
void
|
||||
RoomList::addInvitedRoom(const QString &room_id, const RoomInfo &info)
|
||||
{
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QPushButton>
|
||||
#include <QScrollArea>
|
||||
#include <QSharedPointer>
|
||||
|
@ -33,6 +34,9 @@ class UserSettings;
|
|||
struct DescInfo;
|
||||
struct RoomInfo;
|
||||
|
||||
using RoomIds = std::map<QString, bool>;
|
||||
Q_DECLARE_METATYPE(RoomIds)
|
||||
|
||||
class RoomList : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -49,8 +53,10 @@ public:
|
|||
void addRoom(const QString &room_id, const RoomInfo &info);
|
||||
void addInvitedRoom(const QString &room_id, const RoomInfo &info);
|
||||
void removeRoom(const QString &room_id, bool reset);
|
||||
void setFilterRooms(bool filterRooms);
|
||||
void setRoomFilter(std::vector<QString> room_ids);
|
||||
//! Hide rooms that are not present in the given filter.
|
||||
void applyFilter(const std::map<QString, bool> &rooms);
|
||||
//! Show all the available rooms.
|
||||
void removeFilter();
|
||||
void updateRoom(const QString &room_id, const RoomInfo &info);
|
||||
void cleanupInvites(const std::map<QString, bool> &invites);
|
||||
|
||||
|
@ -82,10 +88,8 @@ private:
|
|||
std::pair<QString, QSharedPointer<RoomInfoListItem>> firstRoom() const;
|
||||
void calculateUnreadMessageCount();
|
||||
bool roomExists(const QString &room_id) { return rooms_.find(room_id) != rooms_.end(); }
|
||||
bool filterItemExists(const QString &id)
|
||||
{
|
||||
return std::find(roomFilter_.begin(), roomFilter_.end(), id) != roomFilter_.end();
|
||||
}
|
||||
//! Select the first visible room in the room list.
|
||||
void selectFirstVisibleRoom();
|
||||
|
||||
QVBoxLayout *topLayout_;
|
||||
QVBoxLayout *contentsLayout_;
|
||||
|
@ -99,9 +103,6 @@ private:
|
|||
std::map<QString, QSharedPointer<RoomInfoListItem>> rooms_;
|
||||
QString selectedRoom_;
|
||||
|
||||
//! Which rooms to include in the room list.
|
||||
std::vector<QString> roomFilter_;
|
||||
|
||||
QSharedPointer<UserSettings> userSettings_;
|
||||
|
||||
bool isSortPending_ = false;
|
||||
|
|
Loading…
Reference in New Issue