~ubuntu-branches/ubuntu/vivid/qgo/vivid-proposed

« back to all changes in this revision

Viewing changes to src/network/room.cpp

  • Committer: Package Import Robot
  • Author(s): Yann Dirson
  • Date: 2012-05-19 19:05:05 UTC
  • mfrom: (1.1.12)
  • Revision ID: package-import@ubuntu.com-20120519190505-b23f5tzx7y8cu946
Tags: 2~svn764-1
* The "Raise dead" release (Closes: #673520), new maintainer.
* New upstream snapshot with Qt4 support (Closes: #604589), adjusted
  build-deps.
* Switched to source format "3.0 (quilt)", adjusted build-deps.
* Switched to dh and debhelper compat level 9, adjusted build-deps.
* Build with -fpermissive.
* New build-dep libasound2-dev, remove obsolete build-dep on libxinerama-dev.
* Refreshed patches 01_gnugo and 04_desktop, leaving 20_kfreebsd away
  for this release, and removing the remaining ones, now obsolete.
* Added patch 02_usrgames for FHS-correct install location.
* Adjusted icon names in menu file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   Copyright (C) 2009 by The qGo Project                                 *
 
3
 *                                                                         *
 
4
 *   This file is part of qGo.                                             *
 
5
 *                                                                         *
 
6
 *   qGo is free software: you can redistribute it and/or modify           *
 
7
 *   it under the terms of the GNU General Public License as published by  *
 
8
 *   the Free Software Foundation; either version 2 of the License, or     *
 
9
 *   (at your option) any later version.                                   *
 
10
 *                                                                         *
 
11
 *   This program is distributed in the hope that it will be useful,       *
 
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 
14
 *   GNU General Public License for more details.                          *
 
15
 *                                                                         *
 
16
 *   You should have received a copy of the GNU General Public License     *
 
17
 *   along with this program; if not, see <http://www.gnu.org/licenses/>   *
 
18
 *   or write to the Free Software Foundation, Inc.,                       *
 
19
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 
20
 ***************************************************************************/
 
21
 
 
22
 
 
23
#include "room.h"
 
24
#include "../listviews.h"
 
25
#include "roomregistries.h"
 
26
#include "talk.h"
 
27
#include "messages.h"
 
28
#include "gamedialog.h"
 
29
#include "../mainwindow.h"
 
30
#include "playergamelistings.h"
 
31
#include "boarddispatch.h"      //so we can remove observers
 
32
#include "friendslistdialog.h"
 
33
 
 
34
//#define PLAYERLISTING_ISSUES
 
35
Room::Room()
 
36
{
 
37
        playerView = mainwindow->getUi()->playerView;
 
38
        gamesView = mainwindow->getUi()->gamesView;
 
39
        refreshPlayersButton = mainwindow->getUi()->pbRefreshPlayers;
 
40
        refreshGamesButton = mainwindow->getUi()->pbRefreshGames;
 
41
        whoBox1 = mainwindow->getUi()->whoBox1;
 
42
        whoBox2 = mainwindow->getUi()->whoBox2;
 
43
        whoOpenCheckBox = mainwindow->getUi()->whoOpenCheck;
 
44
        friendsCheckBox = mainwindow->getUi()->friendsCheck;
 
45
        watchesCheckBox = mainwindow->getUi()->watchesCheck;
 
46
        editFriendsWatchesListButton = mainwindow->getUi()->editFriendsWatchesPB;
 
47
        /* Normally the dispatch and the UI are created at the sametime
 
48
        * by the connection or dispatch code.  In this case,
 
49
        * the UI already exists and is being passed straight in here,
 
50
        * so we'll do things backwards and have this create the dispatch */
 
51
        /* UI MUST be created before dispatch.  FIXME
 
52
        * This is an ugly non-apparent dependency because
 
53
        * the dispatch registries depend on the UI's models */
 
54
        /* There are further strangenesses here because of the account_name
 
55
        * for making our player listing blue */
 
56
        setupUI();
 
57
        
 
58
        playerListingRegistry = 0;
 
59
        playerListingIDRegistry = 0;
 
60
        
 
61
        players = 0;
 
62
        games = 0;
 
63
}
 
64
 
 
65
void Room::setupUI(void)
 
66
{
 
67
        gamesListModel = new GamesListModel();
 
68
 
 
69
        /*ui.ListView_games->header()->setSortIndicatorShown ( FALSE );
 
70
        ui.ListView_games->hideColumn(12);
 
71
        ui.ListView_games->hideColumn(13);*/
 
72
        gamesView->setModel(gamesListModel);
 
73
        gamesView->setFilter(new GamesListFilter(gamesListModel));
 
74
        /* Justifications??? */
 
75
        /* No sort indicator??? */
 
76
        /* Qt 4.4.1 made sortIndicatorShown necesssary for sort behavior
 
77
         * !!!! */
 
78
        gamesView->header()->setSortIndicatorShown ( true );
 
79
 
 
80
        //gamesView->setSelectionBehavior(QAbstractItemView::SelectRows);
 
81
        /*ui.gamesView->setColumnWidth ( 0, 40 );       //35
 
82
        ui.gamesView->setColumnWidth ( 1, 100 );
 
83
        ui.gamesView->setColumnWidth ( 2, 48 ); //35
 
84
        ui.gamesView->setColumnWidth ( 3, 100 );
 
85
        ui.gamesView->setColumnWidth ( 4, 48 ); //35
 
86
        ui.gamesView->setColumnWidth ( 5, 45 ); //30
 
87
        ui.gamesView->setColumnWidth ( 6, 45 ); //25
 
88
        ui.gamesView->setColumnWidth ( 7, 38 ); //20
 
89
        ui.gamesView->setColumnWidth ( 8, 35 ); //30
 
90
        ui.gamesView->setColumnWidth ( 9, 43 ); //25
 
91
        ui.gamesView->setColumnWidth ( 10, 60 ); //20
 
92
        ui.gamesView->setColumnWidth ( 11, 55 ); //25
 
93
        */
 
94
        //IGS needs bigger rank column with the "+"s, etc., also whole thing looks sloppy FIXME
 
95
        gamesView->setColumnWidth ( 0, 40 );    //35
 
96
        gamesView->setColumnWidth ( 1, 100 );
 
97
        gamesView->setColumnWidth ( 2, 40 );    //35
 
98
        gamesView->setColumnWidth ( 3, 100 );
 
99
        gamesView->setColumnWidth ( 4, 40 );    //35
 
100
        gamesView->setColumnWidth ( 5, 30 );    //30
 
101
        gamesView->setColumnWidth ( 6, 30 ); //25
 
102
        gamesView->setColumnWidth ( 7, 20 ); //20
 
103
        gamesView->setColumnWidth ( 8, 35 ); //30
 
104
        gamesView->setColumnWidth ( 9, 35 ); //25
 
105
        gamesView->setColumnWidth ( 10, 35 ); //20
 
106
        gamesView->setColumnWidth ( 11, 30 ); //25
 
107
        //ui.gamesView->show();
 
108
        
 
109
        playerListModel = new PlayerListModel();
 
110
        /* FIXME the below seems to have no affect, so I commented it out.
 
111
         * I changed references to the listmodel to the sortproxy in the id
 
112
         * registries, in the hope that they would... well I think that was the
 
113
         * wrong way, but I can't be sure since it could be an issue with
 
114
         * the network connection as well... anyway, if I get it working
 
115
         * correctly, probably more like the way it was, then I should change
 
116
         * the sortproxy references back maybe... */
 
117
        
 
118
   // playerView->setIconSize(QSize(20, 20));
 
119
        playerView->setModel(playerListModel);
 
120
        playerListModel->setView(playerView);
 
121
        playerView->setFilter(new PlayerListFilter(playerListModel));
 
122
        playerView->header()->setSortIndicatorShown ( true );
 
123
        
 
124
        playerView->setColumnWidth ( 0, 40 );
 
125
        playerView->setColumnWidth ( 1, 100 );
 
126
        playerView->setColumnWidth ( 2, 40 );
 
127
        playerView->setColumnWidth ( 3, 40 );
 
128
        playerView->setColumnWidth ( 4, 40);
 
129
        playerView->setColumnWidth ( 5, 40 );
 
130
        playerView->setColumnWidth ( 6, 40 );
 
131
        playerView->setColumnWidth ( 7, 40 );
 
132
        playerView->setColumnWidth ( 8, 80 );
 
133
        /*ui.ListView_players->hideColumn(6);
 
134
        ui.ListView_players->hideColumn(7);
 
135
        ui.ListView_players->hideColumn(8);
 
136
        ui.ListView_players->hideColumn(9);
 
137
        ui.ListView_players->hideColumn(12);
 
138
        ui.ListView_players->setColumnWidth ( 0, 30 );
 
139
        ui.ListView_players->setColumnWidth ( 1, 100 );
 
140
        ui.ListView_players->setColumnWidth ( 2, 30 );
 
141
        ui.ListView_players->setColumnWidth ( 3, 30 );
 
142
        ui.ListView_players->setColumnWidth ( 4, 30);
 
143
        ui.ListView_players->setColumnWidth ( 5, 30 );
 
144
//      ui.ListView_players->setColumnWidth ( 6, 80 );
 
145
        ui.ListView_players->setColumnWidth ( 7, 80 );
 
146
//      ui.ListView_players->setColumnWidth ( 8, 30 );
 
147
//      ui.ListView_players->setColumnWidth ( 9, 25 );
 
148
        ui.ListView_players->setColumnWidth ( 10, 50 );
 
149
//      ui.ListView_players->setColumnWidth ( 11, 25 );*/
 
150
 
 
151
        whoBox1->setCurrentIndex(0);
 
152
        whoBox2->setCurrentIndex(0);
 
153
        /* Maybe also a "clicked" for something? */
 
154
        connect(playerView, SIGNAL(doubleClicked(const QModelIndex &)), SLOT(slot_playersDoubleClicked(const QModelIndex &)));
 
155
        connect(playerView, SIGNAL(customContextMenuRequested (const QPoint &)), SLOT(slot_showPopup(const QPoint &)));
 
156
        connect(gamesView, SIGNAL(doubleClicked(const QModelIndex &)), SLOT(slot_gamesDoubleClicked(const QModelIndex &)));
 
157
        connect(gamesView, SIGNAL(customContextMenuRequested (const QPoint &)), SLOT(slot_showGamesPopup(const QPoint &)));
 
158
        connect(refreshPlayersButton, SIGNAL(pressed()), SLOT(slot_refreshPlayers()));
 
159
        connect(refreshGamesButton, SIGNAL(pressed()), SLOT(slot_refreshGames()));
 
160
        connect(whoBox1, SIGNAL(currentIndexChanged(int)), SLOT(slot_setRankSpreadView()));
 
161
        connect(whoBox2, SIGNAL(currentIndexChanged(int)), SLOT(slot_setRankSpreadView()));
 
162
        connect(whoOpenCheckBox, SIGNAL(stateChanged(int)), SLOT(slot_showOpen(int)));
 
163
        connect(friendsCheckBox, SIGNAL(stateChanged(int)), SLOT(slot_showFriends(int)));
 
164
        connect(watchesCheckBox, SIGNAL(stateChanged(int)), SLOT(slot_showWatches(int)));
 
165
        connect(editFriendsWatchesListButton, SIGNAL(pressed()), SLOT(slot_editFriendsWatchesList()));
 
166
        editFriendsWatchesListButton->setEnabled(true);
 
167
        whoOpenCheckBox->setEnabled(true);
 
168
        friendsCheckBox->setEnabled(true);
 
169
        watchesCheckBox->setEnabled(true);
 
170
        playerView->blockSignals(false);
 
171
        gamesView->blockSignals(false);
 
172
        playerView->header()->blockSignals(false);
 
173
        gamesView->header()->blockSignals(false);
 
174
}
 
175
 
 
176
Room::~Room()
 
177
{
 
178
        delete playerListingRegistry;
 
179
        delete playerListingIDRegistry;
 
180
        delete gameListingRegistry;
 
181
        
 
182
        /* FIXME: Should probably be part of something else this P G stuff */
 
183
        mainwindow->statusUsers->setText(" P: 0");
 
184
        mainwindow->statusGames->setText(" G: 0");
 
185
        //mainwindow->ui.changeServerPB->hide();        //done in mainwindow_server
 
186
        //mainwindow->ui.createRoomPB->hide();
 
187
        
 
188
        /* If this was a stand alone room, we'd also destroy the UI
 
189
         * here, I just want to clear the lists */
 
190
        qDebug("Deconstructing room");
 
191
        /* blockSignals necessary in qt 4.7 otherwise setModel(0) crashes stupidly */
 
192
        playerView->blockSignals(true);
 
193
        gamesView->blockSignals(true);
 
194
        playerView->header()->blockSignals(true);
 
195
        gamesView->header()->blockSignals(true);
 
196
        playerView->setModel(0);
 
197
        gamesView->setModel(0);
 
198
        delete playerListModel;
 
199
        delete gamesListModel;
 
200
        
 
201
        disconnect(whoBox1, SIGNAL(currentIndexChanged(int)), 0, 0);
 
202
        disconnect(whoBox2, SIGNAL(currentIndexChanged(int)), 0, 0);
 
203
        disconnect(editFriendsWatchesListButton, SIGNAL(pressed()), 0, 0);
 
204
        disconnect(whoOpenCheckBox, SIGNAL(stateChanged(int)), 0, 0);
 
205
        disconnect(friendsCheckBox, SIGNAL(stateChanged(int)), 0, 0);
 
206
        disconnect(watchesCheckBox, SIGNAL(stateChanged(int)), 0, 0);
 
207
        editFriendsWatchesListButton->setDisabled(true);
 
208
        
 
209
        QSettings settings;
 
210
        settings.setValue("LOWRANKFILTER", whoBox1->currentIndex());
 
211
        settings.setValue("HIGHRANKFILTER", whoBox2->currentIndex());
 
212
        whoBox1->setCurrentIndex(0);
 
213
        whoBox2->setCurrentIndex(0);
 
214
        
 
215
        settings.setValue("OPENFILTER", whoOpenCheckBox->isChecked());
 
216
        settings.setValue("FRIENDSFILTER", friendsCheckBox->isChecked());
 
217
        settings.setValue("WATCHESFILTER", watchesCheckBox->isChecked());
 
218
        whoOpenCheckBox->setChecked(false);
 
219
        friendsCheckBox->setChecked(false);
 
220
        watchesCheckBox->setChecked(false);
 
221
        whoOpenCheckBox->setEnabled(false);
 
222
        friendsCheckBox->setEnabled(false);
 
223
        watchesCheckBox->setEnabled(false);
 
224
}
 
225
 
 
226
void Room::onError(void)
 
227
{
 
228
        /* We're going to call this straight from the network dispatch
 
229
         * until we work out any room UI issues */
 
230
        //mainwindow->onConnectionError();
 
231
}
 
232
 
 
233
void Room::setConnection(NetworkConnection * c)
 
234
{
 
235
        connection = c;
 
236
        if(connection->playerTrackingByID())
 
237
        {
 
238
                qDebug("Creating player ID Registry");
 
239
                playerListingIDRegistry = new PlayerListingIDRegistry(playerListModel);
 
240
        }
 
241
        else
 
242
        {
 
243
                qDebug("Creating player Registry");
 
244
                playerListingRegistry = new PlayerListingRegistry(playerListModel);
 
245
        }
 
246
        gameListingRegistry = new GameListingRegistry(gamesListModel);
 
247
        
 
248
        playerListModel->setAccountName(connection->getUsername());
 
249
        // FIXME, what about observerListModels when they come up on boards?
 
250
        unsigned long flags = connection->getPlayerListColumns();
 
251
        if(flags & PL_NOWINSLOSSES)
 
252
        {
 
253
                playerView->hideColumn(5);
 
254
                playerView->hideColumn(6);
 
255
        }
 
256
        if(flags & PL_NOMATCHPREFS)
 
257
        {
 
258
                playerView->hideColumn(9);      
 
259
        }
 
260
        
 
261
        QSettings settings;
 
262
        QVariant var = settings.value("LOWRANKFILTER");
 
263
        if(var != QVariant())
 
264
        {
 
265
                whoBox1->setCurrentIndex(var.toInt());
 
266
                whoBox2->setCurrentIndex(settings.value("HIGHRANKFILTER").toInt());
 
267
        }
 
268
        
 
269
        whoOpenCheckBox->setChecked(settings.value("OPENFILTER").toBool());
 
270
        friendsCheckBox->setChecked(settings.value("FRIENDSFILTER").toBool());
 
271
        watchesCheckBox->setChecked(settings.value("WATCHESFILTER").toBool());
 
272
}
 
273
 
 
274
void Room::updateRoomStats(void)
 
275
{
 
276
        /* With sort, it might be better to get these from the registries? 
 
277
         * possible FIXME */
 
278
        players = playerListModel->rowCount(QModelIndex());
 
279
        games = gamesListModel->rowCount(QModelIndex());
 
280
        
 
281
        //qDebug("%d %d", players, games);
 
282
        mainwindow->statusUsers->setText(" P: " + QString::number(players));
 
283
        mainwindow->statusGames->setText(" G: " + QString::number(games));
 
284
}
 
285
 
 
286
//stats
 
287
void Room::slot_playersDoubleClicked(const QModelIndex & index)
 
288
{
 
289
        QModelIndex translated = index;
 
290
        PlayerListing * opponent = playerListModel->playerListingFromIndex(translated);
 
291
        sendStatsRequest(*opponent);
 
292
}
 
293
 
 
294
void Room::slot_showPopup(const QPoint & iPoint)
 
295
{
 
296
        popup_item = playerView->indexAt(iPoint);
 
297
        if (popup_item != QModelIndex())
 
298
        {
 
299
                /* If we have the listing now, we don't need to look it up
 
300
                 * again later FIXME */
 
301
                QModelIndex translated = popup_item;
 
302
                popup_playerlisting = playerListModel->playerListingFromIndex(translated);
 
303
                if(popup_playerlisting->name == connection->getUsername())
 
304
                        return;
 
305
                        
 
306
        QMenu menu(playerView);
 
307
        menu.addAction(tr("Stats"), this, SLOT(slot_popupStats()));
 
308
        QAction * matchAct = new QAction(tr("Match"), 0);
 
309
        if(popup_playerlisting->info.contains("X"))
 
310
                matchAct->setEnabled(false);
 
311
        else
 
312
                connect(matchAct, SIGNAL(triggered()), this, SLOT(slot_popupMatch()));
 
313
                
 
314
        menu.addAction(matchAct);
 
315
        
 
316
                
 
317
        menu.addAction(tr("Talk"), this, SLOT(slot_popupTalk()));
 
318
        menu.addSeparator();
 
319
        if(popup_playerlisting->friendWatchType == PlayerListing::friended)
 
320
                menu.addAction(tr("Remove from Friends"), this, SLOT(slot_removeFriend()));
 
321
        else
 
322
                menu.addAction(tr("Add to Friends"), this, SLOT(slot_addFriend()));
 
323
        if(popup_playerlisting->friendWatchType == PlayerListing::watched)
 
324
                menu.addAction(tr("Remove from Watches"), this, SLOT(slot_removeWatch()));
 
325
        else
 
326
                menu.addAction(tr("Add to Watches"), this, SLOT(slot_addWatch()));
 
327
        menu.addAction(tr("Block"), this, SLOT(slot_addBlock()));
 
328
        menu.exec(playerView->mapToGlobal(iPoint));
 
329
        delete matchAct;
 
330
        }
 
331
}
 
332
 
 
333
void Room::slot_showGamesPopup(const QPoint & iPoint)
 
334
{
 
335
        if(!connection)
 
336
                return;
 
337
        if(!connection->supportsObserveOutside())
 
338
                return;
 
339
        popup_item = gamesView->indexAt(iPoint);
 
340
        if (popup_item != QModelIndex())
 
341
        {
 
342
                /* Do not give options on rooms without games */
 
343
                QModelIndex translated = popup_item;
 
344
                popup_gamelisting = gamesListModel->gameListingFromIndex(translated);
 
345
                if(popup_gamelisting->isRoomOnly)
 
346
                        return;
 
347
                QMenu menu(gamesView);
 
348
                if(preferences.observe_outside_on_doubleclick)
 
349
                {
 
350
                        menu.addAction(tr("Observe Outside"), this, SLOT(slot_popupObserveOutside()));
 
351
                        menu.addAction(tr("Join and Observe"), this, SLOT(slot_popupJoinObserve()));
 
352
                }
 
353
                else
 
354
                {
 
355
                        menu.addAction(tr("Join and Observe"), this, SLOT(slot_popupJoinObserve()));
 
356
                        menu.addAction(tr("Observe Outside"), this, SLOT(slot_popupObserveOutside()));
 
357
                }
 
358
                
 
359
                menu.exec(gamesView->mapToGlobal(iPoint));
 
360
        }
 
361
}
 
362
 
 
363
void Room::slot_addFriend(void)
 
364
{
 
365
        connection->addFriend(*popup_playerlisting);
 
366
}
 
367
 
 
368
/* This needs to call a resort or something on the list
 
369
 * if we have "friends" checked, same thing with blocked
 
370
 * if we don't, just to update that one entry FIXME */
 
371
void Room::slot_removeFriend(void)
 
372
{
 
373
        connection->removeFriend(*popup_playerlisting);
 
374
}
 
375
 
 
376
void Room::slot_addWatch(void)
 
377
{
 
378
        connection->addWatch(*popup_playerlisting);
 
379
}
 
380
 
 
381
void Room::slot_removeWatch(void)
 
382
{
 
383
        connection->removeWatch(*popup_playerlisting);
 
384
}
 
385
 
 
386
void Room::slot_addBlock(void)
 
387
{
 
388
        connection->addBlock(*popup_playerlisting);
 
389
}
 
390
 
 
391
void Room::slot_popupStats(void)
 
392
{
 
393
        /* For now, just request stats.  Later, we might open a separate window with a tab for
 
394
         * game records */
 
395
        connection->sendStatsRequest(*popup_playerlisting);
 
396
}
 
397
 
 
398
void Room::slot_popupMatch(void)
 
399
{
 
400
        connection->sendMatchInvite(*popup_playerlisting);
 
401
}
 
402
 
 
403
void Room::slot_popupTalk(void)
 
404
{
 
405
        slot_playersDoubleClicked(popup_item);
 
406
}
 
407
 
 
408
void Room::slot_popupObserveOutside(void)
 
409
{
 
410
        connection->sendObserveOutside(*popup_gamelisting);
 
411
}
 
412
 
 
413
void Room::slot_popupJoinObserve(void)
 
414
{
 
415
        connection->sendObserve(*popup_gamelisting);
 
416
}
 
417
 
 
418
//observe
 
419
void Room::slot_gamesDoubleClicked(const QModelIndex & index)
 
420
{
 
421
        QModelIndex translated = index;
 
422
        const GameListing * g = gamesListModel->gameListingFromIndex(translated);
 
423
        if(preferences.observe_outside_on_doubleclick &&
 
424
                  connection->supportsObserveOutside() && !g->isRoomOnly)
 
425
                connection->sendObserveOutside(*g);
 
426
        else
 
427
                connection->sendObserve(*g);
 
428
}
 
429
 
 
430
void Room::slot_refreshPlayers(void)
 
431
{
 
432
        //we don't have to clear the players list
 
433
        //if we're checking for existing player records
 
434
        //clearPlayerList();
 
435
        connection->sendPlayersRequest();
 
436
}
 
437
 
 
438
void Room::clearPlayerList(void)
 
439
{
 
440
        playerListModel->clearList();
 
441
        if(connection->playerTrackingByID())
 
442
        {
 
443
                qDebug("Recreating player ID Registry");
 
444
                delete playerListingIDRegistry;
 
445
                playerListingIDRegistry = new PlayerListingIDRegistry(playerListModel);
 
446
        }
 
447
        else
 
448
        {
 
449
                qDebug("Recreating player Registry");
 
450
                delete playerListingRegistry;
 
451
                playerListingRegistry = new PlayerListingRegistry(playerListModel);
 
452
        }
 
453
}
 
454
 
 
455
void Room::clearGamesList(void)
 
456
{
 
457
        gamesListModel->clearList();
 
458
        delete gameListingRegistry;
 
459
        gameListingRegistry = new GameListingRegistry(gamesListModel);
 
460
}
 
461
 
 
462
void Room::slot_refreshGames(void)
 
463
{
 
464
        /* First clear list.  There doesn't
 
465
        * seem to be a good way to update it
 
466
        * or update everything [IGS issue].  Since we're
 
467
        * getting all info again anyway... 
 
468
        * same with players and perhaps 
 
469
        * observers as well. */
 
470
        clearGamesList();
 
471
        connection->sendGamesRequest();
 
472
}
 
473
 
 
474
/* This code was taken from mainwindow_server.cpp
 
475
 * I guess it figures out which is min and which
 
476
 * is max?? */
 
477
void Room::slot_setRankSpreadView(void)
 
478
{
 
479
        QString rkMin, rkMax;
 
480
        QString r1,r2;
 
481
 
 
482
        if ((whoBox1->currentIndex() == 0) && (whoBox2->currentIndex() == 0))
 
483
        {
 
484
                rkMin = "NR";
 
485
                rkMax = "9p";
 
486
        }
 
487
 
 
488
        else if ( ((whoBox1->currentIndex() == 0) && (whoBox2->currentIndex() == 1)) ||
 
489
                ((whoBox1->currentIndex() == 1) && (whoBox2->currentIndex() == 0))  ||
 
490
                ((whoBox1->currentIndex() == 1) && (whoBox2->currentIndex() ==1)) )
 
491
        {
 
492
                rkMin = "1p";
 
493
                rkMax = "9p";
 
494
        }       
 
495
 
 
496
        else if ((whoBox1->currentIndex() == 0) && (whoBox2->currentIndex() > 1))
 
497
        {
 
498
                rkMin = whoBox2->currentText();
 
499
                rkMax = whoBox2->currentText();
 
500
        }       
 
501
 
 
502
 
 
503
        else if ((whoBox1->currentIndex() > 1) && (whoBox2->currentIndex() == 0))
 
504
        {
 
505
                rkMin = whoBox1->currentText();
 
506
                rkMax = whoBox1->currentText();
 
507
        }       
 
508
 
 
509
        else if ((whoBox1->currentIndex() > 1) && (whoBox2->currentIndex() == 1))
 
510
        {
 
511
                rkMin = whoBox1->currentText();
 
512
                rkMax = "9p";
 
513
        }       
 
514
 
 
515
        else if ((whoBox1->currentIndex() == 1) && (whoBox2->currentIndex() > 1))
 
516
        {
 
517
                rkMin = whoBox2->currentText();
 
518
                rkMax = "9p";
 
519
        }
 
520
 
 
521
 
 
522
        else if ((whoBox2->currentIndex() >= whoBox1->currentIndex() ))
 
523
        {
 
524
                rkMin = whoBox2->currentText();
 
525
                rkMax = whoBox1->currentText();
 
526
        } 
 
527
        else 
 
528
        {
 
529
                rkMin = whoBox1->currentText();
 
530
                rkMax = whoBox2->currentText();
 
531
        } 
 
532
 
 
533
        dynamic_cast<PlayerListFilter *>(playerView->getFilter())->setFilter(connection->rankToScore(rkMin), connection->rankToScore(rkMax));
 
534
        qDebug( "rank spread : %s - %s" , rkMin.toLatin1().constData() , rkMax.toLatin1().constData());
 
535
}
 
536
 
 
537
void Room::slot_showOpen(int)
 
538
{
 
539
        dynamic_cast<PlayerListFilter *>(playerView->getFilter())->setFilter(PlayerListFilter::open);
 
540
}
 
541
 
 
542
void Room::slot_showFriends(int)
 
543
{
 
544
        dynamic_cast<PlayerListFilter *>(playerView->getFilter())->setFilter(PlayerListFilter::friends);
 
545
}
 
546
 
 
547
void Room::slot_showWatches(int)
 
548
{
 
549
        dynamic_cast<PlayerListFilter *>(playerView->getFilter())->setFilter(PlayerListFilter::fans);
 
550
        dynamic_cast<GamesListFilter *>(gamesView->getFilter())->toggleWatches();
 
551
}
 
552
 
 
553
void Room::slot_editFriendsWatchesList(void)
 
554
{
 
555
        //does this crash if we do it too soon?
 
556
        FriendsListDialog * fld = new FriendsListDialog(connection);
 
557
        fld->exec();
 
558
        delete fld;             //okay?
 
559
}
 
560
 
 
561
void Room::talkOpened(Talk * d)
 
562
{
 
563
        mainwindow->talkOpened(d);
 
564
}
 
565
 
 
566
void Room::recvToggle(int type, bool val)
 
567
{
 
568
        mainwindow->slot_checkbox(type, val);
 
569
}
 
570
 
 
571
GameListing * Room::registerGameListing(GameListing * l)
 
572
{
 
573
        return gameListingRegistry->getEntry(l->number, l);
 
574
}
 
575
 
 
576
/* This appears to be unused, recvGameListing does stuff
 
577
 * with "->running" FIXME */
 
578
void Room::unRegisterGameListing(unsigned int key)
 
579
{
 
580
        gameListingRegistry->deleteEntry(key);
 
581
}
 
582
 
 
583
PlayerListing * Room::getPlayerListing(const QString & name)
 
584
{
 
585
        PlayerListing * p;
 
586
        if(!playerListingRegistry)
 
587
        {
 
588
                if(playerListingIDRegistry)
 
589
                        p = playerListingIDRegistry->getPlayerFromName(name);
 
590
                else
 
591
                {
 
592
                        qDebug("No player listing registry!");
 
593
                        return NULL;
 
594
                }
 
595
        }
 
596
        else
 
597
                p = playerListingRegistry->getEntry(name);      //note getNewEntry not defined and so returns 0 like getIfEntry
 
598
 
 
599
#ifdef FIXME
 
600
        /* this is tricky FIXME */
 
601
        if(!p)
 
602
                connection->sendStatsRequest(name);             
 
603
#endif //FIXME
 
604
        /* Should probably return & FIXME */
 
605
        return p;
 
606
}
 
607
 
 
608
PlayerListing * Room::getPlayerListing(const unsigned int id)
 
609
{
 
610
        if(!playerListingIDRegistry)    //FIXME
 
611
        {
 
612
                qDebug("No player listing registry!");
 
613
                return NULL;
 
614
        }
 
615
        PlayerListing * p = playerListingIDRegistry->getEntry(id);
 
616
        // FIXME
 
617
        /*if(!p)
 
618
                connection->sendStatsRequest(id);*/     
 
619
#ifdef PLAYERLISTING_ISSUES     
 
620
        if(!p)
 
621
                qDebug("Can't get player listing for %d", id);
 
622
#endif //PLAYERLISTING_ISSUES
 
623
        return p;
 
624
}
 
625
 
 
626
/* Here's the deal with this.  Tygem has a username and a nickname.
 
627
 * the nickname is displayed and generally present, but not always.  The username
 
628
 * seems to always be present.  At first glance, it makes sense to lookup by
 
629
 * the username since that seems how the information is stored and it seems
 
630
 * unique to username.  However, if we need to display and sort by the
 
631
 * nickname, that introduces overhead in the listviews that are slow enough
 
632
 * already.  It might be minor overhead, and it might be really ugly
 
633
 * to search through all the listings to find a particular username like
 
634
 * this, but I think its better since its done rarely.  I may regret this
 
635
 * and change it later. */
 
636
 /* FIXME don't we usually say "from" instead of "by" change this */
 
637
PlayerListing * Room::getPlayerListingByNotNickname(const QString & notnickname)
 
638
{
 
639
        PlayerListing * p;
 
640
        if(!playerListingRegistry)
 
641
        {
 
642
                qDebug("No player listing registry!");
 
643
                return NULL;
 
644
        }
 
645
        else
 
646
                p = playerListingRegistry->getPlayerFromNotNickName(notnickname);
 
647
 
 
648
        /* Should probably return & FIXME */
 
649
        return p;       
 
650
}
 
651
 
 
652
/* Remember that this and getPlayerListing do return 0.
 
653
 * getEntry functions like getIfEntry because getNewEntry
 
654
 * is not defined, since we create registry entries for
 
655
 * the games/player registries by passing them */
 
656
GameListing * Room::getGameListing(unsigned int key)
 
657
{
 
658
        GameListing * l = gameListingRegistry->getEntry(key);
 
659
        /* I'm not sure we'd ever want to automatically
 
660
         * requestGameStats.  Either the listing is on the way
 
661
         * or we request it from some other place.  The main
 
662
         * thing is we don't want to be requesting it from
 
663
         * the games listing messages every time we try to
 
664
         * get an existing listing.  But if its a problem
 
665
         * to just comment out the below two lines, then
 
666
         * we'll need a getIfGameListing as with the 
 
667
         * getIfBoardDispatch FIXME */
 
668
        //if(!l)
 
669
        //      connection->requestGameStats(key);
 
670
        return l;
 
671
}
 
672
 
 
673
/* Called from getNewEntry in BoardDispatchRegistry in networkconnection.cpp */
 
674
class BoardDispatch * Room::getNewBoardDispatch(unsigned int key)
 
675
{
 
676
        /* Oro might pass a game code rather than a number here.  But
 
677
        * the listings sometimes only have numbers.  We need to
 
678
        * look up in game stuff like moves and results by game code.
 
679
        * we don't have the number there.  But this means always
 
680
        * passing game codes to this, but then we can't use getGameListing
 
681
        * initially.  Even if we use the number on the initial board get/create
 
682
        * and the game code thereafter, assuming there aren't collisions in
 
683
        * the id spaces, we still have to alter this to be aware of the
 
684
        * ORO protocol.  Its a fucking mess. I think we better just store
 
685
        * everything by the key and have a separate lookup, code to key */
 
686
        GameListing * listing = getGameListing(key);
 
687
        if(!listing)
 
688
        {
 
689
                /* I'm not so sure about this.  FIXME We want BoardDispatch
 
690
                * to have an initial listing maybe but perhaps we should
 
691
                * alter BoardDispatch to be more adaptable in case there
 
692
                * is no listing rather than create a dummy one like this
 
693
                * and just hope it gets filled in later */
 
694
                listing = new GameListing();
 
695
                listing->number = key;
 
696
                registerGameListing(listing);
 
697
        }
 
698
        /* Look up game information to pass to board dispatch, if any 
 
699
        * ... actually that might be circular, let's NOT do that.
 
700
        * Except, we don't want to overwrite an existing listing */
 
701
 
 
702
        /*GameListing * temp_listing = new GameListing();
 
703
        temp_listing->number = key;
 
704
        listing = registerGameListing(temp_listing);
 
705
        delete temp_listing;*/
 
706
        
 
707
        return new BoardDispatch(connection, listing);
 
708
}
 
709
 
 
710
std::map<PlayerListing *, unsigned short> removed_player;
 
711
void Room::recvPlayerListing(PlayerListing * player)
 
712
{
 
713
        if(!player->online)
 
714
        {
 
715
#ifdef VIEWTESTDEBUG
 
716
                if(player->name == "REMOVEMENOTAPLAYER")
 
717
                {
 
718
                        int i;
 
719
                        delete player;
 
720
                        player = 0;
 
721
                        do
 
722
                        {
 
723
                                i = rand() % players;
 
724
                        }
 
725
                        while(!(player = playerListingIDRegistry->getIfEntry(i)));
 
726
                        player->online = false;
 
727
                }
 
728
#endif  //VIEWTESTDEBUG
 
729
                removed_player[player] = player->playing;
 
730
#ifdef PLAYERLISTING_ISSUES
 
731
                qDebug("Removing player %s %p on attached game %d", player->name.toLatin1().constData(), player, player->playing);
 
732
#endif //PLAYERLISTING_ISSUES
 
733
                /* To prevent crashes due to GameListing link to PlayerListing
 
734
                 * FIXME */
 
735
                if(player->playing)
 
736
                {
 
737
                        /* FIXME, something should clear this when games end */
 
738
                        GameListing * g = getGameListing(player->playing);
 
739
                        if(g)
 
740
                        {
 
741
                                if(g->black == player)
 
742
                                {
 
743
                                        g->black = 0;
 
744
                                        g->_black_name = player->name;
 
745
                                        g->_black_rank = player->rank;
 
746
                                }
 
747
                                else if(g->white == player)
 
748
                                {
 
749
                                        g->white = 0;
 
750
                                        g->_white_name = player->name;
 
751
                                        g->_white_rank = player->rank;
 
752
                                }
 
753
                        }
 
754
                }
 
755
                if(player->observing)
 
756
                {
 
757
                        /* FIXME remove this check, room_list should be sufficient */
 
758
                        /* FIXME, something should clear this when games end */
 
759
                        BoardDispatch * b = connection->getIfBoardDispatch(player->observing);
 
760
                        if(b)
 
761
                        {
 
762
#ifdef PLAYERLISTING_ISSUES
 
763
                                qDebug("Removing player %s on observing game %d", player->name.toLatin1().constData(), player->observing);
 
764
#endif //PLAYERLISTING_ISSUES
 
765
                                b->recvObserver(player, false);
 
766
                        }
 
767
                        if(player->dialog_opened)
 
768
                                connection->closeTalk(*player);
 
769
                }
 
770
                std::vector<unsigned short>::iterator room_listit = player->room_list.begin();
 
771
                while(room_listit != player->room_list.end())
 
772
                {
 
773
                        BoardDispatch * boarddispatch = connection->getIfBoardDispatch(*room_listit);
 
774
                        if(boarddispatch)
 
775
                                boarddispatch->recvObserver(player, false);
 
776
                        else
 
777
                                player->room_list.erase(room_listit);
 
778
                        room_listit = player->room_list.begin();
 
779
                }
 
780
                if(player->friendWatchType != PlayerListing::none)
 
781
                        connection->getAndSetFriendWatchType(*player);  //removes
 
782
        }
 
783
        PlayerListing * registered_player = 0;
 
784
        if(player->online)
 
785
                connection->getAndSetFriendWatchType(*player);
 
786
        if(playerListingIDRegistry)
 
787
        {
 
788
                if(player->online)
 
789
                        registered_player = playerListingIDRegistry->getEntry(player->id, player);
 
790
                else
 
791
                        playerListingIDRegistry->deleteEntry(player->id);       
 
792
        }
 
793
        else
 
794
        {
 
795
                if(player->online)
 
796
                        registered_player = playerListingRegistry->getEntry(player->name, player);
 
797
                else
 
798
                        playerListingRegistry->deleteEntry(player->name);
 
799
        }
 
800
        
 
801
        if(registered_player && player->online)
 
802
        {
 
803
                /* FIXME consider changing name of getEntry with the object?
 
804
                 * so that its more clear that it returns a new stored object
 
805
                 * based on the one passed. (i.e., looking it up if
 
806
                 * alread there)*/
 
807
                if(player->dialog_opened)
 
808
                {
 
809
                        Talk * t = connection->getIfTalk(*player);
 
810
                        if(t)
 
811
                                t->updatePlayerListing();
 
812
                        else
 
813
                                qDebug("dialog_opened flag set but no talk dialog");
 
814
                }
 
815
        }
 
816
        
 
817
        /* This is just for those listing bugs... its weird...remove it
 
818
         * soon */
 
819
        if(registered_player && player->online)
 
820
        {
 
821
                std::map<PlayerListing *, unsigned short>::iterator it;
 
822
                it = removed_player.find(registered_player);
 
823
                if(it != removed_player.end())
 
824
                        removed_player.erase(it);
 
825
        }
 
826
        updateRoomStats();      //in case we lost one or added one
 
827
}
 
828
 
 
829
/* These two may want to check that they are the mainwindowroom or the
 
830
 * default room or whatever.  But its not necessary to have a whole
 
831
 * other subclass for mainwindowrooms because they both need some
 
832
 * kind of ui.  It would be more effective to do something with the
 
833
 * ui classes */
 
834
void Room::recvExtPlayerListing(class PlayerListing * player)
 
835
{
 
836
        mainwindow->slot_statsPlayer(player);
 
837
}
 
838
 
 
839
void Room::updatePlayerListing(class PlayerListing & player)
 
840
{
 
841
        playerListModel->updateListing(&player);
 
842
}
 
843
 
 
844
void Room::recvGameListing(GameListing * game)
 
845
{
 
846
        unsigned int key;
 
847
        /* This WAS iffy, we WERE using the other ID registry's
 
848
         * existence to indicate an ORO connection in order
 
849
         * to use a different key.  Ugly.  Once this works, 
 
850
         * we need to find a way to hide this within the
 
851
         * connection.  It shouldn't be running around here */
 
852
        /* FIXME, turns out that game_number is better for listings
 
853
         * even if we need the code for joining, etc.  Its unique
 
854
         * anyway, so who cares */
 
855
        //if(playerListingIDRegistry)
 
856
        //      key = game->game_code;
 
857
        //else
 
858
                key = game->number;
 
859
        
 
860
        if(game->running)
 
861
        {
 
862
                game = gameListingRegistry->getEntry(key, game);
 
863
                connection->checkGameWatched(*game);
 
864
        }
 
865
        else
 
866
                gameListingRegistry->deleteEntry(key);
 
867
        updateRoomStats();      //in case we lost one or added one
 
868
}
 
869
 
 
870
/* This isn't really just a "sendStats" function anymore, that's
 
871
 * done by the talk object I think and... well its ugly, responsibilities
 
872
 * are crossed, etc.. FIXME */
 
873
void Room::sendStatsRequest(PlayerListing & opponent)
 
874
{
 
875
        Talk * talk;
 
876
        /* Whenever a talk window is opened, we want stats.  This
 
877
         * means its easier to create the talk window and let it
 
878
         * always create stats, then send out stats messages
 
879
         * that generate talk windows */
 
880
        /* This is a little weird now...almost like we're just asking
 
881
         * for an update on the references */
 
882
        talk = connection->getTalk(opponent);
 
883
        //connection->sendStatsRequest(opponent);
 
884
        /* This is really only for ORO, and let's see if it works but... */
 
885
        if(talk)
 
886
                talk->updatePlayerListing();
 
887
}
 
888
 
 
889
/*** GameListing/PlayerListing Registry functions ***/
 
890
 
 
891
void GameListingRegistry::initEntry(GameListing * l)
 
892
{
 
893
        gamesListModel->updateListing(l);
 
894
}
 
895
 
 
896
void GameListingRegistry::onErase(GameListing * l)
 
897
{
 
898
        gamesListModel->removeListing(l);
 
899
        delete l->gameData;             //used by ORO
 
900
        delete l;
 
901
}
 
902
 
 
903
void PlayerListingRegistry::initEntry(PlayerListing * l)
 
904
{
 
905
        playerListModel->updateListing(l);
 
906
}
 
907
 
 
908
void PlayerListingRegistry::onErase(PlayerListing * l)
 
909
{
 
910
        playerListModel->removeListing(l);
 
911
        delete l;
 
912
}
 
913
 
 
914
PlayerListing * PlayerListingRegistry::getPlayerFromNotNickName(const QString & notnickname)
 
915
{
 
916
        std::map<QString, PlayerListing *>::iterator i;
 
917
        for(i = getStorage()->begin(); i != getStorage()->end(); i++)
 
918
        {
 
919
                if(i->second->notnickname == notnickname)
 
920
                        return (i->second);
 
921
        }
 
922
        return NULL;
 
923
}
 
924
 
 
925
void PlayerListingIDRegistry::initEntry(PlayerListing * l)
 
926
{
 
927
        playerListModel->updateListing(l);
 
928
}
 
929
 
 
930
void PlayerListingIDRegistry::onErase(PlayerListing * l)
 
931
{
 
932
        playerListModel->removeListing(l);
 
933
        delete l;
 
934
}
 
935
 
 
936
PlayerListing * PlayerListingIDRegistry::getPlayerFromName(const QString & name)
 
937
{
 
938
        std::map<unsigned int, PlayerListing *>::iterator i;
 
939
        for(i = getStorage()->begin(); i != getStorage()->end(); i++)
 
940
        {
 
941
                if(i->second->name == name)
 
942
                        return (i->second);
 
943
        }
 
944
        return NULL;
 
945
}