File indexing completed on 2023-12-03 08:28:35
0001 /* 0002 * Model of all accounts with inbuilt grouping and filtering 0003 * 0004 * Copyright (C) 2013 David Edmundson <kde@davidedmundson.co.uk> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Lesser General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2.1 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Lesser General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Lesser General Public 0017 * License along with this library; if not, write to the Free Software 0018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 0019 */ 0020 0021 #include "contacts-model.h" 0022 0023 #include "contacts-list-model.h" 0024 #include "accounts-tree-proxy-model.h" 0025 #include "groups-tree-proxy-model.h" 0026 #include "text-channel-watcher-proxy-model.h" 0027 0028 #include "core.h" 0029 0030 #include <TelepathyQt/ClientRegistrar> 0031 0032 #ifdef HAVE_KPEOPLE 0033 #include <KPeople/PersonsModel> 0034 #include "kpeopletranslationproxy.h" 0035 #endif 0036 0037 #include "debug.h" 0038 0039 0040 namespace KTp 0041 { 0042 class ContactsModel::Private 0043 { 0044 public: 0045 GroupMode groupMode; 0046 bool trackUnread; 0047 QPointer<KTp::AbstractGroupingProxyModel> proxy; 0048 QAbstractItemModel *source; 0049 Tp::AccountManagerPtr accountManager; 0050 Tp::ClientRegistrarPtr clientRegistrar; 0051 Tp::SharedPtr<KTp::TextChannelWatcherProxyModel> channelWatcherProxy; 0052 }; 0053 } 0054 0055 0056 KTp::ContactsModel::ContactsModel(QObject *parent) 0057 : KTp::ContactsFilterModel(parent), 0058 d(new Private) 0059 { 0060 d->groupMode = NoGrouping; 0061 d->trackUnread = false; 0062 if (KTp::kpeopleEnabled()) { 0063 #ifdef HAVE_KPEOPLE 0064 qCDebug(KTP_MODELS) << "Built with kpeople support, using kpeople model"; 0065 KPeople::PersonsModel *personsModel = new KPeople::PersonsModel(this); 0066 0067 connect(personsModel, SIGNAL(modelInitialized(bool)), 0068 this, SIGNAL(modelInitialized(bool))); 0069 0070 d->source = new KPeopleTranslationProxy(this); 0071 qobject_cast<KPeopleTranslationProxy*>(d->source)->setSourceModel(personsModel); 0072 #endif 0073 } 0074 else 0075 { 0076 qCDebug(KTP_MODELS) << "KPeople support not built-in, using normal model"; 0077 d->source = new KTp::ContactsListModel(this); 0078 connect(d->source, SIGNAL(modelInitialized(bool)), 0079 this, SIGNAL(modelInitialized(bool))); 0080 } 0081 0082 } 0083 0084 KTp::ContactsModel::~ContactsModel() 0085 { 0086 delete d; 0087 } 0088 0089 0090 void KTp::ContactsModel::setAccountManager(const Tp::AccountManagerPtr &accountManager) 0091 { 0092 d->accountManager = accountManager; 0093 0094 updateGroupProxyModels(); 0095 0096 //set the account manager after we've reloaded the groups so that we don't send a list to the view, only to replace it with a grouped tree 0097 if (qobject_cast<ContactsListModel*>(d->source)) { 0098 qobject_cast<ContactsListModel*>(d->source)->setAccountManager(accountManager); 0099 } 0100 } 0101 0102 Tp::AccountManagerPtr KTp::ContactsModel::accountManager() const 0103 { 0104 return d->accountManager; 0105 } 0106 0107 void KTp::ContactsModel::setGroupMode(KTp::ContactsModel::GroupMode mode) 0108 { 0109 if (mode == d->groupMode) { 0110 //if nothing has changed, do nothing. 0111 return; 0112 } 0113 0114 d->groupMode = mode; 0115 0116 updateGroupProxyModels(); 0117 0118 Q_EMIT groupModeChanged(); 0119 } 0120 0121 KTp::ContactsModel::GroupMode KTp::ContactsModel::groupMode() const 0122 { 0123 return d->groupMode; 0124 } 0125 0126 void KTp::ContactsModel::setTrackUnreadMessages(bool trackUnread) 0127 { 0128 if (d->trackUnread == trackUnread) { 0129 return; 0130 } 0131 d->trackUnread = trackUnread; 0132 0133 updateGroupProxyModels(); 0134 0135 Q_EMIT trackUnreadMessagesChanged(); 0136 } 0137 0138 bool KTp::ContactsModel::trackUnreadMessages() const 0139 { 0140 return d->trackUnread; 0141 } 0142 0143 void KTp::ContactsModel::updateGroupProxyModels() 0144 { 0145 //reset the filter 0146 //trying to track current selections whilst updating proxy models can cause issues 0147 //debug versions of Qt will assert 0148 beginResetModel(); 0149 endResetModel(); 0150 0151 //if there no account manager there's not a lot point doing anything 0152 if (!d->accountManager) { 0153 return; 0154 } 0155 0156 //if needed set up the client registrar and observer proxy model 0157 if (d->trackUnread && d->clientRegistrar.isNull()) { 0158 0159 //share the accountFactory and connectFactory etc. from the main application, but create a new channelFactory that fetches the message queue for text chats 0160 Tp::ChannelFactoryPtr channelFactory = Tp::ChannelFactory::create(QDBusConnection::sessionBus()); 0161 channelFactory->addFeaturesForTextChats(Tp::Features() << Tp::Channel::FeatureCore << Tp::TextChannel::FeatureMessageQueue); 0162 d->clientRegistrar = Tp::ClientRegistrar::create(d->accountManager->accountFactory(), d->accountManager->connectionFactory(), channelFactory, d->accountManager->contactFactory()); 0163 0164 d->channelWatcherProxy = Tp::SharedPtr<KTp::TextChannelWatcherProxyModel>(new TextChannelWatcherProxyModel()); 0165 d->channelWatcherProxy->setSourceModel(d->source); 0166 d->clientRegistrar->registerClient(Tp::AbstractClientPtr::dynamicCast(d->channelWatcherProxy), QLatin1String("ListWatcher")); 0167 } else if (!d->trackUnread) { 0168 //delete the client registrar 0169 d->clientRegistrar.reset(); 0170 d->channelWatcherProxy.reset(); 0171 } 0172 0173 QAbstractItemModel *modelToGroup = nullptr; 0174 if (d->trackUnread) { 0175 modelToGroup = d->channelWatcherProxy.data(); 0176 } else { 0177 modelToGroup = d->source; 0178 } 0179 0180 //delete any previous proxy 0181 if (d->proxy) { 0182 d->proxy->deleteLater(); 0183 } 0184 0185 switch (d->groupMode) { 0186 case NoGrouping: 0187 //This is a workaround to a Qt assert which gets confused when we switch from a source model that was 0188 //part of the proxy chain, and is now used in the view directly 0189 // 0190 //do not disable until you have tested on Qt in debug mode 0191 setSourceModel(nullptr); 0192 setSourceModel(modelToGroup); 0193 break; 0194 case AccountGrouping: 0195 d->proxy = new KTp::AccountsTreeProxyModel(modelToGroup, d->accountManager); 0196 setSourceModel(d->proxy); 0197 break; 0198 case GroupGrouping: 0199 d->proxy = new KTp::GroupsTreeProxyModel(modelToGroup); 0200 setSourceModel(d->proxy); 0201 break; 0202 } 0203 } 0204 0205 QHash<int, QByteArray> KTp::ContactsModel::roleNames() const 0206 { 0207 QHash<int, QByteArray> roles = KTp::ContactsFilterModel::roleNames(); 0208 roles[KTp::RowTypeRole]= "type"; 0209 roles[KTp::IdRole]= "id"; 0210 0211 roles[KTp::ContactRole]= "contact"; 0212 roles[KTp::AccountRole]= "account"; 0213 0214 roles[KTp::ContactClientTypesRole]= "clientTypes"; 0215 roles[KTp::ContactAvatarPathRole]= "avatar"; 0216 roles[KTp::ContactAvatarPixmapRole]="avatarPixmap"; 0217 roles[KTp::ContactGroupsRole]= "groups"; 0218 roles[KTp::ContactPresenceNameRole]= "presenceName"; 0219 roles[KTp::ContactPresenceMessageRole]= "presenceMessage"; 0220 roles[KTp::ContactPresenceTypeRole]= "presenceType"; 0221 roles[KTp::ContactPresenceIconRole]= "presenceIcon"; 0222 roles[KTp::ContactSubscriptionStateRole]= "subscriptionState"; 0223 roles[KTp::ContactPublishStateRole]= "publishState"; 0224 roles[KTp::ContactIsBlockedRole]= "blocked"; 0225 roles[KTp::ContactHasTextChannelRole]= "hasTextChannel"; 0226 roles[KTp::ContactUnreadMessageCountRole]= "unreadMessageCount"; 0227 roles[KTp::ContactLastMessageRole]= "lastMessage"; 0228 roles[KTp::ContactLastMessageDirectionRole]= "lastMessageDirection"; 0229 roles[KTp::ContactCanTextChatRole]= "textChat"; 0230 roles[KTp::ContactCanFileTransferRole]= "fileTransfer"; 0231 roles[KTp::ContactCanAudioCallRole]= "audioCall"; 0232 roles[KTp::ContactCanVideoCallRole]= "videoCall"; 0233 roles[KTp::ContactTubesRole]= "tubes"; 0234 roles[KTp::PersonIdRole]= "personId"; 0235 return roles; 0236 }