From 80277ff573c5c4adf5bf81bf3ce52ecac7172a8f Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sun, 2 Jan 2011 16:13:07 +0100 Subject: [PATCH] rooms work mostly --- cockatrice/cockatrice.pro | 6 +- cockatrice/src/abstractclient.cpp | 14 +- cockatrice/src/abstractclient.h | 11 +- cockatrice/src/dlg_creategame.cpp | 5 +- cockatrice/src/dlg_creategame.h | 3 +- cockatrice/src/tab_chatchannel.cpp | 118 ---------- cockatrice/src/tab_chatchannel.h | 47 ---- cockatrice/src/tab_room.cpp | 243 ++++++++++++++++++++ cockatrice/src/tab_room.h | 86 +++++++ cockatrice/src/tab_server.cpp | 352 ++++++++--------------------- cockatrice/src/tab_server.h | 85 ++----- cockatrice/src/tab_supervisor.cpp | 38 ++-- cockatrice/src/tab_supervisor.h | 13 +- cockatrice/src/userlist.cpp | 93 ++++++++ cockatrice/src/userlist.h | 35 +++ cockatrice/src/window_main.cpp | 4 +- common/protocol.cpp | 9 + common/protocol.h | 10 + common/protocol_datastructures.cpp | 49 ++-- common/protocol_datastructures.h | 33 +-- common/server_protocolhandler.cpp | 10 +- common/server_room.cpp | 21 +- common/server_room.h | 4 +- servatrice/src/servatrice.cpp | 12 +- servatrice/src/servatrice.h | 1 + 25 files changed, 726 insertions(+), 576 deletions(-) delete mode 100644 cockatrice/src/tab_chatchannel.cpp delete mode 100644 cockatrice/src/tab_chatchannel.h create mode 100644 cockatrice/src/tab_room.cpp create mode 100644 cockatrice/src/tab_room.h create mode 100644 cockatrice/src/userlist.cpp create mode 100644 cockatrice/src/userlist.h diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index 8d32ed68..330f612c 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -52,11 +52,12 @@ HEADERS += src/counter.h \ src/arrowtarget.h \ src/tab.h \ src/tab_server.h \ - src/tab_chatchannel.h \ + src/tab_room.h \ src/tab_message.h \ src/tab_game.h \ src/tab_deck_storage.h \ src/tab_supervisor.h \ + src/userlist.h \ src/remotedecklist_treewidget.h \ src/deckview.h \ src/playerlistwidget.h \ @@ -130,11 +131,12 @@ SOURCES += src/counter.cpp \ src/arrowitem.cpp \ src/arrowtarget.cpp \ src/tab_server.cpp \ - src/tab_chatchannel.cpp \ + src/tab_room.cpp \ src/tab_message.cpp \ src/tab_game.cpp \ src/tab_deck_storage.cpp \ src/tab_supervisor.cpp \ + src/userlist.cpp \ src/remotedecklist_treewidget.cpp \ src/deckview.cpp \ src/playerlistwidget.cpp \ diff --git a/cockatrice/src/abstractclient.cpp b/cockatrice/src/abstractclient.cpp index 924c9617..627f6ed6 100644 --- a/cockatrice/src/abstractclient.cpp +++ b/cockatrice/src/abstractclient.cpp @@ -32,11 +32,10 @@ void AbstractClient::processProtocolItem(ProtocolItem *item) GenericEvent *genericEvent = qobject_cast(item); if (genericEvent) { switch (genericEvent->getItemId()) { - case ItemId_Event_ListGames: emit listGamesEventReceived(qobject_cast(item)); break; case ItemId_Event_UserJoined: emit userJoinedEventReceived(qobject_cast(item)); break; case ItemId_Event_UserLeft: emit userLeftEventReceived(qobject_cast(item)); break; case ItemId_Event_ServerMessage: emit serverMessageEventReceived(qobject_cast(item)); break; - case ItemId_Event_ListChatChannels: emit listChatChannelsEventReceived(qobject_cast(item)); break; + case ItemId_Event_ListRooms: emit listRoomsEventReceived(qobject_cast(item)); break; case ItemId_Event_GameJoined: emit gameJoinedEventReceived(qobject_cast(item)); break; case ItemId_Event_Message: emit messageEventReceived(qobject_cast(item)); break; } @@ -53,11 +52,11 @@ void AbstractClient::processProtocolItem(ProtocolItem *item) return; } - ChatEvent *chatEvent = qobject_cast(item); - if (chatEvent) { - emit chatEventReceived(chatEvent); - if (chatEvent->getReceiverMayDelete()) - delete chatEvent; + RoomEvent *roomEvent = qobject_cast(item); + if (roomEvent) { + emit roomEventReceived(roomEvent); + if (roomEvent->getReceiverMayDelete()) + delete roomEvent; return; } } @@ -75,4 +74,3 @@ void AbstractClient::sendCommand(Command *cmd) { sendCommandContainer(new CommandContainer(QList() << cmd)); } - diff --git a/cockatrice/src/abstractclient.h b/cockatrice/src/abstractclient.h index 601e55db..d5b4dc96 100644 --- a/cockatrice/src/abstractclient.h +++ b/cockatrice/src/abstractclient.h @@ -10,13 +10,13 @@ class ProtocolItem; class ProtocolResponse; class TopLevelProtocolItem; class CommandContainer; -class ChatEvent; +class RoomEvent; class GameEventContainer; class Event_ListGames; class Event_UserJoined; class Event_UserLeft; class Event_ServerMessage; -class Event_ListChatChannels; +class Event_ListRooms; class Event_GameJoined; class Event_Message; @@ -35,16 +35,15 @@ signals: void statusChanged(ClientStatus _status); void serverError(ResponseCode resp); - // Chat events - void chatEventReceived(ChatEvent *event); + // Room events + void roomEventReceived(RoomEvent *event); // Game events void gameEventContainerReceived(GameEventContainer *event); // Generic events - void listGamesEventReceived(Event_ListGames *event); void userJoinedEventReceived(Event_UserJoined *event); void userLeftEventReceived(Event_UserLeft *event); void serverMessageEventReceived(Event_ServerMessage *event); - void listChatChannelsEventReceived(Event_ListChatChannels *event); + void listRoomsEventReceived(Event_ListRooms *event); void gameJoinedEventReceived(Event_GameJoined *event); void messageEventReceived(Event_Message *event); protected slots: diff --git a/cockatrice/src/dlg_creategame.cpp b/cockatrice/src/dlg_creategame.cpp index 5cf957b6..e36a6815 100644 --- a/cockatrice/src/dlg_creategame.cpp +++ b/cockatrice/src/dlg_creategame.cpp @@ -11,8 +11,8 @@ #include "dlg_creategame.h" #include "protocol_items.h" -DlgCreateGame::DlgCreateGame(AbstractClient *_client, QWidget *parent) - : QDialog(parent), client(_client) +DlgCreateGame::DlgCreateGame(AbstractClient *_client, int _roomId, QWidget *parent) + : QDialog(parent), client(_client), roomId(_roomId) { descriptionLabel = new QLabel(tr("&Description:")); descriptionEdit = new QLineEdit; @@ -77,6 +77,7 @@ DlgCreateGame::DlgCreateGame(AbstractClient *_client, QWidget *parent) void DlgCreateGame::actOK() { Command_CreateGame *createCommand = new Command_CreateGame( + roomId, descriptionEdit->text(), passwordEdit->text(), maxPlayersEdit->value(), diff --git a/cockatrice/src/dlg_creategame.h b/cockatrice/src/dlg_creategame.h index af72fe18..dcd901df 100644 --- a/cockatrice/src/dlg_creategame.h +++ b/cockatrice/src/dlg_creategame.h @@ -14,13 +14,14 @@ class QSpinBox; class DlgCreateGame : public QDialog { Q_OBJECT public: - DlgCreateGame(AbstractClient *_client, QWidget *parent = 0); + DlgCreateGame(AbstractClient *_client, int _roomId, QWidget *parent = 0); private slots: void actOK(); void checkResponse(ResponseCode response); void spectatorsAllowedChanged(int state); private: AbstractClient *client; + int roomId; QGroupBox *spectatorsGroupBox; QLabel *descriptionLabel, *passwordLabel, *maxPlayersLabel; diff --git a/cockatrice/src/tab_chatchannel.cpp b/cockatrice/src/tab_chatchannel.cpp deleted file mode 100644 index 515844f1..00000000 --- a/cockatrice/src/tab_chatchannel.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "tab_chatchannel.h" -#include "abstractclient.h" -#include "protocol_items.h" - -TabChatChannel::TabChatChannel(AbstractClient *_client, const QString &_channelName) - : Tab(), client(_client), channelName(_channelName) -{ - playerList = new QListWidget; - playerList->setFixedWidth(150); - - textEdit = new QTextEdit; - textEdit->setReadOnly(true); - sayEdit = new QLineEdit; - connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(sendMessage())); - - QVBoxLayout *vbox = new QVBoxLayout; - vbox->addWidget(textEdit); - vbox->addWidget(sayEdit); - - QHBoxLayout *hbox = new QHBoxLayout; - hbox->addLayout(vbox); - hbox->addWidget(playerList); - - aLeaveChannel = new QAction(this); - connect(aLeaveChannel, SIGNAL(triggered()), this, SLOT(actLeaveChannel())); - - tabMenu = new QMenu(this); - tabMenu->addAction(aLeaveChannel); - - retranslateUi(); - setLayout(hbox); -} - -TabChatChannel::~TabChatChannel() -{ - emit channelClosing(this); -} - -void TabChatChannel::retranslateUi() -{ - tabMenu->setTitle(tr("C&hat channel")); - aLeaveChannel->setText(tr("&Leave channel")); -} - -QString TabChatChannel::sanitizeHtml(QString dirty) const -{ - return dirty - .replace("&", "&") - .replace("<", "<") - .replace(">", ">"); -} - -void TabChatChannel::sendMessage() -{ - if (sayEdit->text().isEmpty()) - return; - - client->sendCommand(new Command_ChatSay(channelName, sayEdit->text())); - sayEdit->clear(); -} - -void TabChatChannel::actLeaveChannel() -{ - client->sendCommand(new Command_ChatLeaveChannel(channelName)); - deleteLater(); -} - -void TabChatChannel::processChatEvent(ChatEvent *event) -{ - switch (event->getItemId()) { - case ItemId_Event_ChatListPlayers: processListPlayersEvent(qobject_cast(event)); break; - case ItemId_Event_ChatJoinChannel: processJoinChannelEvent(qobject_cast(event)); break; - case ItemId_Event_ChatLeaveChannel: processLeaveChannelEvent(qobject_cast(event)); break; - case ItemId_Event_ChatSay: processSayEvent(qobject_cast(event)); break; - default: ; - } -} - -void TabChatChannel::processListPlayersEvent(Event_ChatListPlayers *event) -{ - const QList &players = event->getPlayerList(); - for (int i = 0; i < players.size(); ++i) - playerList->addItem(players[i]->getName()); -} - -void TabChatChannel::processJoinChannelEvent(Event_ChatJoinChannel *event) -{ - textEdit->append(tr("%1 has joined the channel.").arg(sanitizeHtml(event->getUserInfo()->getName()))); - playerList->addItem(event->getUserInfo()->getName()); - emit userEvent(); -} - -void TabChatChannel::processLeaveChannelEvent(Event_ChatLeaveChannel *event) -{ - textEdit->append(tr("%1 has left the channel.").arg(sanitizeHtml(event->getPlayerName()))); - for (int i = 0; i < playerList->count(); ++i) - if (playerList->item(i)->text() == event->getPlayerName()) { - delete playerList->takeItem(i); - break; - } - emit userEvent(); -} - -void TabChatChannel::processSayEvent(Event_ChatSay *event) -{ - if (event->getPlayerName().isEmpty()) - textEdit->append(QString("%1getMessage()))); - else - textEdit->append(QString("%1: %2").arg(sanitizeHtml(event->getPlayerName())).arg(sanitizeHtml(event->getMessage()))); - emit userEvent(); -} diff --git a/cockatrice/src/tab_chatchannel.h b/cockatrice/src/tab_chatchannel.h deleted file mode 100644 index 2c329199..00000000 --- a/cockatrice/src/tab_chatchannel.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef TAB_CHATCHANNEL_H -#define TAB_CHATCHANNEL_H - -#include "tab.h" - -class AbstractClient; -class QListWidget; -class QTextEdit; -class QLineEdit; -class ChatEvent; -class Event_ChatListPlayers; -class Event_ChatJoinChannel; -class Event_ChatLeaveChannel; -class Event_ChatSay; - -class TabChatChannel : public Tab { - Q_OBJECT -private: - AbstractClient *client; - QString channelName; - - QListWidget *playerList; - QTextEdit *textEdit; - QLineEdit *sayEdit; - - QAction *aLeaveChannel; - QString sanitizeHtml(QString dirty) const; -signals: - void channelClosing(TabChatChannel *tab); -private slots: - void sendMessage(); - void actLeaveChannel(); - - void processListPlayersEvent(Event_ChatListPlayers *event); - void processJoinChannelEvent(Event_ChatJoinChannel *event); - void processLeaveChannelEvent(Event_ChatLeaveChannel *event); - void processSayEvent(Event_ChatSay *event); -public: - TabChatChannel(AbstractClient *_client, const QString &_channelName); - ~TabChatChannel(); - void retranslateUi(); - void processChatEvent(ChatEvent *event); - QString getChannelName() const { return channelName; } - QString getTabText() const { return channelName; } -}; - -#endif diff --git a/cockatrice/src/tab_room.cpp b/cockatrice/src/tab_room.cpp new file mode 100644 index 00000000..fbe101a8 --- /dev/null +++ b/cockatrice/src/tab_room.cpp @@ -0,0 +1,243 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dlg_creategame.h" +#include "tab_room.h" +#include "userlist.h" +#include "abstractclient.h" +#include "protocol_items.h" +#include "gamesmodel.h" + +GameSelector::GameSelector(AbstractClient *_client, int _roomId, QWidget *parent) + : QGroupBox(parent), client(_client), roomId(_roomId) +{ + gameListView = new QTreeView; + gameListModel = new GamesModel(this); + gameListProxyModel = new GamesProxyModel(this); + gameListProxyModel->setSourceModel(gameListModel); + gameListView->setModel(gameListProxyModel); + gameListView->header()->setResizeMode(0, QHeaderView::ResizeToContents); + + showFullGamesCheckBox = new QCheckBox; + createButton = new QPushButton; + joinButton = new QPushButton; + spectateButton = new QPushButton; + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->addWidget(showFullGamesCheckBox); + buttonLayout->addStretch(); + buttonLayout->addWidget(createButton); + buttonLayout->addWidget(joinButton); + buttonLayout->addWidget(spectateButton); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(gameListView); + mainLayout->addLayout(buttonLayout); + + retranslateUi(); + setLayout(mainLayout); + + setMinimumWidth(gameListView->columnWidth(0) * gameListModel->columnCount()); + setMinimumHeight(400); + + connect(showFullGamesCheckBox, SIGNAL(stateChanged(int)), this, SLOT(showFullGamesChanged(int))); + connect(createButton, SIGNAL(clicked()), this, SLOT(actCreate())); + connect(joinButton, SIGNAL(clicked()), this, SLOT(actJoin())); + connect(spectateButton, SIGNAL(clicked()), this, SLOT(actJoin())); +} + +void GameSelector::showFullGamesChanged(int state) +{ + gameListProxyModel->setFullGamesVisible(state); +} + +void GameSelector::actCreate() +{ + DlgCreateGame dlg(client, roomId, this); + dlg.exec(); +} + +void GameSelector::checkResponse(ResponseCode response) +{ + createButton->setEnabled(true); + joinButton->setEnabled(true); + spectateButton->setEnabled(true); + + switch (response) { + case RespWrongPassword: QMessageBox::critical(this, tr("Error"), tr("Wrong password.")); break; + case RespSpectatorsNotAllowed: QMessageBox::critical(this, tr("Error"), tr("Spectators are not allowed in this game.")); break; + case RespGameFull: QMessageBox::critical(this, tr("Error"), tr("The game is already full.")); break; + case RespNameNotFound: QMessageBox::critical(this, tr("Error"), tr("The game does not exist any more.")); break; + default: ; + } +} + +void GameSelector::actJoin() +{ + bool spectator = sender() == spectateButton; + + QModelIndex ind = gameListView->currentIndex(); + if (!ind.isValid()) + return; + ServerInfo_Game *game = gameListModel->getGame(ind.data(Qt::UserRole).toInt()); + QString password; + if (game->getHasPassword() && !(spectator && !game->getSpectatorsNeedPassword())) { + bool ok; + password = QInputDialog::getText(this, tr("Join game"), tr("Password:"), QLineEdit::Password, QString(), &ok); + if (!ok) + return; + } + + Command_JoinGame *commandJoinGame = new Command_JoinGame(roomId, game->getGameId(), password, spectator); + connect(commandJoinGame, SIGNAL(finished(ResponseCode)), this, SLOT(checkResponse(ResponseCode))); + client->sendCommand(commandJoinGame); + + createButton->setEnabled(false); + joinButton->setEnabled(false); + spectateButton->setEnabled(false); +} + +void GameSelector::retranslateUi() +{ + setTitle(tr("Games")); + showFullGamesCheckBox->setText(tr("Show &full games")); + createButton->setText(tr("C&reate")); + joinButton->setText(tr("&Join")); + spectateButton->setText(tr("J&oin as spectator")); +} + +void GameSelector::processGameInfo(ServerInfo_Game *info) +{ + gameListModel->updateGameList(info); +} + +TabRoom::TabRoom(AbstractClient *_client, ServerInfo_Room *info) + : Tab(), client(_client), roomId(info->getRoomId()), roomName(info->getName()) +{ + gameSelector = new GameSelector(client, roomId); + userList = new UserList(false); + + textEdit = new QTextEdit; + textEdit->setReadOnly(true); + sayLabel = new QLabel; + sayEdit = new QLineEdit; + sayLabel->setBuddy(sayEdit); + connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(sendMessage())); + + QHBoxLayout *sayHbox = new QHBoxLayout; + sayHbox->addWidget(sayLabel); + sayHbox->addWidget(sayEdit); + + QVBoxLayout *chatVbox = new QVBoxLayout; + chatVbox->addWidget(textEdit); + chatVbox->addLayout(sayHbox); + + chatGroupBox = new QGroupBox; + chatGroupBox->setLayout(chatVbox); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->addWidget(gameSelector); + vbox->addWidget(chatGroupBox); + + QHBoxLayout *hbox = new QHBoxLayout; + hbox->addLayout(vbox, 3); + hbox->addWidget(userList, 1); + + aLeaveRoom = new QAction(this); + connect(aLeaveRoom, SIGNAL(triggered()), this, SLOT(actLeaveRoom())); + + tabMenu = new QMenu(this); + tabMenu->addAction(aLeaveRoom); + + retranslateUi(); + setLayout(hbox); + + const QList users = info->getUserList(); + for (int i = 0; i < users.size(); ++i) + userList->processUserInfo(users[i]); +} + +TabRoom::~TabRoom() +{ + emit roomClosing(this); +} + +void TabRoom::retranslateUi() +{ + sayLabel->setText(tr("&Say:")); + chatGroupBox->setTitle(tr("Chat")); + tabMenu->setTitle(tr("&Room")); + aLeaveRoom->setText(tr("&Leave room")); +} + +QString TabRoom::sanitizeHtml(QString dirty) const +{ + return dirty + .replace("&", "&") + .replace("<", "<") + .replace(">", ">"); +} + +void TabRoom::sendMessage() +{ + if (sayEdit->text().isEmpty()) + return; + + client->sendCommand(new Command_RoomSay(roomId, sayEdit->text())); + sayEdit->clear(); +} + +void TabRoom::actLeaveRoom() +{ + client->sendCommand(new Command_LeaveRoom(roomId)); + deleteLater(); +} + +void TabRoom::processRoomEvent(RoomEvent *event) +{ + switch (event->getItemId()) { + case ItemId_Event_ListGames: processListGamesEvent(qobject_cast(event)); break; + case ItemId_Event_JoinRoom: processJoinRoomEvent(qobject_cast(event)); break; + case ItemId_Event_LeaveRoom: processLeaveRoomEvent(qobject_cast(event)); break; + case ItemId_Event_RoomSay: processSayEvent(qobject_cast(event)); break; + default: ; + } +} + +void TabRoom::processListGamesEvent(Event_ListGames *event) +{ + const QList &gameList = event->getGameList(); + for (int i = 0; i < gameList.size(); ++i) + gameSelector->processGameInfo(gameList[i]); +} + +void TabRoom::processJoinRoomEvent(Event_JoinRoom *event) +{ + textEdit->append(tr("%1 has joined the room.").arg(sanitizeHtml(event->getUserInfo()->getName()))); + userList->processUserInfo(event->getUserInfo()); + emit userEvent(); +} + +void TabRoom::processLeaveRoomEvent(Event_LeaveRoom *event) +{ + textEdit->append(tr("%1 has left the room.").arg(sanitizeHtml(event->getPlayerName()))); + userList->deleteUser(event->getPlayerName()); + emit userEvent(); +} + +void TabRoom::processSayEvent(Event_RoomSay *event) +{ + if (event->getPlayerName().isEmpty()) + textEdit->append(QString("%1getMessage()))); + else + textEdit->append(QString("%1: %2").arg(sanitizeHtml(event->getPlayerName())).arg(sanitizeHtml(event->getMessage()))); + emit userEvent(); +} diff --git a/cockatrice/src/tab_room.h b/cockatrice/src/tab_room.h new file mode 100644 index 00000000..e61a3831 --- /dev/null +++ b/cockatrice/src/tab_room.h @@ -0,0 +1,86 @@ +#ifndef TAB_ROOM_H +#define TAB_ROOM_H + +#include "tab.h" +#include "protocol_datastructures.h" +#include + +class AbstractClient; +class UserList; +class QLabel; +class QTextEdit; +class QLineEdit; +class QTreeView; +class QPushButton; +class QCheckBox; +class GamesModel; +class GamesProxyModel; +class RoomEvent; +class ServerInfo_Room; +class ServerInfo_Game; +class Event_ListGames; +class Event_JoinRoom; +class Event_LeaveRoom; +class Event_RoomSay; + +class GameSelector : public QGroupBox { + Q_OBJECT +private slots: + void showFullGamesChanged(int state); + void actCreate(); + void actJoin(); + void checkResponse(ResponseCode response); +signals: + void gameJoined(int gameId); +private: + AbstractClient *client; + int roomId; + + QTreeView *gameListView; + GamesModel *gameListModel; + GamesProxyModel *gameListProxyModel; + QPushButton *createButton, *joinButton, *spectateButton; + QCheckBox *showFullGamesCheckBox; +public: + GameSelector(AbstractClient *_client, int _roomId, QWidget *parent = 0); + void retranslateUi(); + void processGameInfo(ServerInfo_Game *info); +}; + +class TabRoom : public Tab { + Q_OBJECT +private: + AbstractClient *client; + int roomId; + QString roomName; + + GameSelector *gameSelector; + UserList *userList; + QTextEdit *textEdit; + QLabel *sayLabel; + QLineEdit *sayEdit; + QGroupBox *chatGroupBox; + + QAction *aLeaveRoom; + QString sanitizeHtml(QString dirty) const; +signals: + void roomClosing(TabRoom *tab); +private slots: + void sendMessage(); + void actLeaveRoom(); + + void processListGamesEvent(Event_ListGames *event); + void processJoinRoomEvent(Event_JoinRoom *event); + void processLeaveRoomEvent(Event_LeaveRoom *event); + void processSayEvent(Event_RoomSay *event); +public: + TabRoom(AbstractClient *_client, ServerInfo_Room *info); + ~TabRoom(); + void retranslateUi(); + void processRoomEvent(RoomEvent *event); + int getRoomId() const { return roomId; } + QString getChannelName() const { return roomName; } + QString getTabText() const { return roomName; } +}; + +#endif diff --git a/cockatrice/src/tab_server.cpp b/cockatrice/src/tab_server.cpp index d64c0a00..438c2281 100644 --- a/cockatrice/src/tab_server.cpp +++ b/cockatrice/src/tab_server.cpp @@ -10,126 +10,24 @@ #include #include #include "tab_server.h" -#include "gamesmodel.h" -#include "dlg_creategame.h" #include "abstractclient.h" #include "protocol.h" #include "protocol_items.h" +#include "userlist.h" #include "pixmapgenerator.h" #include -GameSelector::GameSelector(AbstractClient *_client, QWidget *parent) +RoomSelector::RoomSelector(AbstractClient *_client, QWidget *parent) : QGroupBox(parent), client(_client) { - gameListView = new QTreeView; - gameListModel = new GamesModel(this); - gameListProxyModel = new GamesProxyModel(this); - gameListProxyModel->setSourceModel(gameListModel); - gameListView->setModel(gameListProxyModel); - gameListView->header()->setResizeMode(0, QHeaderView::ResizeToContents); - - showFullGamesCheckBox = new QCheckBox; - createButton = new QPushButton; - joinButton = new QPushButton; - spectateButton = new QPushButton; - QHBoxLayout *buttonLayout = new QHBoxLayout; - buttonLayout->addWidget(showFullGamesCheckBox); - buttonLayout->addStretch(); - buttonLayout->addWidget(createButton); - buttonLayout->addWidget(joinButton); - buttonLayout->addWidget(spectateButton); - - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addWidget(gameListView); - mainLayout->addLayout(buttonLayout); - - retranslateUi(); - setLayout(mainLayout); - - setMinimumWidth(gameListView->columnWidth(0) * gameListModel->columnCount()); - setMinimumHeight(400); - - connect(showFullGamesCheckBox, SIGNAL(stateChanged(int)), this, SLOT(showFullGamesChanged(int))); - connect(createButton, SIGNAL(clicked()), this, SLOT(actCreate())); - connect(joinButton, SIGNAL(clicked()), this, SLOT(actJoin())); - connect(spectateButton, SIGNAL(clicked()), this, SLOT(actJoin())); - - connect(client, SIGNAL(listGamesEventReceived(Event_ListGames *)), this, SLOT(processListGamesEvent(Event_ListGames *))); - client->sendCommand(new Command_ListGames); -} - -void GameSelector::showFullGamesChanged(int state) -{ - gameListProxyModel->setFullGamesVisible(state); -} - -void GameSelector::actCreate() -{ - DlgCreateGame dlg(client, this); - dlg.exec(); -} - -void GameSelector::checkResponse(ResponseCode response) -{ - createButton->setEnabled(true); - joinButton->setEnabled(true); - spectateButton->setEnabled(true); - - switch (response) { - case RespWrongPassword: QMessageBox::critical(this, tr("Error"), tr("Wrong password.")); break; - case RespSpectatorsNotAllowed: QMessageBox::critical(this, tr("Error"), tr("Spectators are not allowed in this game.")); break; - case RespGameFull: QMessageBox::critical(this, tr("Error"), tr("The game is already full.")); break; - case RespNameNotFound: QMessageBox::critical(this, tr("Error"), tr("The game does not exist any more.")); break; - default: ; - } -} - -void GameSelector::actJoin() -{ - bool spectator = sender() == spectateButton; - - QModelIndex ind = gameListView->currentIndex(); - if (!ind.isValid()) - return; - ServerInfo_Game *game = gameListModel->getGame(ind.data(Qt::UserRole).toInt()); - QString password; - if (game->getHasPassword() && !(spectator && !game->getSpectatorsNeedPassword())) { - bool ok; - password = QInputDialog::getText(this, tr("Join game"), tr("Password:"), QLineEdit::Password, QString(), &ok); - if (!ok) - return; - } - - Command_JoinGame *commandJoinGame = new Command_JoinGame(game->getGameId(), password, spectator); - connect(commandJoinGame, SIGNAL(finished(ResponseCode)), this, SLOT(checkResponse(ResponseCode))); - client->sendCommand(commandJoinGame); - - createButton->setEnabled(false); - joinButton->setEnabled(false); - spectateButton->setEnabled(false); -} - -void GameSelector::retranslateUi() -{ - setTitle(tr("Games")); - showFullGamesCheckBox->setText(tr("&Show full games")); - createButton->setText(tr("C&reate")); - joinButton->setText(tr("&Join")); - spectateButton->setText(tr("J&oin as spectator")); -} - -void GameSelector::processListGamesEvent(Event_ListGames *event) -{ - const QList &gamesToUpdate = event->getGameList(); - for (int i = 0; i < gamesToUpdate.size(); ++i) - gameListModel->updateGameList(gamesToUpdate[i]); -} - -ChatChannelSelector::ChatChannelSelector(AbstractClient *_client, QWidget *parent) - : QGroupBox(parent), client(_client) -{ - channelList = new QTreeWidget; - channelList->setRootIsDecorated(false); + roomList = new QTreeWidget; + roomList->setRootIsDecorated(false); + roomList->setColumnCount(4); + roomList->header()->setStretchLastSection(false); + roomList->header()->setResizeMode(0, QHeaderView::ResizeToContents); + roomList->header()->setResizeMode(1, QHeaderView::Stretch); + roomList->header()->setResizeMode(2, QHeaderView::ResizeToContents); + roomList->header()->setResizeMode(3, QHeaderView::ResizeToContents); joinButton = new QPushButton; connect(joinButton, SIGNAL(clicked()), this, SLOT(joinClicked())); @@ -137,79 +35,85 @@ ChatChannelSelector::ChatChannelSelector(AbstractClient *_client, QWidget *paren buttonLayout->addStretch(); buttonLayout->addWidget(joinButton); QVBoxLayout *vbox = new QVBoxLayout; - vbox->addWidget(channelList); + vbox->addWidget(roomList); vbox->addLayout(buttonLayout); retranslateUi(); setLayout(vbox); - connect(client, SIGNAL(listChatChannelsEventReceived(Event_ListChatChannels *)), this, SLOT(processListChatChannelsEvent(Event_ListChatChannels *))); - client->sendCommand(new Command_ListChatChannels); + connect(client, SIGNAL(listRoomsEventReceived(Event_ListRooms *)), this, SLOT(processListRoomsEvent(Event_ListRooms *))); + client->sendCommand(new Command_ListRooms); } -void ChatChannelSelector::retranslateUi() +void RoomSelector::retranslateUi() { - setTitle(tr("Chat channels")); + setTitle(tr("Rooms")); joinButton->setText(tr("Joi&n")); - QTreeWidgetItem *header = channelList->headerItem(); - header->setText(0, tr("Channel")); + QTreeWidgetItem *header = roomList->headerItem(); + header->setText(0, tr("Room")); header->setText(1, tr("Description")); header->setText(2, tr("Players")); + header->setText(3, tr("Games")); header->setTextAlignment(2, Qt::AlignRight); + header->setTextAlignment(3, Qt::AlignRight); } -void ChatChannelSelector::processListChatChannelsEvent(Event_ListChatChannels *event) +void RoomSelector::processListRoomsEvent(Event_ListRooms *event) { - const QList &channelsToUpdate = event->getChannelList(); - for (int i = 0; i < channelsToUpdate.size(); ++i) { - ServerInfo_ChatChannel *channel = channelsToUpdate[i]; + const QList &roomsToUpdate = event->getRoomList(); + for (int i = 0; i < roomsToUpdate.size(); ++i) { + ServerInfo_Room *room = roomsToUpdate[i]; - for (int j = 0; j < channelList->topLevelItemCount(); ++j) { - QTreeWidgetItem *twi = channelList->topLevelItem(j); - if (twi->text(0) == channel->getName()) { - twi->setText(1, channel->getDescription()); - twi->setText(2, QString::number(channel->getPlayerCount())); + for (int j = 0; j < roomList->topLevelItemCount(); ++j) { + QTreeWidgetItem *twi = roomList->topLevelItem(j); + if (twi->data(0, Qt::UserRole).toInt() == room->getRoomId()) { + twi->setData(0, Qt::DisplayRole, room->getName()); + twi->setData(1, Qt::DisplayRole, room->getDescription()); + twi->setData(2, Qt::DisplayRole, room->getPlayerCount()); + twi->setData(3, Qt::DisplayRole, room->getGameCount()); return; } } - QTreeWidgetItem *twi = new QTreeWidgetItem(QStringList() << channel->getName() << channel->getDescription() << QString::number(channel->getPlayerCount())); + QTreeWidgetItem *twi = new QTreeWidgetItem; + twi->setData(0, Qt::UserRole, room->getRoomId()); + twi->setData(0, Qt::DisplayRole, room->getName()); + twi->setData(1, Qt::DisplayRole, room->getDescription()); + twi->setData(2, Qt::DisplayRole, room->getPlayerCount()); + twi->setData(3, Qt::DisplayRole, room->getGameCount()); twi->setTextAlignment(2, Qt::AlignRight); - channelList->addTopLevelItem(twi); - channelList->resizeColumnToContents(0); - channelList->resizeColumnToContents(1); - channelList->resizeColumnToContents(2); - if (channel->getAutoJoin()) - joinChannel(channel->getName()); + twi->setTextAlignment(3, Qt::AlignRight); + roomList->addTopLevelItem(twi); + if (room->getAutoJoin()) + joinRoom(room->getRoomId()); } } -void ChatChannelSelector::joinChannel(const QString &channelName) +void RoomSelector::joinRoom(int id) { - Command_ChatJoinChannel *command = new Command_ChatJoinChannel(channelName); - connect(command, SIGNAL(finished(ResponseCode)), this, SLOT(joinFinished(ResponseCode))); + Command_JoinRoom *command = new Command_JoinRoom(id); + connect(command, SIGNAL(finished(ProtocolResponse *)), this, SLOT(joinFinished(ProtocolResponse *))); client->sendCommand(command); } -void ChatChannelSelector::joinClicked() +void RoomSelector::joinClicked() { - QTreeWidgetItem *twi = channelList->currentItem(); + QTreeWidgetItem *twi = roomList->currentItem(); if (!twi) return; - QString channelName = twi->text(0); - joinChannel(channelName); + joinRoom(twi->data(0, Qt::UserRole).toInt()); } -void ChatChannelSelector::joinFinished(ResponseCode resp) +void RoomSelector::joinFinished(ProtocolResponse *r) { - if (resp != RespOk) + if (r->getResponseCode() != RespOk) + return; + Response_JoinRoom *resp = qobject_cast(r); + if (!resp) return; - Command_ChatJoinChannel *command = qobject_cast(sender()); - QString channelName = command->getChannel(); - - emit channelJoined(channelName); + emit roomJoined(resp->getRoomInfo()); } ServerMessageLog::ServerMessageLog(AbstractClient *_client, QWidget *parent) @@ -237,108 +141,6 @@ void ServerMessageLog::processServerMessageEvent(Event_ServerMessage *event) textEdit->append(event->getMessage()); } -UserListTWI::UserListTWI() - : QTreeWidgetItem(Type) -{ -} - -bool UserListTWI::operator<(const QTreeWidgetItem &other) const -{ - // Equal user level => sort by name - if (data(0, Qt::UserRole) == other.data(0, Qt::UserRole)) - return data(2, Qt::UserRole).toString().toLower() < other.data(2, Qt::UserRole).toString().toLower(); - // Else sort by user level - return data(0, Qt::UserRole).toInt() > other.data(0, Qt::UserRole).toInt(); -} - -UserList::UserList(AbstractClient *_client, QWidget *parent) - : QGroupBox(parent) -{ - userTree = new QTreeWidget; - userTree->setColumnCount(3); - userTree->header()->setResizeMode(QHeaderView::ResizeToContents); - userTree->setHeaderHidden(true); - userTree->setRootIsDecorated(false); - userTree->setIconSize(QSize(20, 12)); - connect(userTree, SIGNAL(itemActivated(QTreeWidgetItem *, int)), this, SLOT(userClicked(QTreeWidgetItem *, int))); - - QVBoxLayout *vbox = new QVBoxLayout; - vbox->addWidget(userTree); - - setLayout(vbox); - - retranslateUi(); - - connect(_client, SIGNAL(userJoinedEventReceived(Event_UserJoined *)), this, SLOT(processUserJoinedEvent(Event_UserJoined *))); - connect(_client, SIGNAL(userLeftEventReceived(Event_UserLeft *)), this, SLOT(processUserLeftEvent(Event_UserLeft *))); - - Command_ListUsers *cmd = new Command_ListUsers; - connect(cmd, SIGNAL(finished(ProtocolResponse *)), this, SLOT(processResponse(ProtocolResponse *))); - _client->sendCommand(cmd); -} - -void UserList::retranslateUi() -{ - setTitle(tr("Users online: %1").arg(userTree->topLevelItemCount())); -} - -void UserList::processUserInfo(ServerInfo_User *user) -{ - QTreeWidgetItem *item = 0; - for (int i = 0; i < userTree->topLevelItemCount(); ++i) { - QTreeWidgetItem *temp = userTree->topLevelItem(i); - if (temp->data(2, Qt::UserRole) == user->getName()) { - item = temp; - break; - } - } - if (!item) { - item = new UserListTWI; - userTree->addTopLevelItem(item); - retranslateUi(); - } - item->setData(0, Qt::UserRole, user->getUserLevel()); - item->setIcon(0, QIcon(UserLevelPixmapGenerator::generatePixmap(12, user->getUserLevel()))); - item->setIcon(1, QIcon(CountryPixmapGenerator::generatePixmap(12, user->getCountry()))); - item->setData(2, Qt::UserRole, user->getName()); - item->setData(2, Qt::DisplayRole, user->getName()); -} - -void UserList::processResponse(ProtocolResponse *response) -{ - Response_ListUsers *resp = qobject_cast(response); - if (!resp) - return; - - const QList &respList = resp->getUserList(); - for (int i = 0; i < respList.size(); ++i) - processUserInfo(respList[i]); - - userTree->sortItems(1, Qt::AscendingOrder); -} - -void UserList::processUserJoinedEvent(Event_UserJoined *event) -{ - processUserInfo(event->getUserInfo()); - userTree->sortItems(1, Qt::AscendingOrder); -} - -void UserList::processUserLeftEvent(Event_UserLeft *event) -{ - for (int i = 0; i < userTree->topLevelItemCount(); ++i) - if (userTree->topLevelItem(i)->data(2, Qt::UserRole) == event->getUserName()) { - emit userLeft(event->getUserName()); - delete userTree->takeTopLevelItem(i); - retranslateUi(); - break; - } -} - -void UserList::userClicked(QTreeWidgetItem *item, int /*column*/) -{ - emit openMessageDialog(item->data(2, Qt::UserRole).toString(), true); -} - UserInfoBox::UserInfoBox(AbstractClient *_client, QWidget *parent) : QWidget(parent) { @@ -409,24 +211,26 @@ void UserInfoBox::processResponse(ProtocolResponse *response) TabServer::TabServer(AbstractClient *_client, QWidget *parent) : Tab(parent), client(_client) { - gameSelector = new GameSelector(client); - chatChannelSelector = new ChatChannelSelector(client); + roomSelector = new RoomSelector(client); serverMessageLog = new ServerMessageLog(client); userInfoBox = new UserInfoBox(client); - userList = new UserList(client); + userList = new UserList(true); - connect(gameSelector, SIGNAL(gameJoined(int)), this, SIGNAL(gameJoined(int))); - connect(chatChannelSelector, SIGNAL(channelJoined(const QString &)), this, SIGNAL(chatChannelJoined(const QString &))); +// connect(gameSelector, SIGNAL(gameJoined(int)), this, SIGNAL(gameJoined(int))); + connect(roomSelector, SIGNAL(roomJoined(ServerInfo_Room *)), this, SIGNAL(roomJoined(ServerInfo_Room *))); connect(userList, SIGNAL(openMessageDialog(const QString &, bool)), this, SIGNAL(openMessageDialog(const QString &, bool))); connect(userList, SIGNAL(userLeft(const QString &)), this, SIGNAL(userLeft(const QString &))); - QHBoxLayout *hbox = new QHBoxLayout; - hbox->addWidget(chatChannelSelector); - hbox->addWidget(serverMessageLog); + connect(client, SIGNAL(userJoinedEventReceived(Event_UserJoined *)), this, SLOT(processUserJoinedEvent(Event_UserJoined *))); + connect(client, SIGNAL(userLeftEventReceived(Event_UserLeft *)), this, SLOT(processUserLeftEvent(Event_UserLeft *))); + + Command_ListUsers *cmd = new Command_ListUsers; + connect(cmd, SIGNAL(finished(ProtocolResponse *)), this, SLOT(processListUsersResponse(ProtocolResponse *))); + client->sendCommand(cmd); QVBoxLayout *vbox = new QVBoxLayout; - vbox->addWidget(gameSelector); - vbox->addLayout(hbox); + vbox->addWidget(roomSelector); + vbox->addWidget(serverMessageLog); QVBoxLayout *vbox2 = new QVBoxLayout; vbox2->addWidget(userInfoBox); @@ -441,9 +245,33 @@ TabServer::TabServer(AbstractClient *_client, QWidget *parent) void TabServer::retranslateUi() { - gameSelector->retranslateUi(); - chatChannelSelector->retranslateUi(); + roomSelector->retranslateUi(); serverMessageLog->retranslateUi(); userInfoBox->retranslateUi(); userList->retranslateUi(); } + +void TabServer::processListUsersResponse(ProtocolResponse *response) +{ + Response_ListUsers *resp = qobject_cast(response); + if (!resp) + return; + + const QList &respList = resp->getUserList(); + for (int i = 0; i < respList.size(); ++i) + userList->processUserInfo(respList[i]); + + userList->sortItems(); +} + +void TabServer::processUserJoinedEvent(Event_UserJoined *event) +{ + userList->processUserInfo(event->getUserInfo()); + userList->sortItems(); +} + +void TabServer::processUserLeftEvent(Event_UserLeft *event) +{ + if (userList->deleteUser(event->getUserName())) + emit userLeft(event->getUserName()); +} \ No newline at end of file diff --git a/cockatrice/src/tab_server.h b/cockatrice/src/tab_server.h index 642c1456..47003983 100644 --- a/cockatrice/src/tab_server.h +++ b/cockatrice/src/tab_server.h @@ -7,63 +7,33 @@ #include "protocol_datastructures.h" class AbstractClient; -class QTreeView; -class QTreeWidget; -class QTreeWidgetItem; -class QPushButton; -class QCheckBox; class QTextEdit; class QLabel; +class UserList; +class QPushButton; -class GamesModel; -class GamesProxyModel; - -class Event_ListGames; -class Event_ListChatChannels; +class Event_ListRooms; class Event_ServerMessage; class Event_UserJoined; class Event_UserLeft; class ProtocolResponse; -class GameSelector : public QGroupBox { - Q_OBJECT -public: - GameSelector(AbstractClient *_client, QWidget *parent = 0); - void retranslateUi(); -private slots: - void processListGamesEvent(Event_ListGames *event); - void showFullGamesChanged(int state); - void actCreate(); - void actJoin(); - void checkResponse(ResponseCode response); -signals: - void gameJoined(int gameId); -private: - AbstractClient *client; - - QTreeView *gameListView; - GamesModel *gameListModel; - GamesProxyModel *gameListProxyModel; - QPushButton *createButton, *joinButton, *spectateButton; - QCheckBox *showFullGamesCheckBox; -}; - -class ChatChannelSelector : public QGroupBox { +class RoomSelector : public QGroupBox { Q_OBJECT private: - QTreeWidget *channelList; + QTreeWidget *roomList; QPushButton *joinButton; AbstractClient *client; - void joinChannel(const QString &channelName); + void joinRoom(int id); private slots: - void processListChatChannelsEvent(Event_ListChatChannels *event); + void processListRoomsEvent(Event_ListRooms *event); void joinClicked(); - void joinFinished(ResponseCode resp); + void joinFinished(ProtocolResponse *resp); signals: - void channelJoined(const QString &channelName); + void roomJoined(ServerInfo_Room *info); public: - ChatChannelSelector(AbstractClient *_client, QWidget *parent = 0); + RoomSelector(AbstractClient *_client, QWidget *parent = 0); void retranslateUi(); }; @@ -78,30 +48,6 @@ public: void retranslateUi(); }; -class UserListTWI : public QTreeWidgetItem { -public: - UserListTWI(); - bool operator<(const QTreeWidgetItem &other) const; -}; - -class UserList : public QGroupBox { - Q_OBJECT -private: - QTreeWidget *userTree; - void processUserInfo(ServerInfo_User *user); -private slots: - void processResponse(ProtocolResponse *response); - void processUserJoinedEvent(Event_UserJoined *event); - void processUserLeftEvent(Event_UserLeft *event); - void userClicked(QTreeWidgetItem *item, int column); -signals: - void openMessageDialog(const QString &userName, bool focus); - void userLeft(const QString &userName); -public: - UserList(AbstractClient *_client, QWidget *parent = 0); - void retranslateUi(); -}; - class UserInfoBox : public QWidget { Q_OBJECT private: @@ -116,14 +62,17 @@ public: class TabServer : public Tab { Q_OBJECT signals: - void chatChannelJoined(const QString &channelName); - void gameJoined(int gameId); + void roomJoined(ServerInfo_Room *info); +// void gameJoined(int gameId); void openMessageDialog(const QString &userName, bool focus); void userLeft(const QString &userName); +private slots: + void processListUsersResponse(ProtocolResponse *response); + void processUserJoinedEvent(Event_UserJoined *event); + void processUserLeftEvent(Event_UserLeft *event); private: AbstractClient *client; - GameSelector *gameSelector; - ChatChannelSelector *chatChannelSelector; + RoomSelector *roomSelector; ServerMessageLog *serverMessageLog; UserList *userList; UserInfoBox *userInfoBox; diff --git a/cockatrice/src/tab_supervisor.cpp b/cockatrice/src/tab_supervisor.cpp index b5075470..084e9e35 100644 --- a/cockatrice/src/tab_supervisor.cpp +++ b/cockatrice/src/tab_supervisor.cpp @@ -2,7 +2,7 @@ #include "tab_supervisor.h" #include "abstractclient.h" #include "tab_server.h" -#include "tab_chatchannel.h" +#include "tab_room.h" #include "tab_game.h" #include "tab_deck_storage.h" #include "tab_message.h" @@ -32,9 +32,9 @@ void TabSupervisor::retranslateUi() tabs.append(tabServer); if (tabDeckStorage) tabs.append(tabDeckStorage); - QMapIterator chatChannelIterator(chatChannelTabs); - while (chatChannelIterator.hasNext()) - tabs.append(chatChannelIterator.next().value()); + QMapIterator roomIterator(roomTabs); + while (roomIterator.hasNext()) + tabs.append(roomIterator.next().value()); QMapIterator gameIterator(gameTabs); while (gameIterator.hasNext()) tabs.append(gameIterator.next().value()); @@ -54,14 +54,14 @@ void TabSupervisor::myAddTab(Tab *tab) void TabSupervisor::start(AbstractClient *_client) { client = _client; - connect(client, SIGNAL(chatEventReceived(ChatEvent *)), this, SLOT(processChatEvent(ChatEvent *))); + connect(client, SIGNAL(roomEventReceived(RoomEvent *)), this, SLOT(processRoomEvent(RoomEvent *))); connect(client, SIGNAL(gameEventContainerReceived(GameEventContainer *)), this, SLOT(processGameEventContainer(GameEventContainer *))); connect(client, SIGNAL(gameJoinedEventReceived(Event_GameJoined *)), this, SLOT(gameJoined(Event_GameJoined *))); connect(client, SIGNAL(messageEventReceived(Event_Message *)), this, SLOT(processMessageEvent(Event_Message *))); connect(client, SIGNAL(maxPingTime(int, int)), this, SLOT(updatePingTime(int, int))); tabServer = new TabServer(client); - connect(tabServer, SIGNAL(chatChannelJoined(const QString &)), this, SLOT(addChatChannelTab(const QString &))); + connect(tabServer, SIGNAL(roomJoined(ServerInfo_Room *)), this, SLOT(addRoomTab(ServerInfo_Room *))); connect(tabServer, SIGNAL(openMessageDialog(const QString &, bool)), this, SLOT(addMessageTab(const QString &, bool))); connect(tabServer, SIGNAL(userLeft(const QString &)), this, SLOT(processUserLeft(const QString &))); myAddTab(tabServer); @@ -107,10 +107,10 @@ void TabSupervisor::stop() tabDeckStorage->deleteLater(); tabDeckStorage = 0; - QMapIterator chatChannelIterator(chatChannelTabs); - while (chatChannelIterator.hasNext()) - chatChannelIterator.next().value()->deleteLater(); - chatChannelTabs.clear(); + QMapIterator roomIterator(roomTabs); + while (roomIterator.hasNext()) + roomIterator.next().value()->deleteLater(); + roomTabs.clear(); QMapIterator gameIterator(gameTabs); while (gameIterator.hasNext()) @@ -160,20 +160,20 @@ void TabSupervisor::gameLeft(TabGame *tab) stop(); } -void TabSupervisor::addChatChannelTab(const QString &channelName) +void TabSupervisor::addRoomTab(ServerInfo_Room *info) { - TabChatChannel *tab = new TabChatChannel(client, channelName); - connect(tab, SIGNAL(channelClosing(TabChatChannel *)), this, SLOT(chatChannelLeft(TabChatChannel *))); + TabRoom *tab = new TabRoom(client, info); + connect(tab, SIGNAL(roomClosing(TabRoom *)), this, SLOT(roomLeft(TabRoom *))); myAddTab(tab); - chatChannelTabs.insert(channelName, tab); + roomTabs.insert(info->getRoomId(), tab); setCurrentWidget(tab); } -void TabSupervisor::chatChannelLeft(TabChatChannel *tab) +void TabSupervisor::roomLeft(TabRoom *tab) { emit setMenu(0); - chatChannelTabs.remove(tab->getChannelName()); + roomTabs.remove(tab->getRoomId()); removeTab(indexOf(tab)); } @@ -206,11 +206,11 @@ void TabSupervisor::tabUserEvent() QApplication::alert(this); } -void TabSupervisor::processChatEvent(ChatEvent *event) +void TabSupervisor::processRoomEvent(RoomEvent *event) { - TabChatChannel *tab = chatChannelTabs.value(event->getChannel(), 0); + TabRoom *tab = roomTabs.value(event->getRoomId(), 0); if (tab) - tab->processChatEvent(event); + tab->processRoomEvent(event); } void TabSupervisor::processGameEventContainer(GameEventContainer *cont) diff --git a/cockatrice/src/tab_supervisor.h b/cockatrice/src/tab_supervisor.h index 7d1965f8..1dd11463 100644 --- a/cockatrice/src/tab_supervisor.h +++ b/cockatrice/src/tab_supervisor.h @@ -8,14 +8,15 @@ class QMenu; class AbstractClient; class Tab; class TabServer; -class TabChatChannel; +class TabRoom; class TabGame; class TabDeckStorage; class TabMessage; -class ChatEvent; +class RoomEvent; class GameEventContainer; class Event_GameJoined; class Event_Message; +class ServerInfo_Room; class TabSupervisor : public QTabWidget { Q_OBJECT @@ -25,7 +26,7 @@ private: QList localClients; TabServer *tabServer; TabDeckStorage *tabDeckStorage; - QMap chatChannelTabs; + QMap roomTabs; QMap gameTabs; QMap messageTabs; void myAddTab(Tab *tab); @@ -46,13 +47,13 @@ private slots: void gameJoined(Event_GameJoined *event); void localGameJoined(Event_GameJoined *event); void gameLeft(TabGame *tab); - void addChatChannelTab(const QString &channelName); - void chatChannelLeft(TabChatChannel *tab); + void addRoomTab(ServerInfo_Room *info); + void roomLeft(TabRoom *tab); TabMessage *addMessageTab(const QString &userName, bool focus); void processUserLeft(const QString &userName); void talkLeft(TabMessage *tab); void tabUserEvent(); - void processChatEvent(ChatEvent *event); + void processRoomEvent(RoomEvent *event); void processGameEventContainer(GameEventContainer *cont); void processMessageEvent(Event_Message *event); }; diff --git a/cockatrice/src/userlist.cpp b/cockatrice/src/userlist.cpp new file mode 100644 index 00000000..54fb4703 --- /dev/null +++ b/cockatrice/src/userlist.cpp @@ -0,0 +1,93 @@ +#include "userlist.h" +#include "abstractclient.h" +#include "pixmapgenerator.h" +#include +#include + +UserListTWI::UserListTWI() + : QTreeWidgetItem(Type) +{ +} + +bool UserListTWI::operator<(const QTreeWidgetItem &other) const +{ + // Equal user level => sort by name + if (data(0, Qt::UserRole) == other.data(0, Qt::UserRole)) + return data(2, Qt::UserRole).toString().toLower() < other.data(2, Qt::UserRole).toString().toLower(); + // Else sort by user level + return data(0, Qt::UserRole).toInt() > other.data(0, Qt::UserRole).toInt(); +} + +UserList::UserList(bool _global, QWidget *parent) + : QGroupBox(parent), global(_global) +{ + userTree = new QTreeWidget; + userTree->setColumnCount(3); + userTree->header()->setResizeMode(QHeaderView::ResizeToContents); + userTree->setHeaderHidden(true); + userTree->setRootIsDecorated(false); + userTree->setIconSize(QSize(20, 12)); + connect(userTree, SIGNAL(itemActivated(QTreeWidgetItem *, int)), this, SLOT(userClicked(QTreeWidgetItem *, int))); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->addWidget(userTree); + + setLayout(vbox); + + retranslateUi(); +} + +void UserList::retranslateUi() +{ + titleStr = global ? tr("Users online: %1") : tr("Users in this room: %1"); + updateCount(); +} + +void UserList::processUserInfo(ServerInfo_User *user) +{ + QTreeWidgetItem *item = 0; + for (int i = 0; i < userTree->topLevelItemCount(); ++i) { + QTreeWidgetItem *temp = userTree->topLevelItem(i); + if (temp->data(2, Qt::UserRole) == user->getName()) { + item = temp; + break; + } + } + if (!item) { + item = new UserListTWI; + userTree->addTopLevelItem(item); + retranslateUi(); + } + item->setData(0, Qt::UserRole, user->getUserLevel()); + item->setIcon(0, QIcon(UserLevelPixmapGenerator::generatePixmap(12, user->getUserLevel()))); + item->setIcon(1, QIcon(CountryPixmapGenerator::generatePixmap(12, user->getCountry()))); + item->setData(2, Qt::UserRole, user->getName()); + item->setData(2, Qt::DisplayRole, user->getName()); +} + +bool UserList::deleteUser(const QString &userName) +{ + for (int i = 0; i < userTree->topLevelItemCount(); ++i) + if (userTree->topLevelItem(i)->data(2, Qt::UserRole) == userName) { + delete userTree->takeTopLevelItem(i); + updateCount(); + return true; + } + + return false; +} + +void UserList::updateCount() +{ + setTitle(titleStr.arg(userTree->topLevelItemCount())); +} + +void UserList::userClicked(QTreeWidgetItem *item, int /*column*/) +{ + emit openMessageDialog(item->data(2, Qt::UserRole).toString(), true); +} + +void UserList::sortItems() +{ + userTree->sortItems(1, Qt::AscendingOrder); +} diff --git a/cockatrice/src/userlist.h b/cockatrice/src/userlist.h new file mode 100644 index 00000000..0694eee0 --- /dev/null +++ b/cockatrice/src/userlist.h @@ -0,0 +1,35 @@ +#ifndef USERLIST_H +#define USERLIST_H + +#include +#include + +class QTreeWidget; +class ServerInfo_User; + +class UserListTWI : public QTreeWidgetItem { +public: + UserListTWI(); + bool operator<(const QTreeWidgetItem &other) const; +}; + +class UserList : public QGroupBox { + Q_OBJECT +private: + QTreeWidget *userTree; + bool global; + QString titleStr; + void updateCount(); +private slots: + void userClicked(QTreeWidgetItem *item, int column); +signals: + void openMessageDialog(const QString &userName, bool focus); +public: + UserList(bool _global, QWidget *parent = 0); + void retranslateUi(); + void processUserInfo(ServerInfo_User *user); + bool deleteUser(const QString &userName); + void sortItems(); +}; + +#endif \ No newline at end of file diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index d4c11b59..e6d53e7c 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -110,9 +110,9 @@ void MainWindow::actSinglePlayer() } tabSupervisor->startLocal(localClients); - Command_CreateGame *createCommand = new Command_CreateGame(QString(), QString(), numberPlayers, false, false, false, false); +/* Command_CreateGame *createCommand = new Command_CreateGame(QString(), QString(), numberPlayers, false, false, false, false); mainClient->sendCommand(createCommand); -} +*/} void MainWindow::localGameEnded() { diff --git a/common/protocol.cpp b/common/protocol.cpp index 4ac9677f..1a1a2f55 100644 --- a/common/protocol.cpp +++ b/common/protocol.cpp @@ -37,6 +37,7 @@ void ProtocolItem::initializeHash() registerSerializableItem("resp", ProtocolResponse::newItem); ProtocolResponse::initializeHash(); + registerSerializableItem("respjoin_room", Response_JoinRoom::newItem); registerSerializableItem("resplist_users", Response_ListUsers::newItem); registerSerializableItem("respget_user_info", Response_GetUserInfo::newItem); registerSerializableItem("respdeck_list", Response_DeckList::newItem); @@ -220,6 +221,14 @@ void ProtocolResponse::initializeHash() responseHash.insert("spectators_not_allowed", RespSpectatorsNotAllowed); } +Response_JoinRoom::Response_JoinRoom(int _cmdId, ResponseCode _responseCode, ServerInfo_Room *_roomInfo) + : ProtocolResponse(_cmdId, _responseCode, "join_room") +{ + if (!_roomInfo) + _roomInfo = new ServerInfo_Room; + insertItem(_roomInfo); +} + Response_ListUsers::Response_ListUsers(int _cmdId, ResponseCode _responseCode, const QList &_userList) : ProtocolResponse(_cmdId, _responseCode, "list_users") { diff --git a/common/protocol.h b/common/protocol.h index 387057a0..307a15e7 100644 --- a/common/protocol.h +++ b/common/protocol.h @@ -43,6 +43,7 @@ enum ItemId { ItemId_Response_DeckDownload = ItemId_Other + 303, ItemId_Response_DeckUpload = ItemId_Other + 304, ItemId_Response_DumpZone = ItemId_Other + 305, + ItemId_Response_JoinRoom = ItemId_Other + 306, ItemId_Invalid = ItemId_Other + 1000 }; @@ -204,6 +205,15 @@ public: ResponseCode getResponseCode() const { return responseHash.value(static_cast(itemMap.value("response_code"))->getData(), RespOk); } }; +class Response_JoinRoom : public ProtocolResponse { + Q_OBJECT +public: + Response_JoinRoom(int _cmdId = -1, ResponseCode _responseCode = RespOk, ServerInfo_Room *_roomInfo = 0); + int getItemId() const { return ItemId_Response_JoinRoom; } + static SerializableItem *newItem() { return new Response_JoinRoom; } + ServerInfo_Room *getRoomInfo() const { return static_cast(itemMap.value("room")); } +}; + class Response_ListUsers : public ProtocolResponse { Q_OBJECT public: diff --git a/common/protocol_datastructures.cpp b/common/protocol_datastructures.cpp index f3ee0b73..ccf34bcb 100644 --- a/common/protocol_datastructures.cpp +++ b/common/protocol_datastructures.cpp @@ -3,17 +3,6 @@ #include #include -ServerInfo_Room::ServerInfo_Room(int _roomId, const QString &_name, const QString &_description, int _gameCount, int _playerCount, bool _autoJoin) - : SerializableItem_Map("room") -{ - insertItem(new SerializableItem_Int("room_id", _roomId)); - insertItem(new SerializableItem_String("name", _name)); - insertItem(new SerializableItem_String("description", _description)); - insertItem(new SerializableItem_Int("game_count", _gameCount)); - insertItem(new SerializableItem_Int("player_count", _playerCount)); - insertItem(new SerializableItem_Bool("auto_join", _autoJoin)); -} - ServerInfo_User::ServerInfo_User(const QString &_name, int _userLevel, const QString &_country, const QByteArray &_avatarBmp) : SerializableItem_Map("user") { @@ -23,13 +12,13 @@ ServerInfo_User::ServerInfo_User(const QString &_name, int _userLevel, const QSt insertItem(new SerializableItem_ByteArray("avatar_bmp", _avatarBmp)); } -ServerInfo_User::ServerInfo_User(const ServerInfo_User *other) +ServerInfo_User::ServerInfo_User(const ServerInfo_User *other, bool complete) : SerializableItem_Map("user") { insertItem(new SerializableItem_String("name", other->getName())); insertItem(new SerializableItem_Int("userlevel", other->getUserLevel())); insertItem(new SerializableItem_String("country", other->getCountry())); - insertItem(new SerializableItem_ByteArray("avatar_bmp", other->getAvatarBmp())); + insertItem(new SerializableItem_ByteArray("avatar_bmp", complete ? other->getAvatarBmp() : QByteArray())); } ServerInfo_Game::ServerInfo_Game(int _gameId, const QString &_description, bool _hasPassword, int _playerCount, int _maxPlayers, ServerInfo_User *_creatorInfo, bool _spectatorsAllowed, bool _spectatorsNeedPassword, int _spectatorCount) @@ -48,6 +37,40 @@ ServerInfo_Game::ServerInfo_Game(int _gameId, const QString &_description, bool insertItem(new SerializableItem_Int("spectator_count", _spectatorCount)); } +ServerInfo_Room::ServerInfo_Room(int _roomId, const QString &_name, const QString &_description, int _gameCount, int _playerCount, bool _autoJoin, const QList &_gameList, const QList &_userList) + : SerializableItem_Map("room") +{ + insertItem(new SerializableItem_Int("room_id", _roomId)); + insertItem(new SerializableItem_String("name", _name)); + insertItem(new SerializableItem_String("description", _description)); + insertItem(new SerializableItem_Int("game_count", _gameCount)); + insertItem(new SerializableItem_Int("player_count", _playerCount)); + insertItem(new SerializableItem_Bool("auto_join", _autoJoin)); + + gameList = _gameList; + for (int i = 0; i < _gameList.size(); ++i) + itemList.append(_gameList[i]); + userList = _userList; + for (int i = 0; i < _userList.size(); ++i) + itemList.append(_userList[i]); +} + +void ServerInfo_Room::extractData() +{ + for (int i = 0; i < itemList.size(); ++i) { + ServerInfo_User *user = dynamic_cast(itemList[i]); + if (user) { + userList.append(user); + continue; + } + ServerInfo_Game *game = dynamic_cast(itemList[i]); + if (game) { + gameList.append(game); + continue; + } + } +} + ServerInfo_CardCounter::ServerInfo_CardCounter(int _id, int _value) : SerializableItem_Map("card_counter") { diff --git a/common/protocol_datastructures.h b/common/protocol_datastructures.h index 614dcaf8..5f5649ec 100644 --- a/common/protocol_datastructures.h +++ b/common/protocol_datastructures.h @@ -20,18 +20,6 @@ enum ResponseCode { RespNothing, RespOk, RespInvalidCommand, RespInvalidData, Re // list index, whereas cards in any other zone are referenced by their ids. enum ZoneType { PrivateZone, PublicZone, HiddenZone }; -class ServerInfo_Room : public SerializableItem_Map { -public: - ServerInfo_Room(int _id = -1, const QString &_name = QString(), const QString &_description = QString(), int _gameCount = -1, int _playerCount = -1, bool _autoJoin = false); - static SerializableItem *newItem() { return new ServerInfo_Room; } - int getRoomId() const { return static_cast(itemMap.value("room_id"))->getData(); } - QString getName() const { return static_cast(itemMap.value("name"))->getData(); } - QString getDescription() const { return static_cast(itemMap.value("description"))->getData(); } - int getGameCount() const { return static_cast(itemMap.value("game_count"))->getData(); } - int getPlayerCount() const { return static_cast(itemMap.value("player_count"))->getData(); } - bool getAutoJoin() const { return static_cast(itemMap.value("auto_join"))->getData(); } -}; - class ServerInfo_User : public SerializableItem_Map { public: enum UserLevelFlags { @@ -42,7 +30,7 @@ public: IsAdmin = 0x08 }; ServerInfo_User(const QString &_name = QString(), int _userLevel = IsNothing, const QString &_country = QString(), const QByteArray &_avatarBmp = QByteArray()); - ServerInfo_User(const ServerInfo_User *other); + ServerInfo_User(const ServerInfo_User *other, bool complete = true); static SerializableItem *newItem() { return new ServerInfo_User; } QString getName() const { return static_cast(itemMap.value("name"))->getData(); } int getUserLevel() const { return static_cast(itemMap.value("userlevel"))->getData(); } @@ -66,6 +54,25 @@ public: int getSpectatorCount() const { return static_cast(itemMap.value("spectator_count"))->getData(); } }; +class ServerInfo_Room : public SerializableItem_Map { +private: + QList gameList; + QList userList; +protected: + void extractData(); +public: + ServerInfo_Room(int _id = -1, const QString &_name = QString(), const QString &_description = QString(), int _gameCount = -1, int _playerCount = -1, bool _autoJoin = false, const QList &_gameList = QList(), const QList &_userList = QList()); + static SerializableItem *newItem() { return new ServerInfo_Room; } + int getRoomId() const { return static_cast(itemMap.value("room_id"))->getData(); } + QString getName() const { return static_cast(itemMap.value("name"))->getData(); } + QString getDescription() const { return static_cast(itemMap.value("description"))->getData(); } + int getGameCount() const { return static_cast(itemMap.value("game_count"))->getData(); } + int getPlayerCount() const { return static_cast(itemMap.value("player_count"))->getData(); } + bool getAutoJoin() const { return static_cast(itemMap.value("auto_join"))->getData(); } + const QList &getGameList() const { return gameList; } + const QList &getUserList() const { return userList; } +}; + class ServerInfo_CardCounter : public SerializableItem_Map { public: ServerInfo_CardCounter(int _id = -1, int _value = 0); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 2e946c24..114b6bd3 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -279,10 +279,8 @@ ResponseCode Server_ProtocolHandler::cmdListRooms(Command_ListRooms * /*cmd*/, C QList eventRoomList; QMapIterator roomIterator(server->getRooms()); - while (roomIterator.hasNext()) { - Server_Room *r = roomIterator.next().value(); - eventRoomList.append(new ServerInfo_Room(r->getId(), r->getName(), r->getDescription(), r->getGames().size(), r->size(), r->getAutoJoin())); - } + while (roomIterator.hasNext()) + eventRoomList.append(roomIterator.next().value()->getInfo(false)); cont->enqueueItem(new Event_ListRooms(eventRoomList)); acceptsRoomListChanges = true; @@ -303,7 +301,9 @@ ResponseCode Server_ProtocolHandler::cmdJoinRoom(Command_JoinRoom *cmd, CommandC r->addClient(this); rooms.insert(r->getId(), r); - return RespOk; + + cont->setResponse(new Response_JoinRoom(cont->getCmdId(), RespOk, r->getInfo(true))); + return RespNothing; } ResponseCode Server_ProtocolHandler::cmdLeaveRoom(Command_LeaveRoom * /*cmd*/, CommandContainer *cont, Server_Room *room) diff --git a/common/server_room.cpp b/common/server_room.cpp index 95ca746a..ff13ea29 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -1,6 +1,7 @@ #include "server_room.h" #include "server_protocolhandler.h" #include "server_game.h" +#include Server_Room::Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, Server *parent) : QObject(parent), id(_id), name(_name), description(_description), autoJoin(_autoJoin), joinMessage(_joinMessage) @@ -12,7 +13,24 @@ Server *Server_Room::getServer() const return static_cast(parent()); } -QList Server_Room::addClient(Server_ProtocolHandler *client) +ServerInfo_Room *Server_Room::getInfo(bool complete) const +{ + QList gameList; + QList userList; + qDebug() << "getInfo: complete=" << complete; + if (complete) { + QMapIterator gameIterator(games); + while (gameIterator.hasNext()) + gameList.append(gameIterator.next().value()->getInfo()); + + for (int i = 0; i < size(); ++i) + userList.append(new ServerInfo_User(at(i)->getUserInfo(), false)); + } + + return new ServerInfo_Room(id, name, description, games.size(), size(), autoJoin, gameList, userList); +} + +void Server_Room::addClient(Server_ProtocolHandler *client) { sendRoomEvent(new Event_JoinRoom(id, new ServerInfo_User(client->getUserInfo()))); append(client); @@ -22,7 +40,6 @@ QList Server_Room::addClient(Server_ProtocolHandler *client) eventUserList.append(new ServerInfo_User(at(i)->getUserInfo())); emit roomInfoChanged(); - return eventUserList; } void Server_Room::removeClient(Server_ProtocolHandler *client) diff --git a/common/server_room.h b/common/server_room.h index 4f6cc46f..a22893b8 100644 --- a/common/server_room.h +++ b/common/server_room.h @@ -9,6 +9,7 @@ class Server_ProtocolHandler; class RoomEvent; class ServerInfo_User; +class ServerInfo_Room; class Server_Game; class Server; @@ -35,8 +36,9 @@ public: bool getAutoJoin() const { return autoJoin; } const QMap &getGames() const { return games; } Server *getServer() const; + ServerInfo_Room *getInfo(bool complete) const; - QList addClient(Server_ProtocolHandler *client); + void addClient(Server_ProtocolHandler *client); void removeClient(Server_ProtocolHandler *client); void say(Server_ProtocolHandler *client, const QString &s); void broadcastGameListUpdate(Server_Game *game); diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index b196b84d..e5ec8488 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -64,7 +64,7 @@ Servatrice::Servatrice(QObject *parent) } settings->endArray(); - loginMessage = settings->value("messages/login").toString(); + updateLoginMessage(); maxGameInactivityTime = settings->value("game/max_game_inactivity_time").toInt(); maxPlayerInactivityTime = settings->value("game/max_player_inactivity_time").toInt(); @@ -185,6 +185,16 @@ ServerInfo_User *Servatrice::getUserData(const QString &name) return new ServerInfo_User(name, ServerInfo_User::IsUser); } +void Servatrice::updateLoginMessage() +{ + checkSql(); + QSqlQuery query; + query.prepare("select message from " + dbPrefix + "_servermessages order by timest desc limit 1"); + if (execSqlQuery(query)) + if (query.next()) + loginMessage = query.value(0).toString(); +} + void Servatrice::statusUpdate() { uptime += statusUpdateClock->interval() / 1000; diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index 39a1a1a6..479af4fd 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -46,6 +46,7 @@ public: int getMaxGameInactivityTime() const { return maxGameInactivityTime; } int getMaxPlayerInactivityTime() const { return maxPlayerInactivityTime; } QString getDbPrefix() const { return dbPrefix; } + void updateLoginMessage(); protected: AuthenticationResult checkUserPassword(const QString &user, const QString &password); ServerInfo_User *getUserData(const QString &name);