1 #include "gamesmodel.h"
2
3 #include "pb/serverinfo_game.pb.h"
4 #include "pixmapgenerator.h"
5 #include "settingscache.h"
6 #include "tab_account.h"
7 #include "userlist.h"
8
9 #include <QDateTime>
10 #include <QDebug>
11 #include <QIcon>
12 #include <QStringList>
13 #include <QTime>
14
15 enum GameListColumn
16 {
17 ROOM,
18 CREATED,
19 DESCRIPTION,
20 CREATOR,
21 GAME_TYPE,
22 RESTRICTIONS,
23 PLAYERS,
24 SPECTATORS
25 };
26
27 const bool DEFAULT_SHOW_FULL_GAMES = false;
28 const bool DEFAULT_SHOW_GAMES_THAT_STARTED = false;
29 const bool DEFAULT_SHOW_PASSWORD_PROTECTED_GAMES = true;
30 const bool DEFAULT_SHOW_BUDDIES_ONLY_GAMES = true;
31 const bool DEFAULT_HIDE_IGNORED_USER_GAMES = false;
32 const bool DEFAULT_SHOW_ONLY_IF_SPECTATORS_CAN_WATCH = false;
33 const bool DEFAULT_SHOW_SPECTATOR_PASSWORD_PROTECTED = true;
34 const bool DEFAULT_SHOW_ONLY_IF_SPECTATORS_CAN_CHAT = false;
35 const bool DEFAULT_SHOW_ONLY_IF_SPECTATORS_CAN_SEE_HANDS = false;
36 const int DEFAULT_MAX_PLAYERS_MIN = 1;
37 const int DEFAULT_MAX_PLAYERS_MAX = 99;
38 constexpr QTime DEFAULT_MAX_GAME_AGE = QTime();
39
getGameCreatedString(const int secs)40 const QString GamesModel::getGameCreatedString(const int secs)
41 {
42 static const QTime zeroTime{0, 0};
43 static const int halfHourSecs = zeroTime.secsTo(QTime(1, 0)) / 2;
44 static const int halfMinSecs = zeroTime.secsTo(QTime(0, 1)) / 2;
45 static const int wrapSeconds = zeroTime.secsTo(zeroTime.addSecs(-halfHourSecs)); // round up
46
47 if (secs >= wrapSeconds) { // QTime wraps after a day
48 return tr(">1 day");
49 }
50
51 QTime total = zeroTime.addSecs(secs);
52 QTime totalRounded = total.addSecs(halfMinSecs); // round up
53 QString form;
54 int amount;
55 if (totalRounded.hour()) {
56 amount = total.addSecs(halfHourSecs).hour(); // round up separately
57 form = tr("%1%2 hr", "short age in hours", amount);
58 } else if (total.minute() < 2) { // games are new during their first minute
59 return tr("new");
60 } else {
61 amount = totalRounded.minute();
62 form = tr("%1%2 min", "short age in minutes", amount);
63 }
64
65 for (int aggregate : {40, 20, 10, 5}) { // floor to values in this list
66 if (amount >= aggregate) {
67 return form.arg(">").arg(aggregate);
68 }
69 }
70 return form.arg("").arg(amount);
71 }
72
GamesModel(const QMap<int,QString> & _rooms,const QMap<int,GameTypeMap> & _gameTypes,QObject * parent)73 GamesModel::GamesModel(const QMap<int, QString> &_rooms, const QMap<int, GameTypeMap> &_gameTypes, QObject *parent)
74 : QAbstractTableModel(parent), rooms(_rooms), gameTypes(_gameTypes)
75 {
76 }
77
data(const QModelIndex & index,int role) const78 QVariant GamesModel::data(const QModelIndex &index, int role) const
79 {
80 if (!index.isValid())
81 return QVariant();
82 if (role == Qt::UserRole)
83 return index.row();
84 if (role != Qt::DisplayRole && role != SORT_ROLE && role != Qt::DecorationRole && role != Qt::TextAlignmentRole)
85 return QVariant();
86 if ((index.row() >= gameList.size()) || (index.column() >= columnCount()))
87 return QVariant();
88
89 const ServerInfo_Game &gameentry = gameList[index.row()];
90 switch (index.column()) {
91 case ROOM:
92 return rooms.value(gameentry.room_id());
93 case CREATED: {
94 switch (role) {
95 case Qt::DisplayRole: {
96 #if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
97 QDateTime then = QDateTime::fromSecsSinceEpoch(gameentry.start_time(), Qt::UTC);
98 #else
99 QDateTime then = QDateTime::fromTime_t(gameentry.start_time(), Qt::UTC);
100 #endif
101 int secs = then.secsTo(QDateTime::currentDateTimeUtc());
102 return getGameCreatedString(secs);
103 }
104 case SORT_ROLE:
105 return QVariant(-static_cast<qint64>(gameentry.start_time()));
106 case Qt::TextAlignmentRole:
107 return Qt::AlignCenter;
108 default:
109 return QVariant();
110 }
111 }
112 case DESCRIPTION:
113 switch (role) {
114 case SORT_ROLE:
115 case Qt::DisplayRole:
116 return QString::fromStdString(gameentry.description());
117 case Qt::TextAlignmentRole:
118 return Qt::AlignLeft;
119 default:
120 return QVariant();
121 }
122 case CREATOR: {
123 switch (role) {
124 case SORT_ROLE:
125 case Qt::DisplayRole:
126 return QString::fromStdString(gameentry.creator_info().name());
127 case Qt::DecorationRole: {
128 QPixmap avatarPixmap = UserLevelPixmapGenerator::generatePixmap(
129 13, (UserLevelFlags)gameentry.creator_info().user_level(), false,
130 QString::fromStdString(gameentry.creator_info().privlevel()));
131 return QIcon(avatarPixmap);
132 }
133 default:
134 return QVariant();
135 }
136 }
137 case GAME_TYPE:
138 switch (role) {
139 case SORT_ROLE:
140 case Qt::DisplayRole: {
141 QStringList result;
142 GameTypeMap gameTypeMap = gameTypes.value(gameentry.room_id());
143 for (int i = gameentry.game_types_size() - 1; i >= 0; --i)
144 result.append(gameTypeMap.value(gameentry.game_types(i)));
145 return result.join(", ");
146 }
147 case Qt::TextAlignmentRole:
148 return Qt::AlignLeft;
149 default:
150 return QVariant();
151 }
152 case RESTRICTIONS:
153 switch (role) {
154 case SORT_ROLE:
155 case Qt::DisplayRole: {
156 QStringList result;
157 if (gameentry.with_password())
158 result.append(tr("password"));
159 if (gameentry.only_buddies())
160 result.append(tr("buddies only"));
161 if (gameentry.only_registered())
162 result.append(tr("reg. users only"));
163 return result.join(", ");
164 }
165 case Qt::DecorationRole: {
166 return gameentry.with_password() ? QIcon(LockPixmapGenerator::generatePixmap(13)) : QVariant();
167 case Qt::TextAlignmentRole:
168 return Qt::AlignLeft;
169 default:
170 return QVariant();
171 }
172 }
173 case PLAYERS:
174 switch (role) {
175 case SORT_ROLE:
176 case Qt::DisplayRole:
177 return QString("%1/%2").arg(gameentry.player_count()).arg(gameentry.max_players());
178 case Qt::TextAlignmentRole:
179 return Qt::AlignCenter;
180 default:
181 return QVariant();
182 }
183
184 case SPECTATORS:
185 switch (role) {
186 case SORT_ROLE:
187 case Qt::DisplayRole: {
188 if (gameentry.spectators_allowed()) {
189 QString result;
190 result.append(QString::number(gameentry.spectators_count()));
191
192 if (gameentry.spectators_can_chat() && gameentry.spectators_omniscient()) {
193 result.append(" (")
194 .append(tr("can chat"))
195 .append(" & ")
196 .append(tr("see hands"))
197 .append(")");
198 } else if (gameentry.spectators_can_chat()) {
199 result.append(" (").append(tr("can chat")).append(")");
200 } else if (gameentry.spectators_omniscient()) {
201 result.append(" (").append(tr("can see hands")).append(")");
202 }
203
204 return result;
205 }
206 return QVariant(tr("not allowed"));
207 }
208 case Qt::TextAlignmentRole:
209 return Qt::AlignLeft;
210 default:
211 return QVariant();
212 }
213 default:
214 return QVariant();
215 }
216 }
217
headerData(int section,Qt::Orientation,int role) const218 QVariant GamesModel::headerData(int section, Qt::Orientation /*orientation*/, int role) const
219 {
220 if ((role != Qt::DisplayRole) && (role != Qt::TextAlignmentRole))
221 return QVariant();
222 switch (section) {
223 case ROOM:
224 return tr("Room");
225 case CREATED: {
226 switch (role) {
227 case Qt::DisplayRole:
228 return tr("Age");
229 case Qt::TextAlignmentRole:
230 return Qt::AlignCenter;
231 default:
232 return QVariant();
233 }
234 }
235 case DESCRIPTION:
236 return tr("Description");
237 case CREATOR:
238 return tr("Creator");
239 case GAME_TYPE:
240 return tr("Type");
241 case RESTRICTIONS:
242 return tr("Restrictions");
243 case PLAYERS: {
244 switch (role) {
245 case Qt::DisplayRole:
246 return tr("Players");
247 case Qt::TextAlignmentRole:
248 return Qt::AlignCenter;
249 default:
250 return QVariant();
251 }
252 }
253 case SPECTATORS:
254 return tr("Spectators");
255 default:
256 return QVariant();
257 }
258 }
259
getGame(int row)260 const ServerInfo_Game &GamesModel::getGame(int row)
261 {
262 Q_ASSERT(row < gameList.size());
263 return gameList[row];
264 }
265
updateGameList(const ServerInfo_Game & game)266 void GamesModel::updateGameList(const ServerInfo_Game &game)
267 {
268 for (int i = 0; i < gameList.size(); i++) {
269 if (gameList[i].game_id() == game.game_id()) {
270 if (game.closed()) {
271 beginRemoveRows(QModelIndex(), i, i);
272 gameList.removeAt(i);
273 endRemoveRows();
274 } else {
275 gameList[i].MergeFrom(game);
276 emit dataChanged(index(i, 0), index(i, NUM_COLS - 1));
277 }
278 return;
279 }
280 }
281 if (game.player_count() <= 0)
282 return;
283 beginInsertRows(QModelIndex(), gameList.size(), gameList.size());
284 gameList.append(game);
285 endInsertRows();
286 }
287
GamesProxyModel(QObject * parent,const TabSupervisor * _tabSupervisor)288 GamesProxyModel::GamesProxyModel(QObject *parent, const TabSupervisor *_tabSupervisor)
289 : QSortFilterProxyModel(parent), ownUserIsRegistered(_tabSupervisor->isOwnUserRegistered()),
290 tabSupervisor(_tabSupervisor)
291 {
292 resetFilterParameters();
293 setSortRole(GamesModel::SORT_ROLE);
294 setDynamicSortFilter(true);
295 }
296
setShowBuddiesOnlyGames(bool _showBuddiesOnlyGames)297 void GamesProxyModel::setShowBuddiesOnlyGames(bool _showBuddiesOnlyGames)
298 {
299 showBuddiesOnlyGames = _showBuddiesOnlyGames;
300 invalidateFilter();
301 }
302
setHideIgnoredUserGames(bool _hideIgnoredUserGames)303 void GamesProxyModel::setHideIgnoredUserGames(bool _hideIgnoredUserGames)
304 {
305 hideIgnoredUserGames = _hideIgnoredUserGames;
306 invalidateFilter();
307 }
308
setShowFullGames(bool _showFullGames)309 void GamesProxyModel::setShowFullGames(bool _showFullGames)
310 {
311 showFullGames = _showFullGames;
312 invalidateFilter();
313 }
314
setShowGamesThatStarted(bool _showGamesThatStarted)315 void GamesProxyModel::setShowGamesThatStarted(bool _showGamesThatStarted)
316 {
317 showGamesThatStarted = _showGamesThatStarted;
318 invalidateFilter();
319 }
320
setShowPasswordProtectedGames(bool _showPasswordProtectedGames)321 void GamesProxyModel::setShowPasswordProtectedGames(bool _showPasswordProtectedGames)
322 {
323 showPasswordProtectedGames = _showPasswordProtectedGames;
324 invalidateFilter();
325 }
326
setGameNameFilter(const QString & _gameNameFilter)327 void GamesProxyModel::setGameNameFilter(const QString &_gameNameFilter)
328 {
329 gameNameFilter = _gameNameFilter;
330 invalidateFilter();
331 }
332
setCreatorNameFilter(const QString & _creatorNameFilter)333 void GamesProxyModel::setCreatorNameFilter(const QString &_creatorNameFilter)
334 {
335 creatorNameFilter = _creatorNameFilter;
336 invalidateFilter();
337 }
338
setGameTypeFilter(const QSet<int> & _gameTypeFilter)339 void GamesProxyModel::setGameTypeFilter(const QSet<int> &_gameTypeFilter)
340 {
341 gameTypeFilter = _gameTypeFilter;
342 invalidateFilter();
343 }
344
setMaxPlayersFilter(int _maxPlayersFilterMin,int _maxPlayersFilterMax)345 void GamesProxyModel::setMaxPlayersFilter(int _maxPlayersFilterMin, int _maxPlayersFilterMax)
346 {
347 maxPlayersFilterMin = _maxPlayersFilterMin;
348 maxPlayersFilterMax = _maxPlayersFilterMax;
349 invalidateFilter();
350 }
351
setMaxGameAge(const QTime & _maxGameAge)352 void GamesProxyModel::setMaxGameAge(const QTime &_maxGameAge)
353 {
354 maxGameAge = _maxGameAge;
355 invalidateFilter();
356 }
357
setShowOnlyIfSpectatorsCanWatch(bool _showOnlyIfSpectatorsCanWatch)358 void GamesProxyModel::setShowOnlyIfSpectatorsCanWatch(bool _showOnlyIfSpectatorsCanWatch)
359 {
360 showOnlyIfSpectatorsCanWatch = _showOnlyIfSpectatorsCanWatch;
361 invalidateFilter();
362 }
363
setShowSpectatorPasswordProtected(bool _showSpectatorPasswordProtected)364 void GamesProxyModel::setShowSpectatorPasswordProtected(bool _showSpectatorPasswordProtected)
365 {
366 showSpectatorPasswordProtected = _showSpectatorPasswordProtected;
367 invalidateFilter();
368 }
369
setShowOnlyIfSpectatorsCanChat(bool _showOnlyIfSpectatorsCanChat)370 void GamesProxyModel::setShowOnlyIfSpectatorsCanChat(bool _showOnlyIfSpectatorsCanChat)
371 {
372 showOnlyIfSpectatorsCanChat = _showOnlyIfSpectatorsCanChat;
373 invalidateFilter();
374 }
375
setShowOnlyIfSpectatorsCanSeeHands(bool _showOnlyIfSpectatorsCanSeeHands)376 void GamesProxyModel::setShowOnlyIfSpectatorsCanSeeHands(bool _showOnlyIfSpectatorsCanSeeHands)
377 {
378 showOnlyIfSpectatorsCanSeeHands = _showOnlyIfSpectatorsCanSeeHands;
379 invalidateFilter();
380 }
381
getNumFilteredGames() const382 int GamesProxyModel::getNumFilteredGames() const
383 {
384 GamesModel *model = qobject_cast<GamesModel *>(sourceModel());
385 if (!model)
386 return 0;
387
388 int numFilteredGames = 0;
389 for (int row = 0; row < model->rowCount(); ++row) {
390 if (!filterAcceptsRow(row)) {
391 ++numFilteredGames;
392 }
393 }
394 return numFilteredGames;
395 }
396
resetFilterParameters()397 void GamesProxyModel::resetFilterParameters()
398 {
399 showFullGames = DEFAULT_SHOW_FULL_GAMES;
400 showGamesThatStarted = DEFAULT_SHOW_GAMES_THAT_STARTED;
401 showPasswordProtectedGames = DEFAULT_SHOW_PASSWORD_PROTECTED_GAMES;
402 showBuddiesOnlyGames = DEFAULT_SHOW_BUDDIES_ONLY_GAMES;
403 hideIgnoredUserGames = DEFAULT_HIDE_IGNORED_USER_GAMES;
404 gameNameFilter = QString();
405 creatorNameFilter = QString();
406 gameTypeFilter.clear();
407 maxPlayersFilterMin = DEFAULT_MAX_PLAYERS_MIN;
408 maxPlayersFilterMax = DEFAULT_MAX_PLAYERS_MAX;
409 maxGameAge = DEFAULT_MAX_GAME_AGE;
410 showOnlyIfSpectatorsCanWatch = DEFAULT_SHOW_ONLY_IF_SPECTATORS_CAN_WATCH;
411 showSpectatorPasswordProtected = DEFAULT_SHOW_SPECTATOR_PASSWORD_PROTECTED;
412 showOnlyIfSpectatorsCanChat = DEFAULT_SHOW_ONLY_IF_SPECTATORS_CAN_CHAT;
413 showOnlyIfSpectatorsCanSeeHands = DEFAULT_SHOW_ONLY_IF_SPECTATORS_CAN_SEE_HANDS;
414
415 invalidateFilter();
416 }
417
areFilterParametersSetToDefaults() const418 bool GamesProxyModel::areFilterParametersSetToDefaults() const
419 {
420 return showFullGames == DEFAULT_SHOW_FULL_GAMES && showGamesThatStarted == DEFAULT_SHOW_GAMES_THAT_STARTED &&
421 showPasswordProtectedGames == DEFAULT_SHOW_PASSWORD_PROTECTED_GAMES &&
422 showBuddiesOnlyGames == DEFAULT_SHOW_BUDDIES_ONLY_GAMES &&
423 hideIgnoredUserGames == DEFAULT_HIDE_IGNORED_USER_GAMES && gameNameFilter.isEmpty() &&
424 creatorNameFilter.isEmpty() && gameTypeFilter.isEmpty() && maxPlayersFilterMin == DEFAULT_MAX_PLAYERS_MIN &&
425 maxPlayersFilterMax == DEFAULT_MAX_PLAYERS_MAX && maxGameAge == DEFAULT_MAX_GAME_AGE &&
426 showOnlyIfSpectatorsCanWatch == DEFAULT_SHOW_ONLY_IF_SPECTATORS_CAN_WATCH &&
427 showSpectatorPasswordProtected == DEFAULT_SHOW_SPECTATOR_PASSWORD_PROTECTED &&
428 showOnlyIfSpectatorsCanChat == DEFAULT_SHOW_ONLY_IF_SPECTATORS_CAN_CHAT &&
429 showOnlyIfSpectatorsCanSeeHands == DEFAULT_SHOW_ONLY_IF_SPECTATORS_CAN_SEE_HANDS;
430 }
431
loadFilterParameters(const QMap<int,QString> & allGameTypes)432 void GamesProxyModel::loadFilterParameters(const QMap<int, QString> &allGameTypes)
433 {
434 GameFiltersSettings &gameFilters = SettingsCache::instance().gameFilters();
435 showFullGames = gameFilters.isShowFullGames();
436 showGamesThatStarted = gameFilters.isShowGamesThatStarted();
437 showPasswordProtectedGames = gameFilters.isShowPasswordProtectedGames();
438 hideIgnoredUserGames = gameFilters.isHideIgnoredUserGames();
439 showBuddiesOnlyGames = gameFilters.isShowBuddiesOnlyGames();
440 gameNameFilter = gameFilters.getGameNameFilter();
441 creatorNameFilter = gameFilters.getCreatorNameFilter();
442 maxPlayersFilterMin = gameFilters.getMinPlayers();
443 maxPlayersFilterMax = gameFilters.getMaxPlayers();
444 maxGameAge = gameFilters.getMaxGameAge();
445 showOnlyIfSpectatorsCanWatch = gameFilters.isShowOnlyIfSpectatorsCanWatch();
446 showSpectatorPasswordProtected = gameFilters.isShowSpectatorPasswordProtected();
447 showOnlyIfSpectatorsCanChat = gameFilters.isShowOnlyIfSpectatorsCanChat();
448 showOnlyIfSpectatorsCanSeeHands = gameFilters.isShowOnlyIfSpectatorsCanSeeHands();
449
450 QMapIterator<int, QString> gameTypesIterator(allGameTypes);
451 while (gameTypesIterator.hasNext()) {
452 gameTypesIterator.next();
453 if (gameFilters.isGameTypeEnabled(gameTypesIterator.value())) {
454 gameTypeFilter.insert(gameTypesIterator.key());
455 }
456 }
457
458 invalidateFilter();
459 }
460
saveFilterParameters(const QMap<int,QString> & allGameTypes)461 void GamesProxyModel::saveFilterParameters(const QMap<int, QString> &allGameTypes)
462 {
463 GameFiltersSettings &gameFilters = SettingsCache::instance().gameFilters();
464 gameFilters.setShowBuddiesOnlyGames(showBuddiesOnlyGames);
465 gameFilters.setShowFullGames(showFullGames);
466 gameFilters.setShowGamesThatStarted(showGamesThatStarted);
467 gameFilters.setShowPasswordProtectedGames(showPasswordProtectedGames);
468 gameFilters.setHideIgnoredUserGames(hideIgnoredUserGames);
469 gameFilters.setGameNameFilter(gameNameFilter);
470 gameFilters.setCreatorNameFilter(creatorNameFilter);
471
472 QMapIterator<int, QString> gameTypeIterator(allGameTypes);
473 while (gameTypeIterator.hasNext()) {
474 gameTypeIterator.next();
475 bool enabled = gameTypeFilter.contains(gameTypeIterator.key());
476 gameFilters.setGameTypeEnabled(gameTypeIterator.value(), enabled);
477 }
478
479 gameFilters.setMinPlayers(maxPlayersFilterMin);
480 gameFilters.setMaxPlayers(maxPlayersFilterMax);
481 gameFilters.setMaxGameAge(maxGameAge);
482
483 gameFilters.setShowOnlyIfSpectatorsCanWatch(showOnlyIfSpectatorsCanWatch);
484 gameFilters.setShowSpectatorPasswordProtected(showSpectatorPasswordProtected);
485 gameFilters.setShowOnlyIfSpectatorsCanChat(showOnlyIfSpectatorsCanChat);
486 gameFilters.setShowOnlyIfSpectatorsCanSeeHands(showOnlyIfSpectatorsCanSeeHands);
487 }
488
filterAcceptsRow(int sourceRow,const QModelIndex &) const489 bool GamesProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex & /*sourceParent*/) const
490 {
491 return filterAcceptsRow(sourceRow);
492 }
493
filterAcceptsRow(int sourceRow) const494 bool GamesProxyModel::filterAcceptsRow(int sourceRow) const
495 {
496 #if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
497 static const QDate epochDate = QDateTime::fromSecsSinceEpoch(0, Qt::UTC).date();
498 #else
499 static const QDate epochDate = QDateTime::fromTime_t(0, Qt::UTC).date();
500 #endif
501 auto *model = qobject_cast<GamesModel *>(sourceModel());
502 if (!model)
503 return false;
504
505 const ServerInfo_Game &game = model->getGame(sourceRow);
506
507 if (!showBuddiesOnlyGames && game.only_buddies()) {
508 return false;
509 }
510 if (hideIgnoredUserGames && tabSupervisor->getUserListsTab()->getIgnoreList()->getUsers().contains(
511 QString::fromStdString(game.creator_info().name()))) {
512 return false;
513 }
514 if (!showFullGames && game.player_count() == game.max_players())
515 return false;
516 if (!showGamesThatStarted && game.started())
517 return false;
518 if (!ownUserIsRegistered)
519 if (game.only_registered())
520 return false;
521 if (!showPasswordProtectedGames && game.with_password())
522 return false;
523 if (!gameNameFilter.isEmpty())
524 if (!QString::fromStdString(game.description()).contains(gameNameFilter, Qt::CaseInsensitive))
525 return false;
526 if (!creatorNameFilter.isEmpty())
527 if (!QString::fromStdString(game.creator_info().name()).contains(creatorNameFilter, Qt::CaseInsensitive))
528 return false;
529
530 QSet<int> gameTypes;
531 for (int i = 0; i < game.game_types_size(); ++i)
532 gameTypes.insert(game.game_types(i));
533 if (!gameTypeFilter.isEmpty() && gameTypes.intersect(gameTypeFilter).isEmpty())
534 return false;
535
536 if (game.max_players() < maxPlayersFilterMin)
537 return false;
538 if (game.max_players() > maxPlayersFilterMax)
539 return false;
540
541 if (maxGameAge.isValid()) {
542 QDateTime now = QDateTime::currentDateTimeUtc();
543 qint64 signed_start_time = game.start_time(); // cast to 64 bit value to allow signed value
544 QDateTime total = now.addSecs(-signed_start_time); // a 32 bit value would wrap at 2038-1-19
545 // games shouldn't have negative ages but we'll not filter them
546 // because qtime wraps after a day we consider all games older than a day to be too old
547 if (total.isValid() && total.date() >= epochDate && (total.date() > epochDate || total.time() > maxGameAge)) {
548 return false;
549 }
550 }
551
552 if (showOnlyIfSpectatorsCanWatch) {
553 if (!game.spectators_allowed())
554 return false;
555 if (!showSpectatorPasswordProtected && game.spectators_need_password())
556 return false;
557 if (showOnlyIfSpectatorsCanChat && !game.spectators_can_chat())
558 return false;
559 if (showOnlyIfSpectatorsCanSeeHands && !game.spectators_omniscient())
560 return false;
561 }
562 return true;
563 }
564
refresh()565 void GamesProxyModel::refresh()
566 {
567 invalidateFilter();
568 }
569