1 /*
2 * Hedgewars, a free turn based strategy game
3 * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
4 *
5 * This program 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; version 2 of the License
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <QVBoxLayout>
20 #include <QHBoxLayout>
21 #include <QGridLayout>
22 #include <QPushButton>
23 #include <QComboBox>
24 #include <QLabel>
25 #include <QLineEdit>
26 #include <QMessageBox>
27 #include <QHeaderView>
28 #include <QGroupBox>
29 #include <QMenu>
30 #include <QDebug>
31 #include <QSplitter>
32 #include <QSettings>
33
34 #include <QSortFilterProxyModel>
35
36 #include "roomslistmodel.h"
37
38 #include "gameSchemeModel.h"
39 #include "hwconsts.h"
40 #include "chatwidget.h"
41 #include "roomnameprompt.h"
42 #include "lineeditcursor.h"
43 #include "pageroomslist.h"
44
moveDown()45 void RoomTableView::moveDown()
46 {
47 setCurrentIndex(moveCursor(QAbstractItemView::MoveDown, Qt::NoModifier));
48 }
49
moveUp()50 void RoomTableView::moveUp()
51 {
52 setCurrentIndex(moveCursor(QAbstractItemView::MoveUp, Qt::NoModifier));
53 }
54
bodyLayoutDefinition()55 QLayout * PageRoomsList::bodyLayoutDefinition()
56 {
57 // TODO move stylesheet stuff into css/qt.css
58
59 QVBoxLayout * pageLayout = new QVBoxLayout();
60 pageLayout->setSpacing(0);
61
62 QGridLayout * topLayout = new QGridLayout();
63 topLayout->setSpacing(0);
64 pageLayout->addLayout(topLayout, 0);
65
66 // State button
67
68 QPushButton * btnState = new QPushButton(tr("Room state"));
69 btnState->setStyleSheet("QPushButton { background-color: #F6CB1C; border-color: #F6CB1C; color: #130F2A; padding: 1px 3px 3px 3px; margin: 0px; border-bottom: none; border-radius: 0px; border-top-left-radius: 10px; } QPushButton:hover { background-color: #FFEB3C; border-color: #F6CB1C; color: #000000 } QPushButton:pressed { background-color: #FFEB3C; border-color: #F6CB1C; color: #000000; }");
70 btnState->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
71
72 // State menu
73
74 QMenu * stateMenu = new QMenu(btnState);
75 showGamesInLobby = new QAction(QAction::tr("Show games in lobby"), stateMenu);
76 showGamesInLobby->setCheckable(true);
77 showGamesInLobby->setChecked(true);
78 showGamesInProgress = new QAction(QAction::tr("Show games in-progress"), stateMenu);
79 showGamesInProgress->setCheckable(true);
80 showGamesInProgress->setChecked(true);
81 showPassword = new QAction(QAction::tr("Show password protected"), stateMenu);
82 showPassword->setCheckable(true);
83 showPassword->setChecked(true);
84 showJoinRestricted = new QAction(QAction::tr("Show join restricted"), stateMenu);
85 showJoinRestricted->setCheckable(true);
86 showJoinRestricted->setChecked(true);
87 stateMenu->addAction(showGamesInLobby);
88 stateMenu->addAction(showGamesInProgress);
89 stateMenu->addAction(showPassword);
90 stateMenu->addAction(showJoinRestricted);
91 btnState->setMenu(stateMenu);
92
93 // Help/prompt message at top
94 QLabel * lblDesc = new QLabel(tr("Search for a room:"));
95 lblDesc->setObjectName("lblDesc");
96 lblDesc->setStyleSheet("#lblDesc { color: #130F2A; background: #F6CB1C; border: solid 4px #F6CB1C; padding: 5px 10px 3px 6px;}");
97 lblDesc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
98 lblDesc->setFixedHeight(24);
99 lblDesc->setMinimumWidth(0);
100
101 // Search text box
102 QWidget * searchContainer = new QWidget();
103 searchContainer->setFixedHeight(24);
104 searchContainer->setObjectName("searchContainer");
105 searchContainer->setStyleSheet("#searchContainer { background: #F6CB1C; border-top-right-radius: 10px; padding: 3px; }");
106 searchContainer->setFixedWidth(200);
107 searchText = new LineEditCursor(searchContainer);
108 searchText->setFixedWidth(200);
109 searchText->setMaxLength(60);
110 searchText->setFixedHeight(22);
111 searchText->setStyleSheet("LineEditCursor { border-width: 0px; border-radius: 6px; margin-top: 3px; margin-right: 3px; padding-left: 4px; padding-bottom: 2px; background-color: rgb(23, 11, 54); } LineEditCursor:hover, LineEditCursor:focus { background-color: rgb(13, 5, 68); }");
112
113 // Corner widget
114 QLabel * corner = new QLabel();
115 corner->setPixmap(QPixmap(QString::fromUtf8(":/res/inverse-corner-bl.png")));
116 corner->setFixedSize(10, 10);
117
118 const QIcon& lp = QIcon(":/res/new.png");
119 //QSize sz = lp.actualSize(QSize(65535, 65535));
120 BtnCreate = new QPushButton();
121 BtnCreate->setText(tr("Create room"));
122 BtnCreate->setIcon(lp);
123 BtnCreate->setStyleSheet("padding: 4px 8px; margin-bottom: 6px;");
124
125 BtnJoin = new QPushButton(tr("Join room"));
126 BtnJoin->setStyleSheet("padding: 4px 8px; margin-bottom: 6px; margin-left: 6px;");
127 BtnJoin->setEnabled(false);
128
129 // Add widgets to top layout
130 topLayout->addWidget(btnState, 1, 0);
131 topLayout->addWidget(lblDesc, 1, 1);
132 topLayout->addWidget(searchContainer, 1, 2);
133 topLayout->addWidget(corner, 1, 3, Qt::AlignBottom);
134 topLayout->addWidget(BtnCreate, 0, 5, 2, 1);
135 topLayout->addWidget(BtnJoin, 0, 6, 2, 1);
136
137 // Top layout stretch
138 topLayout->setRowStretch(0, 1);
139 topLayout->setRowStretch(1, 0);
140 topLayout->setColumnStretch(4, 1);
141
142 // Rooms list and chat with splitter
143 m_splitter = new QSplitter();
144 m_splitter->setChildrenCollapsible(false);
145 pageLayout->addWidget(m_splitter, 100);
146
147 // Room list
148 QWidget * roomsListWidget = new QWidget(this);
149 m_splitter->setOrientation(Qt::Vertical);
150 m_splitter->addWidget(roomsListWidget);
151
152 QVBoxLayout * roomsLayout = new QVBoxLayout(roomsListWidget);
153 roomsLayout->setMargin(0);
154
155 roomsList = new RoomTableView(this);
156 roomsList->setSelectionBehavior(QAbstractItemView::SelectRows);
157 roomsList->verticalHeader()->setVisible(false);
158 roomsList->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
159 roomsList->horizontalHeader()->stretchLastSection();
160 roomsList->setAlternatingRowColors(true);
161 roomsList->setShowGrid(false);
162 roomsList->setSelectionMode(QAbstractItemView::SingleSelection);
163 roomsList->setStyleSheet("QTableView { border-top-left-radius: 0px; }");
164 roomsList->setFocusPolicy(Qt::NoFocus);
165 roomsLayout->addWidget(roomsList, 200);
166
167 // Lobby chat
168
169 chatWidget = new HWChatWidget(this, false);
170 m_splitter->addWidget(chatWidget);
171
172 return pageLayout;
173 }
174
footerLayoutDefinition()175 QLayout * PageRoomsList::footerLayoutDefinition()
176 {
177 QHBoxLayout * bottomLayout = new QHBoxLayout();
178
179 BtnAdmin = addButton(tr("Admin features"), bottomLayout, 0, false, Qt::AlignBottom);
180 BtnAdmin->setMinimumSize(180, 50);
181 BtnAdmin->setStyleSheet("padding: 5px 10px");
182 BtnAdmin->setWhatsThis(tr("Open server administration page"));
183
184 return bottomLayout;
185 }
186
connectSignals()187 void PageRoomsList::connectSignals()
188 {
189 connect(chatWidget, SIGNAL(nickCountUpdate(const int)), this, SLOT(updateNickCounter(const int)));
190
191 connect(BtnCreate, SIGNAL(clicked()), this, SLOT(onCreateClick()));
192 connect(BtnJoin, SIGNAL(clicked()), this, SLOT(onJoinClick()));
193 connect(searchText, SIGNAL(moveUp()), this, SLOT(moveSelectionUp()));
194 connect(searchText, SIGNAL(moveDown()), this, SLOT(moveSelectionDown()));
195 connect(searchText, SIGNAL(returnPressed()), this, SLOT(onJoinClick()));
196 connect(roomsList, SIGNAL(doubleClicked (const QModelIndex &)), this, SLOT(onJoinClick()));
197 connect(roomsList, SIGNAL(clicked (const QModelIndex &)), searchText, SLOT(setFocus()));
198 connect(showGamesInLobby, SIGNAL(triggered()), this, SLOT(onFilterChanged()));
199 connect(showGamesInProgress, SIGNAL(triggered()), this, SLOT(onFilterChanged()));
200 connect(showPassword, SIGNAL(triggered()), this, SLOT(onFilterChanged()));
201 connect(showJoinRestricted, SIGNAL(triggered()), this, SLOT(onFilterChanged()));
202 connect(searchText, SIGNAL(textChanged (const QString &)), this, SLOT(onFilterChanged()));
203 connect(this, SIGNAL(askJoinConfirmation (const QString &)), this, SLOT(onJoinConfirmation(const QString &)), Qt::QueuedConnection);
204
205 // Set focus on search box
206 connect(this, SIGNAL(pageEnter()), searchText, SLOT(setFocus()));
207
208 // sorting
209 connect(roomsList->horizontalHeader(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)),
210 this, SLOT(onSortIndicatorChanged(int, Qt::SortOrder)));
211 }
212
moveSelectionUp()213 void PageRoomsList::moveSelectionUp()
214 {
215 roomsList->moveUp();
216 }
217
moveSelectionDown()218 void PageRoomsList::moveSelectionDown()
219 {
220 roomsList->moveDown();
221 }
222
roomSelectionChanged(const QModelIndex & current,const QModelIndex & previous)223 void PageRoomsList::roomSelectionChanged(const QModelIndex & current, const QModelIndex & previous)
224 {
225 Q_UNUSED(previous);
226
227 BtnJoin->setEnabled(current.isValid());
228 }
229
PageRoomsList(QWidget * parent)230 PageRoomsList::PageRoomsList(QWidget* parent) :
231 AbstractPage(parent)
232 {
233 roomsModel = NULL;
234 stateFilteredModel = NULL;
235
236 initPage();
237 }
238
239
displayError(const QString & message)240 void PageRoomsList::displayError(const QString & message)
241 {
242 chatWidget->displayError(message);
243 }
244
245
displayNotice(const QString & message)246 void PageRoomsList::displayNotice(const QString & message)
247 {
248 chatWidget->displayNotice(message);
249 }
250
displayWarning(const QString & message)251 void PageRoomsList::displayWarning(const QString & message)
252 {
253 chatWidget->displayWarning(message);
254 }
255
256
setAdmin(bool flag)257 void PageRoomsList::setAdmin(bool flag)
258 {
259 BtnAdmin->setVisible(flag);
260 }
261
262 /*
263 void PageRoomsList::setRoomsList(const QStringList & list)
264 {
265 QBrush red(QColor(255, 0, 0));
266 QBrush orange(QColor(127, 127, 0));
267 QBrush yellow(QColor(255, 255, 0));
268 QBrush green(QColor(0, 255, 0));
269
270 listFromServer = list;
271
272 QString selection = "";
273
274 if(QTableWidgetItem *item = roomsList->item(roomsList->currentRow(), 0))
275 selection = item->text();
276
277 roomsList->clear();
278 roomsList->setColumnCount(7);
279 roomsList->setHorizontalHeaderLabels(
280
281 );
282
283 // set minimum sizes
284 // roomsList->horizontalHeader()->resizeSection(0, 200);
285 // roomsList->horizontalHeader()->resizeSection(1, 50);
286 // roomsList->horizontalHeader()->resizeSection(2, 50);
287 // roomsList->horizontalHeader()->resizeSection(3, 100);
288 // roomsList->horizontalHeader()->resizeSection(4, 100);
289 // roomsList->horizontalHeader()->resizeSection(5, 100);
290 // roomsList->horizontalHeader()->resizeSection(6, 100);
291
292 // set resize modes
293 // roomsList->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
294
295 bool gameCanBeJoined = true;
296
297 if (list.size() % 8)
298 return;
299
300 roomsList->setRowCount(list.size() / 8);
301 for(int i = 0, r = 0; i < list.size(); i += 8, r++)
302 {
303 // if we are joining a game
304 // TODO: Should NOT be done here
305 if (gameInLobby)
306 {
307 if (gameInLobbyName == list[i + 1])
308 {
309 gameCanBeJoined = list[i].compare("True");
310 }
311 }
312
313 // check filter settings
314 #define NO_FILTER_MATCH roomsList->setRowCount(roomsList->rowCount() - 1); --r; continue
315
316 if (list[i].compare("True") && CBState->currentIndex() == 2)
317 {
318 NO_FILTER_MATCH;
319 }
320 if (list[i].compare("False") && CBState->currentIndex() == 1)
321 {
322 NO_FILTER_MATCH;
323 }
324 if (CBRules->currentIndex() != 0 && list[i + 6].compare(CBRules->currentText()))
325 {
326 NO_FILTER_MATCH;
327 }
328 if (CBWeapons->currentIndex() != 0 && list[i + 7].compare(CBWeapons->currentText()))
329 {
330 NO_FILTER_MATCH;
331 }
332 bool found = list[i + 1].contains(searchText->text(), Qt::CaseInsensitive);
333 if (!found)
334 {
335 for (int a = 4; a <= 7; ++a)
336 {
337 QString compString = list[i + a];
338 if (a == 5 && compString == "+rnd+")
339 {
340 compString = "Random Map";
341 }
342 else if (a == 5 && compString == "+maze+")
343 {
344 compString = "Random Maze";
345 }
346 else if (a == 5 && compString == "+drawn+")
347 {
348 compString = "Drawn Map";
349 }
350 if (compString.contains(searchText->text(), Qt::CaseInsensitive))
351 {
352 found = true;
353 break;
354 }
355 }
356 }
357 if (!searchText->text().isEmpty() && !found)
358 {
359 NO_FILTER_MATCH;
360 }
361
362 QTableWidgetItem * item;
363 item = new QTableWidgetItem(list[i + 1]); // room name
364 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
365
366 // pick appropriate room icon and tooltip (game in progress yes/no; later maybe locked rooms etc.)
367 if(list[i].compare("True"))
368 {
369 item->setIcon(QIcon(":/res/iconTime.png"));// game is in lobby
370 item->setToolTip(tr("Waiting..."));
371 item->setWhatsThis(tr("This game is in lobby: you may join and start playing once the game starts."));
372 }
373 else
374 {
375 item->setIcon(QIcon(":/res/iconDamage.png"));// game has started
376 item->setToolTip(tr("In progress..."));
377 item->setWhatsThis(tr("This game is in progress: you may join and spectate now but you'll have to wait for the game to end to start playing."));
378 }
379
380 roomsList->setItem(r, 0, item);
381
382 item = new QTableWidgetItem(list[i + 2]); // number of clients
383 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
384 item->setTextAlignment(Qt::AlignCenter);
385 item->setWhatsThis(tr("There are %1 clients connected to this room.", "", list[i + 2].toInt()).arg(list[i + 2]));
386 roomsList->setItem(r, 1, item);
387
388 item = new QTableWidgetItem(list[i + 3]); // number of teams
389 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
390 item->setTextAlignment(Qt::AlignCenter);
391 item->setWhatsThis(tr("There are %1 teams participating in this room.", "", list[i + 3].toInt()).arg(list[i + 3]));
392 //Should we highlight "full" games? Might get misinterpreted
393 //if(list[i + 3].toInt() >= cMaxTeams)
394 // item->setForeground(red);
395 roomsList->setItem(r, 2, item);
396
397 item = new QTableWidgetItem(list[i + 4].left(15)); // name of host
398 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
399 item->setWhatsThis(tr("%1 is the host. He may adjust settings and start the game.").arg(list[i + 4]));
400 roomsList->setItem(r, 3, item);
401
402 if(list[i + 5] == "+rnd+")
403 {
404 item = new QTableWidgetItem(tr("Random Map")); // selected map (is randomized)
405 // FIXME - need real icons. Disabling until then
406 // item->setIcon(QIcon(":/res/mapRandom.png"));
407 }
408 else if (list[i+5] == "+maze+")
409 {
410 item = new QTableWidgetItem(tr("Random Maze"));
411 // FIXME - need real icons. Disabling until then
412 // item->setIcon(QIcon(":/res/mapMaze.png"));
413 }
414 else
415 {
416 item = new QTableWidgetItem(list[i + 5]); // selected map
417
418 // check to see if we've got this map
419 // not perfect but a start
420 if(!mapList->contains(list[i + 5]))
421 {
422 item->setForeground(red);
423 item->setIcon(QIcon(":/res/mapMissing.png"));
424 }
425 else
426 {
427 // todo: mission icon?
428 // FIXME - need real icons. Disabling until then
429 // item->setIcon(QIcon(":/res/mapCustom.png"));
430 }
431 }
432
433 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
434 item->setWhatsThis(tr("Games may be played on precreated or randomized maps."));
435 roomsList->setItem(r, 4, item);
436
437 item = new QTableWidgetItem(list[i + 6].left(24)); // selected game scheme
438 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
439 item->setWhatsThis(tr("The Game Scheme defines general options and preferences like Round Time, Sudden Death or Vampirism."));
440 roomsList->setItem(r, 5, item);
441
442 item = new QTableWidgetItem(list[i + 7].left(24)); // selected weapon scheme
443 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
444 item->setWhatsThis(tr("The Weapon Scheme defines available weapons and their ammunition count."));
445 roomsList->setItem(r, 6, item);
446
447 if(!list[i + 1].compare(selection) && !selection.isEmpty())
448 roomsList->selectionModel()->setCurrentIndex(roomsList->model()->index(r, 0), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
449 }
450
451 roomsList->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
452 roomsList->horizontalHeader()->setResizeMode(1, QHeaderView::ResizeToContents);
453 roomsList->horizontalHeader()->setResizeMode(2, QHeaderView::ResizeToContents);
454 roomsList->horizontalHeader()->setResizeMode(3, QHeaderView::ResizeToContents);
455 roomsList->horizontalHeader()->setResizeMode(4, QHeaderView::ResizeToContents);
456 roomsList->horizontalHeader()->setResizeMode(5, QHeaderView::ResizeToContents);
457 roomsList->horizontalHeader()->setResizeMode(6, QHeaderView::ResizeToContents);
458
459 // TODO: Should NOT be done here
460 if (gameInLobby)
461 {
462 gameInLobby = false;
463 if (gameCanBeJoined)
464 {
465 emit askForJoinRoom(gameInLobbyName);
466 }
467 else
468 {
469 emit askJoinConfirmation(gameInLobbyName);
470 }
471 }
472
473 // roomsList->resizeColumnsToContents();
474 }
475 */
476
onCreateClick()477 void PageRoomsList::onCreateClick()
478 {
479 RoomNamePrompt prompt(this, m_gameSettings->value("frontend/lastroomname", QString()).toString());
480 if(prompt.exec())
481 onRoomNameChosen(prompt.getRoomName(), prompt.getPassword());
482 }
483
onRoomNameChosen(const QString & roomName,const QString & password)484 void PageRoomsList::onRoomNameChosen(const QString & roomName, const QString & password)
485 {
486 if (!roomName.trimmed().isEmpty())
487 {
488 m_gameSettings->setValue("frontend/lastroomname", roomName);
489 emit askForCreateRoom(roomName, password);
490 }
491 else
492 {
493 onCreateClick();
494 }
495 }
496
onJoinClick()497 void PageRoomsList::onJoinClick()
498 {
499 QModelIndexList mdl = roomsList->selectionModel()->selectedRows();
500
501 if(mdl.size() != 1)
502 {
503 QMessageBox roomNameMsg(this);
504 roomNameMsg.setIcon(QMessageBox::Warning);
505 roomNameMsg.setWindowTitle(QMessageBox::tr("Room Name - Error"));
506 roomNameMsg.setText(QMessageBox::tr("Please select room from the list"));
507 roomNameMsg.setTextFormat(Qt::PlainText);
508 roomNameMsg.setWindowModality(Qt::WindowModal);
509 roomNameMsg.exec();
510 return;
511 }
512
513 bool gameInLobby = roomsList->model()->index(mdl[0].row(), 0).data().toString().compare("True");
514 QString roomName = roomsList->model()->index(mdl[0].row(), 1).data().toString();
515
516 if (!gameInLobby)
517 emit askJoinConfirmation(roomName);
518 else
519 emit askForJoinRoom(roomName, QString());
520 }
521
onRefreshClick()522 void PageRoomsList::onRefreshClick()
523 {
524 emit askForRoomList();
525 }
526
onJoinConfirmation(const QString & room)527 void PageRoomsList::onJoinConfirmation(const QString & room)
528 {
529
530 QMessageBox reallyJoinMsg(this);
531 reallyJoinMsg.setIcon(QMessageBox::Question);
532 reallyJoinMsg.setWindowTitle(QMessageBox::tr("Room Name - Are you sure?"));
533 reallyJoinMsg.setText(QMessageBox::tr("The game you are trying to join has started.\nDo you still want to join the room?"));
534 reallyJoinMsg.setTextFormat(Qt::PlainText);
535 reallyJoinMsg.setWindowModality(Qt::WindowModal);
536 reallyJoinMsg.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
537
538 if (reallyJoinMsg.exec() == QMessageBox::Ok)
539 {
540 emit askForJoinRoom(room, QString());
541 }
542 }
543
updateNickCounter(int cnt)544 void PageRoomsList::updateNickCounter(int cnt)
545 {
546 setDefaultDescription(tr("%1 players online", 0, cnt).arg(cnt));
547 }
548
setUser(const QString & nickname)549 void PageRoomsList::setUser(const QString & nickname)
550 {
551 chatWidget->setUser(nickname);
552 }
553
setModel(RoomsListModel * model)554 void PageRoomsList::setModel(RoomsListModel * model)
555 {
556 // filter chain:
557 // model -> stateFilteredModel -> schemeFilteredModel ->
558 // -> weaponsFilteredModel -> roomsModel (search filter+sorting)
559
560 if (roomsModel == NULL)
561 {
562 roomsModel = new QSortFilterProxyModel(this);
563 roomsModel->setDynamicSortFilter(true);
564 roomsModel->setSortCaseSensitivity(Qt::CaseInsensitive);
565 roomsModel->sort(RoomsListModel::StateColumn, Qt::AscendingOrder);
566
567 stateFilteredModel = new QSortFilterProxyModel(this);
568
569 stateFilteredModel->setDynamicSortFilter(true);
570
571 roomsModel->setFilterKeyColumn(-1); // search in all columns
572 stateFilteredModel->setFilterKeyColumn(RoomsListModel::StateColumn);
573
574 roomsModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
575
576 roomsModel->setSourceModel(stateFilteredModel);
577
578 // let the table view display the last model in the filter chain
579 roomsList->setModel(roomsModel);
580
581 // When the data changes
582 connect(roomsModel, SIGNAL(layoutChanged()), roomsList, SLOT(repaint()));
583
584 // When a selection changes
585 connect(roomsList->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(roomSelectionChanged(const QModelIndex &, const QModelIndex &)));
586 }
587
588 stateFilteredModel->setSourceModel(model);
589
590 QHeaderView * h = roomsList->horizontalHeader();
591
592 h->setSortIndicatorShown(true);
593 h->setSortIndicator(RoomsListModel::StateColumn, Qt::AscendingOrder);
594 h->setSectionResizeMode(RoomsListModel::NameColumn, QHeaderView::Stretch);
595
596 h->resizeSection(RoomsListModel::PlayerCountColumn, 32);
597 h->resizeSection(RoomsListModel::TeamCountColumn, 32);
598 h->resizeSection(RoomsListModel::OwnerColumn, 100);
599 h->resizeSection(RoomsListModel::MapColumn, 100);
600 h->resizeSection(RoomsListModel::SchemeColumn, 100);
601 h->resizeSection(RoomsListModel::WeaponsColumn, 100);
602
603 // hide column used for filtering
604 roomsList->hideColumn(RoomsListModel::StateColumn);
605
606 roomsList->repaint();
607 }
608
609
onSortIndicatorChanged(int logicalIndex,Qt::SortOrder order)610 void PageRoomsList::onSortIndicatorChanged(int logicalIndex, Qt::SortOrder order)
611 {
612 if (roomsModel == NULL)
613 return;
614
615 if (logicalIndex == 0)
616 {
617 roomsModel->sort(0, Qt::AscendingOrder);
618 return;
619 }
620
621 // three state sorting: asc -> dsc -> default (by room state)
622 if ((order == Qt::AscendingOrder) && (logicalIndex == roomsModel->sortColumn()))
623 roomsList->horizontalHeader()->setSortIndicator(
624 RoomsListModel::StateColumn, Qt::AscendingOrder);
625 else
626 roomsModel->sort(logicalIndex, order);
627 }
628
629
onFilterChanged()630 void PageRoomsList::onFilterChanged()
631 {
632 if (roomsModel == NULL)
633 return;
634
635 roomsModel->setFilterFixedString(searchText->text());
636
637 bool stateLobby = showGamesInLobby->isChecked();
638 bool stateProgress = showGamesInProgress->isChecked();
639 bool statePassword = showPassword->isChecked();
640 bool stateJoinRestricted = showJoinRestricted->isChecked();
641
642 QString filter;
643 if (!stateLobby && !stateProgress)
644 filter = "O_o";
645 else if (stateLobby && stateProgress && statePassword && stateJoinRestricted)
646 filter = "";
647 else
648 {
649 QString exclude = "[^";
650 if (!stateProgress) exclude += "g";
651 if (!statePassword) exclude += "p";
652 if (!stateJoinRestricted) exclude += "j";
653 exclude += "]*";
654 if (stateProgress && statePassword && stateJoinRestricted) exclude = ".*";
655 filter = "^" + exclude;
656 if (!stateLobby) filter += "g" + exclude;
657 filter += "$";
658 }
659 //qDebug() << filter;
660
661 stateFilteredModel->setFilterRegExp(filter);
662 }
663
setSettings(QSettings * settings)664 void PageRoomsList::setSettings(QSettings *settings)
665 {
666 m_gameSettings = settings;
667 }
668