Warning, file /network/ruqola/src/core/model/accountschannelsmodel.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2020 Olivier de Gaalon <olivier.jg@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "accountschannelsmodel.h" 0008 0009 #include "accountmanager.h" 0010 #include "rocketchataccount.h" 0011 #include "rocketchataccountfilterproxymodel.h" 0012 #include "rocketchataccountmodel.h" 0013 #include "ruqola.h" 0014 0015 AccountsChannelsModel::AccountsChannelsModel(QObject *parent) 0016 : QAbstractItemModel(parent) 0017 { 0018 auto accountManager = Ruqola::self()->accountManager(); 0019 const auto src = accountManager->rocketChatAccountModel(); 0020 const auto acctsProxy = accountManager->rocketChatAccountProxyModel(); 0021 0022 auto roomsModel = [src, acctsProxy](int i) { 0023 const auto acctIndex = acctsProxy->mapToSource(acctsProxy->index(i, 0)).row(); 0024 return src->account(acctIndex)->roomModel(); 0025 }; 0026 0027 auto mapRoomsModel = [roomsModel, acctsProxy, this](int roomsModelIndex) { 0028 auto rooms = roomsModel(roomsModelIndex); 0029 mapModelToIndex(rooms, [roomsModel, acctsProxy, rooms, this] { 0030 for (int i = 0, count = acctsProxy->rowCount(); i < count; ++i) { 0031 if (roomsModel(i) == rooms) { 0032 return index(i, 0); 0033 } 0034 } 0035 return QModelIndex(); 0036 }); 0037 }; 0038 0039 connect(acctsProxy, &QAbstractItemModel::rowsInserted, this, [mapRoomsModel](const QModelIndex &, int first, int last) { 0040 for (int i = first; i <= last; ++i) { 0041 mapRoomsModel(i); 0042 } 0043 }); 0044 0045 connect(acctsProxy, &QAbstractItemModel::rowsAboutToBeRemoved, this, [roomsModel, this](const QModelIndex &, int first, int last) { 0046 for (int i = first; i <= last; ++i) { 0047 unproxyModel(roomsModel(i)); 0048 } 0049 }); 0050 0051 connect(acctsProxy, &QAbstractItemModel::modelReset, this, [mapRoomsModel, acctsProxy, this]() { 0052 while (!mProxied.isEmpty()) { 0053 unproxyModel(mProxied.begin()->model); 0054 } 0055 for (int i = 0, count = acctsProxy->rowCount(); i < count; ++i) { 0056 mapRoomsModel(i); 0057 } 0058 }); 0059 0060 mapModelToIndex(acctsProxy, [] { 0061 return QModelIndex(); 0062 }); 0063 for (int i = 0, count = acctsProxy->rowCount(); i < count; ++i) { 0064 mapRoomsModel(i); 0065 } 0066 } 0067 0068 AccountsChannelsModel::~AccountsChannelsModel() = default; 0069 0070 QModelIndex AccountsChannelsModel::index(int row, int column, const QModelIndex &parent) const 0071 { 0072 if (auto model = rootModel(parent)) { 0073 return createIndex(row, column, model); 0074 } 0075 return {}; 0076 } 0077 0078 QModelIndex AccountsChannelsModel::parent(const QModelIndex &child) const 0079 { 0080 if (!child.isValid()) { 0081 return {}; 0082 } 0083 0084 if (auto model = static_cast<QAbstractItemModel *>(child.internalPointer())) { 0085 return modelRoot(model); 0086 } 0087 0088 return {}; 0089 } 0090 0091 int AccountsChannelsModel::rowCount(const QModelIndex &parent) const 0092 { 0093 if (auto model = rootModel(parent)) { 0094 return model->rowCount(); 0095 } 0096 return 0; 0097 } 0098 0099 int AccountsChannelsModel::columnCount(const QModelIndex &) const 0100 { 0101 return 1; 0102 } 0103 0104 QVariant AccountsChannelsModel::data(const QModelIndex &index, int role) const 0105 { 0106 if (!index.isValid()) { 0107 return {}; 0108 } 0109 0110 const auto model = static_cast<QAbstractItemModel *>(index.internalPointer()); 0111 if (!model) { 0112 return {}; 0113 } 0114 0115 return model->index(index.row(), index.column()).data(role); 0116 } 0117 0118 QModelIndex AccountsChannelsModel::modelRoot(QAbstractItemModel *model) const 0119 { 0120 const auto find = [model](const ProxyIndex &i) { 0121 return i.model == model; 0122 }; 0123 const auto it = std::find_if(mProxied.begin(), mProxied.end(), find); 0124 return (it == mProxied.end()) ? QModelIndex() : it->root(); 0125 } 0126 0127 QAbstractItemModel *AccountsChannelsModel::rootModel(const QModelIndex &root) const 0128 { 0129 const auto find = [&root](const ProxyIndex &i) { 0130 return i.root() == root; 0131 }; 0132 const auto it = std::find_if(mProxied.begin(), mProxied.end(), find); 0133 return (it == mProxied.end()) ? nullptr : it->model; 0134 } 0135 0136 void AccountsChannelsModel::mapModelToIndex(QAbstractItemModel *model, const std::function<QModelIndex()> &root) 0137 { 0138 connect(model, &QAbstractItemModel::rowsAboutToBeInserted, this, [this, model](const QModelIndex &parent, int first, int last) { 0139 Q_ASSERT(!parent.isValid()); 0140 beginInsertRows(modelRoot(model), first, last); 0141 }); 0142 connect(model, &QAbstractItemModel::rowsInserted, this, &AccountsChannelsModel::endInsertRows); 0143 0144 connect(model, &QAbstractItemModel::rowsAboutToBeRemoved, this, [this, model](const QModelIndex &parent, int first, int last) { 0145 Q_ASSERT(!parent.isValid()); 0146 beginRemoveRows(modelRoot(model), first, last); 0147 }); 0148 connect(model, &QAbstractItemModel::rowsRemoved, this, &AccountsChannelsModel::endRemoveRows); 0149 0150 connect(model, &QAbstractItemModel::rowsAboutToBeMoved, this, [this, model](const QModelIndex &src, int sf, int sl, const QModelIndex &dst, int df) { 0151 Q_ASSERT(!src.isValid() && !dst.isValid()); 0152 const auto idx = modelRoot(model); 0153 beginMoveRows(idx, sf, sl, idx, df); 0154 }); 0155 connect(model, &QAbstractItemModel::rowsMoved, this, &AccountsChannelsModel::endMoveRows); 0156 0157 connect(model, &QAbstractItemModel::modelAboutToBeReset, this, &AccountsChannelsModel::beginResetModel); 0158 connect(model, &QAbstractItemModel::modelReset, this, &AccountsChannelsModel::endResetModel); 0159 0160 connect(model, &QAbstractItemModel::layoutAboutToBeChanged, this, &AccountsChannelsModel::layoutAboutToBeChanged); 0161 connect(model, &QAbstractItemModel::layoutChanged, this, &AccountsChannelsModel::layoutChanged); 0162 0163 connect(model, &QAbstractItemModel::dataChanged, this, [this, model](const QModelIndex &tl, const QModelIndex &br) { 0164 const auto parent = modelRoot(model); 0165 Q_EMIT dataChanged(index(tl.row(), tl.column(), parent), index(br.row(), br.column(), parent)); 0166 }); 0167 0168 mProxied.append({model, root}); 0169 } 0170 0171 void AccountsChannelsModel::unproxyModel(QAbstractItemModel *model) 0172 { 0173 const auto find = [model](const ProxyIndex &i) { 0174 return i.model == model; 0175 }; 0176 const auto it = std::find_if(mProxied.begin(), mProxied.end(), find); 0177 if (it != mProxied.end()) { 0178 model->disconnect(this); 0179 mProxied.erase(it); 0180 } 0181 }