Skip to content
Snippets Groups Projects
CommunitiesModel.cpp 8.64 KiB
Newer Older
  • Learn to ignore specific revisions
  • // SPDX-FileCopyrightText: 2021 Nheko Contributors
    //
    // SPDX-License-Identifier: GPL-3.0-or-later
    
    #include "CommunitiesModel.h"
    
    #include <set>
    
    #include "Cache.h"
    #include "UserSettingsPage.h"
    
    CommunitiesModel::CommunitiesModel(QObject *parent)
      : QAbstractListModel(parent)
    {}
    
    QHash<int, QByteArray>
    CommunitiesModel::roleNames() const
    {
    
        return {
          {AvatarUrl, "avatarUrl"},
          {DisplayName, "displayName"},
          {Tooltip, "tooltip"},
          {ChildrenHidden, "childrenHidden"},
          {Hidden, "hidden"},
          {Id, "id"},
        };
    
    }
    
    QVariant
    CommunitiesModel::data(const QModelIndex &index, int role) const
    {
    
        if (index.row() == 0) {
            switch (role) {
            case CommunitiesModel::Roles::AvatarUrl:
    
                return QString(":/icons/icons/ui/world.svg");
    
            case CommunitiesModel::Roles::DisplayName:
                return tr("All rooms");
            case CommunitiesModel::Roles::Tooltip:
                return tr("Shows all rooms without filtering.");
            case CommunitiesModel::Roles::ChildrenHidden:
                return false;
            case CommunitiesModel::Roles::Hidden:
                return false;
            case CommunitiesModel::Roles::Id:
                return "";
            }
    
        } else if (index.row() == 1) {
            switch (role) {
            case CommunitiesModel::Roles::AvatarUrl:
                return QString(":/icons/icons/ui/people.svg");
            case CommunitiesModel::Roles::DisplayName:
                return tr("Direct Chats");
            case CommunitiesModel::Roles::Tooltip:
                return tr("Show direct chats.");
            case CommunitiesModel::Roles::ChildrenHidden:
                return false;
            case CommunitiesModel::Roles::Hidden:
                return hiddentTagIds_.contains("dm");
            case CommunitiesModel::Roles::Id:
                return "dm";
            }
        } else if (index.row() - 2 < spaceOrder_.size()) {
            auto id = spaceOrder_.at(index.row() - 2);
    
            switch (role) {
            case CommunitiesModel::Roles::AvatarUrl:
                return QString::fromStdString(spaces_.at(id).avatar_url);
            case CommunitiesModel::Roles::DisplayName:
            case CommunitiesModel::Roles::Tooltip:
                return QString::fromStdString(spaces_.at(id).name);
            case CommunitiesModel::Roles::ChildrenHidden:
                return true;
            case CommunitiesModel::Roles::Hidden:
                return hiddentTagIds_.contains("space:" + id);
            case CommunitiesModel::Roles::Id:
                return "space:" + id;
            }
    
        } else if (index.row() - 2 < tags_.size() + spaceOrder_.size()) {
            auto tag = tags_.at(index.row() - 2 - spaceOrder_.size());
    
            if (tag == "m.favourite") {
                switch (role) {
                case CommunitiesModel::Roles::AvatarUrl:
    
                    return QString(":/icons/icons/ui/star.svg");
    
                case CommunitiesModel::Roles::DisplayName:
                    return tr("Favourites");
                case CommunitiesModel::Roles::Tooltip:
                    return tr("Rooms you have favourited.");
                }
            } else if (tag == "m.lowpriority") {
                switch (role) {
                case CommunitiesModel::Roles::AvatarUrl:
    
                    return QString(":/icons/icons/ui/lowprio.svg");
    
                case CommunitiesModel::Roles::DisplayName:
                    return tr("Low Priority");
                case CommunitiesModel::Roles::Tooltip:
                    return tr("Rooms with low priority.");
                }
            } else if (tag == "m.server_notice") {
                switch (role) {
                case CommunitiesModel::Roles::AvatarUrl:
    
                    return QString(":/icons/icons/ui/tag.svg");
    
                case CommunitiesModel::Roles::DisplayName:
                    return tr("Server Notices");
                case CommunitiesModel::Roles::Tooltip:
                    return tr("Messages from your server or administrator.");
                }
            } else {
                switch (role) {
                case CommunitiesModel::Roles::AvatarUrl:
    
                    return QString(":/icons/icons/ui/tag.svg");
    
                case CommunitiesModel::Roles::DisplayName:
                case CommunitiesModel::Roles::Tooltip:
                    return tag.mid(2);
                }
            }
    
            switch (role) {
            case CommunitiesModel::Roles::Hidden:
                return hiddentTagIds_.contains("tag:" + tag);
            case CommunitiesModel::Roles::ChildrenHidden:
                return true;
            case CommunitiesModel::Roles::Id:
                return "tag:" + tag;
    
        }
        return QVariant();
    
    }
    
    void
    CommunitiesModel::initializeSidebar()
    {
    
        beginResetModel();
        tags_.clear();
        spaceOrder_.clear();
        spaces_.clear();
    
        std::set<std::string> ts;
        std::vector<RoomInfo> tempSpaces;
        auto infos = cache::roomInfo();
        for (auto it = infos.begin(); it != infos.end(); it++) {
            if (it.value().is_space) {
                spaceOrder_.push_back(it.key());
                spaces_[it.key()] = it.value();
            } else {
                for (const auto &t : it.value().tags) {
                    if (t.find("u.") == 0 || t.find("m." == 0)) {
                        ts.insert(t);
    
        for (const auto &t : ts)
            tags_.push_back(QString::fromStdString(t));
    
        hiddentTagIds_ = UserSettings::instance()->hiddenTags();
        endResetModel();
    
        emit tagsChanged();
        emit hiddenTagsChanged();
    
    }
    
    void
    CommunitiesModel::clear()
    {
    
        beginResetModel();
        tags_.clear();
        endResetModel();
        resetCurrentTagId();
    
        emit tagsChanged();
    
    CommunitiesModel::sync(const mtx::responses::Sync &sync_)
    
        bool tagsUpdated = false;
    
    
        for (const auto &[roomid, room] : sync_.rooms.join) {
    
            (void)roomid;
            for (const auto &e : room.account_data.events)
                if (std::holds_alternative<
                      mtx::events::AccountDataEvent<mtx::events::account_data::Tags>>(e)) {
                    tagsUpdated = true;
                }
            for (const auto &e : room.state.events)
                if (std::holds_alternative<mtx::events::StateEvent<mtx::events::state::space::Child>>(
                      e) ||
                    std::holds_alternative<mtx::events::StateEvent<mtx::events::state::space::Parent>>(
                      e)) {
                    tagsUpdated = true;
                }
            for (const auto &e : room.timeline.events)
                if (std::holds_alternative<mtx::events::StateEvent<mtx::events::state::space::Child>>(
                      e) ||
                    std::holds_alternative<mtx::events::StateEvent<mtx::events::state::space::Parent>>(
                      e)) {
                    tagsUpdated = true;
                }
        }
    
        for (const auto &[roomid, room] : sync_.rooms.leave) {
    
            (void)room;
            if (spaceOrder_.contains(QString::fromStdString(roomid)))
                tagsUpdated = true;
        }
    
        for (const auto &e : sync_.account_data.events) {
            if (std::holds_alternative<
                  mtx::events::AccountDataEvent<mtx::events::account_data::Direct>>(e)) {
                tagsUpdated = true;
                break;
            }
        }
    
    
        if (tagsUpdated)
            initializeSidebar();
    
    }
    
    void
    CommunitiesModel::setCurrentTagId(QString tagId)
    {
    
        if (tagId.startsWith("tag:")) {
            auto tag = tagId.mid(4);
            for (const auto &t : tags_) {
                if (t == tag) {
                    this->currentTagId_ = tagId;
                    emit currentTagIdChanged(currentTagId_);
                    return;
                }
            }
        } else if (tagId.startsWith("space:")) {
            auto tag = tagId.mid(6);
            for (const auto &t : spaceOrder_) {
                if (t == tag) {
                    this->currentTagId_ = tagId;
                    emit currentTagIdChanged(currentTagId_);
                    return;
                }
    
        } else if (tagId == "dm") {
            this->currentTagId_ = tagId;
            emit currentTagIdChanged(currentTagId_);
            return;
    
        this->currentTagId_ = "";
        emit currentTagIdChanged(currentTagId_);
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    
    void
    CommunitiesModel::toggleTagId(QString tagId)
    {
    
        if (hiddentTagIds_.contains(tagId)) {
            hiddentTagIds_.removeOne(tagId);
            UserSettings::instance()->setHiddenTags(hiddentTagIds_);
        } else {
            hiddentTagIds_.push_back(tagId);
            UserSettings::instance()->setHiddenTags(hiddentTagIds_);
        }
    
        if (tagId.startsWith("tag:")) {
            auto idx = tags_.indexOf(tagId.mid(4));
            if (idx != -1)
                emit dataChanged(
                  index(idx + 1 + spaceOrder_.size()), index(idx + 1 + spaceOrder_.size()), {Hidden});
        } else if (tagId.startsWith("space:")) {
            auto idx = spaceOrder_.indexOf(tagId.mid(6));
            if (idx != -1)
                emit dataChanged(index(idx + 1), index(idx + 1), {Hidden});
    
        } else if (tagId == "dm") {
            emit dataChanged(index(1), index(1), {Hidden});
    
        }
    
        emit hiddenTagsChanged();
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    }