1 /*
2 Copyright (C) 2014 Aseman
3 http://aseman.co
4
5 This project is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This project is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "telegramdialogsmodel.h"
20 #include "telegramqml.h"
21 #include "objects/types.h"
22 #include "userdata.h"
23 #include "database.h"
24
25 #include <telegram.h>
26 #include <QPointer>
27
28 class TelegramDialogsModelPrivate
29 {
30 public:
31 QPointer<TelegramQml> telegram;
32 bool initializing;
33 bool stopUpdating;
34
35 int refresh_timer;
36
37 QList<qint64> dialogs;
38 };
39
TelegramDialogsModel(QObject * parent)40 TelegramDialogsModel::TelegramDialogsModel(QObject *parent) :
41 TgAbstractListModel(parent)
42 {
43 p = new TelegramDialogsModelPrivate;
44 p->telegram = 0;
45 p->initializing = false;
46 p->stopUpdating = false;
47 p->refresh_timer = 0;
48 }
49
telegram() const50 TelegramQml *TelegramDialogsModel::telegram() const
51 {
52 return p->telegram;
53 }
54
setTelegram(TelegramQml * tgo)55 void TelegramDialogsModel::setTelegram(TelegramQml *tgo)
56 {
57 if( p->telegram == tgo )
58 return;
59
60 if( p->telegram )
61 {
62 disconnect( p->telegram, SIGNAL(dialogsChanged(bool)), this, SLOT(dialogsChanged(bool)) );
63 disconnect( p->telegram, SIGNAL(phoneNumberChanged()), this, SLOT(refreshDatabase()) );
64
65 disconnect( p->telegram->userData(), SIGNAL(favoriteChanged(int)) , this, SLOT(userDataChanged()) );
66 disconnect( p->telegram->userData(), SIGNAL(valueChanged(QString)), this, SLOT(userDataChanged()) );
67
68 disconnect(p->telegram, SIGNAL(authLoggedInChanged()), this, SLOT(recheck()));
69 }
70
71 p->telegram = tgo;
72 p->initializing = tgo;
73 if( p->telegram )
74 {
75 connect( p->telegram, SIGNAL(dialogsChanged(bool)), SLOT(dialogsChanged(bool)) );
76 connect( p->telegram, SIGNAL(phoneNumberChanged()), SLOT(refreshDatabase()), Qt::QueuedConnection );
77
78 connect( p->telegram->userData(), SIGNAL(favoriteChanged(int)) , this, SLOT(userDataChanged()) );
79 connect( p->telegram->userData(), SIGNAL(valueChanged(QString)), this, SLOT(userDataChanged()) );
80
81 connect(p->telegram, SIGNAL(authLoggedInChanged()), this, SLOT(recheck()), Qt::QueuedConnection);
82 }
83
84 recheck();
85
86 Q_EMIT telegramChanged();
87 Q_EMIT initializingChanged();
88 }
89
stopUpdating() const90 bool TelegramDialogsModel::stopUpdating() const
91 {
92 return p->stopUpdating;
93 }
94
setStopUpdating(bool stt)95 void TelegramDialogsModel::setStopUpdating(bool stt)
96 {
97 if(p->stopUpdating == stt)
98 return;
99
100 p->stopUpdating = stt;
101 if(!p->stopUpdating)
102 dialogsChanged(true);
103
104 Q_EMIT stopUpdatingChanged();
105 }
106
id(const QModelIndex & index) const107 qint64 TelegramDialogsModel::id(const QModelIndex &index) const
108 {
109 int row = index.row();
110 return p->dialogs.at(row);
111 }
112
rowCount(const QModelIndex & parent) const113 int TelegramDialogsModel::rowCount(const QModelIndex &parent) const
114 {
115 Q_UNUSED(parent)
116 return p->dialogs.count();
117 }
118
data(const QModelIndex & index,int role) const119 QVariant TelegramDialogsModel::data(const QModelIndex &index, int role) const
120 {
121 QVariant res;
122 const qint64 key = id(index);
123 switch( role )
124 {
125 case ItemRole:
126 res = QVariant::fromValue<DialogObject*>(p->telegram->dialog(key));
127 break;
128
129 case SectionRole:
130 res = p->telegram->userData()->value("love").toLongLong()==key? 2 : (p->telegram->userData()->isFavorited(key)? 1 : 0);
131 break;
132 }
133
134 return res;
135 }
136
roleNames() const137 QHash<qint32, QByteArray> TelegramDialogsModel::roleNames() const
138 {
139 static QHash<qint32, QByteArray> *res = 0;
140 if( res )
141 return *res;
142
143 res = new QHash<qint32, QByteArray>();
144 res->insert( ItemRole, "item");
145 res->insert( SectionRole, "section");
146 return *res;
147 }
148
count() const149 int TelegramDialogsModel::count() const
150 {
151 return p->dialogs.count();
152 }
153
initializing() const154 bool TelegramDialogsModel::initializing() const
155 {
156 return p->initializing;
157 }
158
indexOf(DialogObject * dialog)159 int TelegramDialogsModel::indexOf(DialogObject *dialog)
160 {
161 if(!dialog)
162 return -1;
163
164 qint64 dId = dialog->peer()->chatId();
165 if(!dId)
166 dId = dialog->peer()->userId();
167
168 return p->dialogs.indexOf(dId);
169 }
170
at(int row)171 DialogObject *TelegramDialogsModel::at(int row)
172 {
173 if(row < 0 || row >= p->dialogs.count())
174 return 0;
175
176 return p->telegram->dialog( p->dialogs.at(row) );
177 }
178
refreshDatabase()179 void TelegramDialogsModel::refreshDatabase()
180 {
181 if(!p->telegram)
182 return;
183
184 p->telegram->database()->readFullDialogs();
185 }
186
recheck()187 void TelegramDialogsModel::recheck()
188 {
189 if(!p->telegram)
190 return;
191
192 refreshDatabase();
193 dialogsChanged(true);
194
195 if(!p->telegram->authLoggedIn())
196 return;
197
198 Telegram *tgObject = p->telegram->telegram();
199 if(tgObject)
200 tgObject->messagesGetDialogs(0,0,1000);
201 }
202
dialogsChanged(bool cachedData)203 void TelegramDialogsModel::dialogsChanged(bool cachedData)
204 {
205 Q_UNUSED(cachedData)
206 if(p->initializing)
207 {
208 p->initializing = false;
209 Q_EMIT initializingChanged();
210 }
211
212 if(p->refresh_timer)
213 killTimer(p->refresh_timer);
214
215 p->refresh_timer = startTimer(100);
216 }
217
dialogsChanged_priv()218 void TelegramDialogsModel::dialogsChanged_priv()
219 {
220 if(!p->telegram)
221 return;
222 if(p->stopUpdating)
223 return;
224
225 const QList<qint64> & dialogs = fixDialogs(p->telegram->dialogs());
226
227 for( int i=0 ; i<p->dialogs.count() ; i++ )
228 {
229 const qint64 dId = p->dialogs.at(i);
230 if( dialogs.contains(dId) )
231 continue;
232
233 beginRemoveRows(QModelIndex(), i, i);
234 p->dialogs.removeAt(i);
235 i--;
236 endRemoveRows();
237 }
238
239
240 QList<qint64> temp_msgs = dialogs;
241 for( int i=0 ; i<temp_msgs.count() ; i++ )
242 {
243 const qint64 dId = temp_msgs.at(i);
244 if( p->dialogs.contains(dId) )
245 continue;
246
247 temp_msgs.removeAt(i);
248 i--;
249 }
250 while( p->dialogs != temp_msgs )
251 for( int i=0 ; i<p->dialogs.count() ; i++ )
252 {
253 const qint64 dId = p->dialogs.at(i);
254 int nw = temp_msgs.indexOf(dId);
255 if( i == nw )
256 continue;
257
258 beginMoveRows( QModelIndex(), i, i, QModelIndex(), nw>i?nw+1:nw );
259 p->dialogs.move( i, nw );
260 endMoveRows();
261 }
262
263
264 for( int i=0 ; i<dialogs.count() ; i++ )
265 {
266 const qint64 dId = dialogs.at(i);
267 if( p->dialogs.contains(dId) )
268 continue;
269
270 beginInsertRows(QModelIndex(), i, i );
271 p->dialogs.insert( i, dId );
272 endInsertRows();
273 }
274
275 Q_EMIT countChanged();
276 }
277
userDataChanged()278 void TelegramDialogsModel::userDataChanged()
279 {
280 const QList<qint64> & dialogs = fixDialogs(p->telegram->dialogs());
281
282 beginResetModel();
283 p->dialogs.clear();
284 endResetModel();
285
286 for( int i=0 ; i<dialogs.count() ; i++ )
287 {
288 const qint64 dId = dialogs.at(i);
289 if( p->dialogs.contains(dId) )
290 continue;
291
292 beginInsertRows(QModelIndex(), i, i );
293 p->dialogs.insert( i, dId );
294 endInsertRows();
295 }
296 }
297
fixDialogs(QList<qint64> dialogs)298 QList<qint64> TelegramDialogsModel::fixDialogs(QList<qint64> dialogs)
299 {
300 int fav_counts = 0;
301 for( int i=0; i<dialogs.count(); i++ )
302 {
303 qint64 dId = dialogs.at(i);
304 if( p->telegram->userData()->isFavorited(dId) )
305 {
306 dialogs.move(i, fav_counts);
307 fav_counts++;
308 }
309 }
310
311 qint64 love_id = p->telegram->userData()->value("love").toLongLong();
312 int love_idx = dialogs.indexOf(love_id);
313 if( love_idx != -1 )
314 dialogs.move(love_idx, 0);
315
316 return dialogs;
317 }
318
timerEvent(QTimerEvent * e)319 void TelegramDialogsModel::timerEvent(QTimerEvent *e)
320 {
321 if(e->timerId() == p->refresh_timer)
322 {
323 killTimer(p->refresh_timer);
324 p->refresh_timer = 0;
325
326 dialogsChanged_priv();
327 }
328
329 TgAbstractListModel::timerEvent(e);
330 }
331
~TelegramDialogsModel()332 TelegramDialogsModel::~TelegramDialogsModel()
333 {
334 delete p;
335 }
336