implemented direct chat

This commit is contained in:
Max-Wilhelm Bruker 2010-09-18 23:47:39 +02:00
parent a8e166b609
commit e597325ec3
24 changed files with 821 additions and 335 deletions

View file

@ -33,9 +33,12 @@ void AbstractClient::processProtocolItem(ProtocolItem *item)
if (genericEvent) {
switch (genericEvent->getItemId()) {
case ItemId_Event_ListGames: emit listGamesEventReceived(qobject_cast<Event_ListGames *>(item)); break;
case ItemId_Event_UserJoined: emit userJoinedEventReceived(qobject_cast<Event_UserJoined *>(item)); break;
case ItemId_Event_UserLeft: emit userLeftEventReceived(qobject_cast<Event_UserLeft *>(item)); break;
case ItemId_Event_ServerMessage: emit serverMessageEventReceived(qobject_cast<Event_ServerMessage *>(item)); break;
case ItemId_Event_ListChatChannels: emit listChatChannelsEventReceived(qobject_cast<Event_ListChatChannels *>(item)); break;
case ItemId_Event_GameJoined: emit gameJoinedEventReceived(qobject_cast<Event_GameJoined *>(item)); break;
case ItemId_Event_Message: emit messageEventReceived(qobject_cast<Event_Message *>(item)); break;
}
if (genericEvent->getReceiverMayDelete())
delete genericEvent;

View file

@ -13,9 +13,12 @@ class CommandContainer;
class ChatEvent;
class GameEventContainer;
class Event_ListGames;
class Event_UserJoined;
class Event_UserLeft;
class Event_ServerMessage;
class Event_ListChatChannels;
class Event_GameJoined;
class Event_Message;
enum ClientStatus {
StatusDisconnected,
@ -38,9 +41,12 @@ signals:
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 gameJoinedEventReceived(Event_GameJoined *event);
void messageEventReceived(Event_Message *event);
protected slots:
void processProtocolItem(ProtocolItem *item);
protected:

View file

@ -2,6 +2,7 @@
#include <QPainter>
#include <QSvgRenderer>
#include <math.h>
#include <QDebug>
QPixmap PingPixmapGenerator::generatePixmap(int size, int value, int max)
{
@ -39,11 +40,13 @@ QPixmap CountryPixmapGenerator::generatePixmap(int height, const QString &countr
return pmCache.value(key);
QSvgRenderer svg(QString(":/resources/countries/" + countryCode + ".svg"));
double aspect = (double) svg.defaultSize().width() / (double) svg.defaultSize().height();
QPixmap pixmap((int) round(aspect * height), height);
int width = (int) round(height * (double) svg.defaultSize().width() / (double) svg.defaultSize().height());
QPixmap pixmap(width, height);
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
svg.render(&painter, QRectF(0, 0, aspect * height, height));
svg.render(&painter, QRectF(0, 0, width, height));
painter.setPen(Qt::black);
painter.drawRect(0.5, 0.5, width - 1, height - 1);
pmCache.insert(key, pixmap);
return pixmap;

View file

@ -466,7 +466,7 @@ void Player::actMoveTopCardsToGrave()
void Player::actMoveTopCardsToExile()
{
int number = QInputDialog::getInteger(0, tr("Move top cards to grave"), tr("Number:"));
int number = QInputDialog::getInteger(0, tr("Move top cards to exile"), tr("Number:"));
if (!number)
return;

View file

@ -13,6 +13,7 @@ PlayerListWidget::PlayerListWidget(QWidget *parent)
playerIcon = QIcon(":/resources/icon_player.svg");
spectatorIcon = QIcon(":/resources/icon_spectator.svg");
setIconSize(QSize(20, 15));
setColumnCount(5);
setRootIsDecorated(false);
setSelectionMode(NoSelection);
@ -47,7 +48,7 @@ void PlayerListWidget::updatePlayerProperties(ServerInfo_PlayerProperties *prop)
player->setIcon(2, gameStarted ? (prop->getConceded() ? concededIcon : QIcon()) : (prop->getReadyStart() ? readyIcon : notReadyIcon));
player->setText(3, prop->getUserInfo()->getName());
if (!prop->getUserInfo()->getCountry().isEmpty())
player->setIcon(3, QIcon(CountryPixmapGenerator::generatePixmap(10, prop->getUserInfo()->getCountry())));
player->setIcon(3, QIcon(CountryPixmapGenerator::generatePixmap(12, prop->getUserInfo()->getCountry())));
QString deckText;
if (!prop->getSpectator())

View file

@ -49,6 +49,14 @@ void TabChatChannel::retranslateUi()
aLeaveChannel->setText(tr("&Leave channel"));
}
QString TabChatChannel::sanitizeHtml(QString dirty) const
{
return dirty
.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;");
}
void TabChatChannel::sendMessage()
{
if (sayEdit->text().isEmpty())
@ -84,14 +92,14 @@ void TabChatChannel::processListPlayersEvent(Event_ChatListPlayers *event)
void TabChatChannel::processJoinChannelEvent(Event_ChatJoinChannel *event)
{
textEdit->append(tr("%1 has joined the channel.").arg(event->getUserInfo()->getName()));
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(event->getPlayerName()));
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);
@ -103,8 +111,8 @@ void TabChatChannel::processLeaveChannelEvent(Event_ChatLeaveChannel *event)
void TabChatChannel::processSayEvent(Event_ChatSay *event)
{
if (event->getPlayerName().isEmpty())
textEdit->append(QString("<font color=\"blue\">%1</font").arg(event->getMessage()));
textEdit->append(QString("<font color=\"blue\">%1</font").arg(sanitizeHtml(event->getMessage())));
else
textEdit->append(QString("<font color=\"red\">%1:</font> %2").arg(event->getPlayerName()).arg(event->getMessage()));
textEdit->append(QString("<font color=\"red\">%1:</font> %2").arg(sanitizeHtml(event->getPlayerName())).arg(sanitizeHtml(event->getMessage())));
emit userEvent();
}

View file

@ -24,6 +24,7 @@ private:
QLineEdit *sayEdit;
QAction *aLeaveChannel;
QString sanitizeHtml(QString dirty) const;
signals:
void channelClosing(TabChatChannel *tab);
private slots:

View file

@ -15,6 +15,8 @@
#include "abstractclient.h"
#include "protocol.h"
#include "protocol_items.h"
#include "pixmapgenerator.h"
#include <QDebug>
GameSelector::GameSelector(AbstractClient *_client, QWidget *parent)
: QGroupBox(parent), client(_client)
@ -235,23 +237,116 @@ void ServerMessageLog::processServerMessageEvent(Event_ServerMessage *event)
textEdit->append(event->getMessage());
}
UserList::UserList(AbstractClient *_client, QWidget *parent)
: QGroupBox(parent)
{
userTree = new QTreeWidget;
userTree->setColumnCount(2);
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(1, Qt::UserRole) == user->getName()) {
item = temp;
break;
}
}
if (!item) {
item = new QTreeWidgetItem;
userTree->addTopLevelItem(item);
retranslateUi();
}
item->setIcon(0, QIcon(CountryPixmapGenerator::generatePixmap(12, user->getCountry())));
item->setData(1, Qt::UserRole, user->getName());
item->setData(1, Qt::DisplayRole, user->getName());
}
void UserList::processResponse(ProtocolResponse *response)
{
Response_ListUsers *resp = qobject_cast<Response_ListUsers *>(response);
if (!resp)
return;
const QList<ServerInfo_User *> &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(1, 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(1, Qt::UserRole).toString(), true);
}
TabServer::TabServer(AbstractClient *_client, QWidget *parent)
: Tab(parent), client(_client)
{
gameSelector = new GameSelector(client);
chatChannelSelector = new ChatChannelSelector(client);
serverMessageLog = new ServerMessageLog(client);
userList = new UserList(client);
connect(gameSelector, SIGNAL(gameJoined(int)), this, SIGNAL(gameJoined(int)));
connect(chatChannelSelector, SIGNAL(channelJoined(const QString &)), this, SIGNAL(chatChannelJoined(const QString &)));
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);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(gameSelector);
mainLayout->addLayout(hbox);
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(gameSelector);
vbox->addLayout(hbox);
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addLayout(vbox, 3);
mainLayout->addWidget(userList, 1);
setLayout(mainLayout);
}
@ -261,4 +356,5 @@ void TabServer::retranslateUi()
gameSelector->retranslateUi();
chatChannelSelector->retranslateUi();
serverMessageLog->retranslateUi();
userList->retranslateUi();
}

View file

@ -8,6 +8,7 @@
class AbstractClient;
class QTreeView;
class QTreeWidget;
class QTreeWidgetItem;
class QPushButton;
class QCheckBox;
class QTextEdit;
@ -18,6 +19,9 @@ class GamesProxyModel;
class Event_ListGames;
class Event_ListChatChannels;
class Event_ServerMessage;
class Event_UserJoined;
class Event_UserLeft;
class ProtocolResponse;
class GameSelector : public QGroupBox {
Q_OBJECT
@ -72,16 +76,37 @@ public:
void retranslateUi();
};
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 TabServer : public Tab {
Q_OBJECT
signals:
void chatChannelJoined(const QString &channelName);
void gameJoined(int gameId);
void openMessageDialog(const QString &userName, bool focus);
void userLeft(const QString &userName);
private:
AbstractClient *client;
GameSelector *gameSelector;
ChatChannelSelector *chatChannelSelector;
ServerMessageLog *serverMessageLog;
UserList *userList;
public:
TabServer(AbstractClient *_client, QWidget *parent = 0);
void retranslateUi();

View file

@ -5,6 +5,7 @@
#include "tab_chatchannel.h"
#include "tab_game.h"
#include "tab_deck_storage.h"
#include "tab_message.h"
#include "protocol_items.h"
#include "pixmapgenerator.h"
#include <QDebug>
@ -56,10 +57,13 @@ void TabSupervisor::start(AbstractClient *_client)
connect(client, SIGNAL(chatEventReceived(ChatEvent *)), this, SLOT(processChatEvent(ChatEvent *)));
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(openMessageDialog(const QString &, bool)), this, SLOT(addMessageTab(const QString &, bool)));
connect(tabServer, SIGNAL(userLeft(const QString &)), this, SLOT(processUserLeft(const QString &)));
myAddTab(tabServer);
updatePingTime(0, -1);
@ -173,6 +177,25 @@ void TabSupervisor::chatChannelLeft(TabChatChannel *tab)
removeTab(indexOf(tab));
}
TabMessage *TabSupervisor::addMessageTab(const QString &userName, bool focus)
{
TabMessage *tab = new TabMessage(client, userName);
connect(tab, SIGNAL(talkClosing(TabMessage *)), this, SLOT(talkLeft(TabMessage *)));
myAddTab(tab);
messageTabs.insert(userName, tab);
if (focus)
setCurrentWidget(tab);
return tab;
}
void TabSupervisor::talkLeft(TabMessage *tab)
{
emit setMenu(0);
messageTabs.remove(tab->getUserName());
removeTab(indexOf(tab));
}
void TabSupervisor::tabUserEvent()
{
Tab *tab = static_cast<Tab *>(sender());
@ -200,6 +223,23 @@ void TabSupervisor::processGameEventContainer(GameEventContainer *cont)
qDebug() << "gameEvent: invalid gameId";
}
void TabSupervisor::processMessageEvent(Event_Message *event)
{
TabMessage *tab = messageTabs.value(event->getSenderName());
if (!tab)
tab = messageTabs.value(event->getReceiverName());
if (!tab)
tab = addMessageTab(event->getSenderName(), false);
tab->processMessageEvent(event);
}
void TabSupervisor::processUserLeft(const QString &userName)
{
TabMessage *tab = messageTabs.value(userName);
if (tab)
tab->processUserLeft(userName);
}
void TabSupervisor::updateCurrent(int index)
{
if (index != -1) {

View file

@ -11,9 +11,11 @@ class TabServer;
class TabChatChannel;
class TabGame;
class TabDeckStorage;
class TabMessage;
class ChatEvent;
class GameEventContainer;
class Event_GameJoined;
class Event_Message;
class TabSupervisor : public QTabWidget {
Q_OBJECT
@ -25,6 +27,7 @@ private:
TabDeckStorage *tabDeckStorage;
QMap<QString, TabChatChannel *> chatChannelTabs;
QMap<int, TabGame *> gameTabs;
QMap<QString, TabMessage *> messageTabs;
void myAddTab(Tab *tab);
public:
TabSupervisor(QWidget *parent = 0);
@ -45,9 +48,13 @@ private slots:
void gameLeft(TabGame *tab);
void addChatChannelTab(const QString &channelName);
void chatChannelLeft(TabChatChannel *tab);
TabMessage *addMessageTab(const QString &userName, bool focus);
void processUserLeft(const QString &userName);
void talkLeft(TabMessage *tab);
void tabUserEvent();
void processChatEvent(ChatEvent *event);
void processGameEventContainer(GameEventContainer *cont);
void processMessageEvent(Event_Message *event);
};
#endif