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

@ -52,6 +52,7 @@ HEADERS += src/counter.h \
src/tab.h \ src/tab.h \
src/tab_server.h \ src/tab_server.h \
src/tab_chatchannel.h \ src/tab_chatchannel.h \
src/tab_message.h \
src/tab_game.h \ src/tab_game.h \
src/tab_deck_storage.h \ src/tab_deck_storage.h \
src/tab_supervisor.h \ src/tab_supervisor.h \
@ -125,6 +126,7 @@ SOURCES += src/counter.cpp \
src/arrowtarget.cpp \ src/arrowtarget.cpp \
src/tab_server.cpp \ src/tab_server.cpp \
src/tab_chatchannel.cpp \ src/tab_chatchannel.cpp \
src/tab_message.cpp \
src/tab_game.cpp \ src/tab_game.cpp \
src/tab_deck_storage.cpp \ src/tab_deck_storage.cpp \
src/tab_supervisor.cpp \ src/tab_supervisor.cpp \

View file

@ -33,9 +33,12 @@ void AbstractClient::processProtocolItem(ProtocolItem *item)
if (genericEvent) { if (genericEvent) {
switch (genericEvent->getItemId()) { switch (genericEvent->getItemId()) {
case ItemId_Event_ListGames: emit listGamesEventReceived(qobject_cast<Event_ListGames *>(item)); break; 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_ServerMessage: emit serverMessageEventReceived(qobject_cast<Event_ServerMessage *>(item)); break;
case ItemId_Event_ListChatChannels: emit listChatChannelsEventReceived(qobject_cast<Event_ListChatChannels *>(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_GameJoined: emit gameJoinedEventReceived(qobject_cast<Event_GameJoined *>(item)); break;
case ItemId_Event_Message: emit messageEventReceived(qobject_cast<Event_Message *>(item)); break;
} }
if (genericEvent->getReceiverMayDelete()) if (genericEvent->getReceiverMayDelete())
delete genericEvent; delete genericEvent;

View file

@ -13,9 +13,12 @@ class CommandContainer;
class ChatEvent; class ChatEvent;
class GameEventContainer; class GameEventContainer;
class Event_ListGames; class Event_ListGames;
class Event_UserJoined;
class Event_UserLeft;
class Event_ServerMessage; class Event_ServerMessage;
class Event_ListChatChannels; class Event_ListChatChannels;
class Event_GameJoined; class Event_GameJoined;
class Event_Message;
enum ClientStatus { enum ClientStatus {
StatusDisconnected, StatusDisconnected,
@ -38,9 +41,12 @@ signals:
void gameEventContainerReceived(GameEventContainer *event); void gameEventContainerReceived(GameEventContainer *event);
// Generic events // Generic events
void listGamesEventReceived(Event_ListGames *event); void listGamesEventReceived(Event_ListGames *event);
void userJoinedEventReceived(Event_UserJoined *event);
void userLeftEventReceived(Event_UserLeft *event);
void serverMessageEventReceived(Event_ServerMessage *event); void serverMessageEventReceived(Event_ServerMessage *event);
void listChatChannelsEventReceived(Event_ListChatChannels *event); void listChatChannelsEventReceived(Event_ListChatChannels *event);
void gameJoinedEventReceived(Event_GameJoined *event); void gameJoinedEventReceived(Event_GameJoined *event);
void messageEventReceived(Event_Message *event);
protected slots: protected slots:
void processProtocolItem(ProtocolItem *item); void processProtocolItem(ProtocolItem *item);
protected: protected:

View file

@ -2,6 +2,7 @@
#include <QPainter> #include <QPainter>
#include <QSvgRenderer> #include <QSvgRenderer>
#include <math.h> #include <math.h>
#include <QDebug>
QPixmap PingPixmapGenerator::generatePixmap(int size, int value, int max) 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); return pmCache.value(key);
QSvgRenderer svg(QString(":/resources/countries/" + countryCode + ".svg")); QSvgRenderer svg(QString(":/resources/countries/" + countryCode + ".svg"));
double aspect = (double) svg.defaultSize().width() / (double) svg.defaultSize().height(); int width = (int) round(height * (double) svg.defaultSize().width() / (double) svg.defaultSize().height());
QPixmap pixmap((int) round(aspect * height), height); QPixmap pixmap(width, height);
pixmap.fill(Qt::transparent); pixmap.fill(Qt::transparent);
QPainter painter(&pixmap); 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); pmCache.insert(key, pixmap);
return pixmap; return pixmap;

View file

@ -466,7 +466,7 @@ void Player::actMoveTopCardsToGrave()
void Player::actMoveTopCardsToExile() 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) if (!number)
return; return;

View file

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

View file

@ -49,6 +49,14 @@ void TabChatChannel::retranslateUi()
aLeaveChannel->setText(tr("&Leave channel")); aLeaveChannel->setText(tr("&Leave channel"));
} }
QString TabChatChannel::sanitizeHtml(QString dirty) const
{
return dirty
.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;");
}
void TabChatChannel::sendMessage() void TabChatChannel::sendMessage()
{ {
if (sayEdit->text().isEmpty()) if (sayEdit->text().isEmpty())
@ -84,14 +92,14 @@ void TabChatChannel::processListPlayersEvent(Event_ChatListPlayers *event)
void TabChatChannel::processJoinChannelEvent(Event_ChatJoinChannel *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()); playerList->addItem(event->getUserInfo()->getName());
emit userEvent(); emit userEvent();
} }
void TabChatChannel::processLeaveChannelEvent(Event_ChatLeaveChannel *event) 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) for (int i = 0; i < playerList->count(); ++i)
if (playerList->item(i)->text() == event->getPlayerName()) { if (playerList->item(i)->text() == event->getPlayerName()) {
delete playerList->takeItem(i); delete playerList->takeItem(i);
@ -103,8 +111,8 @@ void TabChatChannel::processLeaveChannelEvent(Event_ChatLeaveChannel *event)
void TabChatChannel::processSayEvent(Event_ChatSay *event) void TabChatChannel::processSayEvent(Event_ChatSay *event)
{ {
if (event->getPlayerName().isEmpty()) 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 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(); emit userEvent();
} }

View file

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

View file

@ -15,6 +15,8 @@
#include "abstractclient.h" #include "abstractclient.h"
#include "protocol.h" #include "protocol.h"
#include "protocol_items.h" #include "protocol_items.h"
#include "pixmapgenerator.h"
#include <QDebug>
GameSelector::GameSelector(AbstractClient *_client, QWidget *parent) GameSelector::GameSelector(AbstractClient *_client, QWidget *parent)
: QGroupBox(parent), client(_client) : QGroupBox(parent), client(_client)
@ -235,23 +237,116 @@ void ServerMessageLog::processServerMessageEvent(Event_ServerMessage *event)
textEdit->append(event->getMessage()); 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) TabServer::TabServer(AbstractClient *_client, QWidget *parent)
: Tab(parent), client(_client) : Tab(parent), client(_client)
{ {
gameSelector = new GameSelector(client); gameSelector = new GameSelector(client);
chatChannelSelector = new ChatChannelSelector(client); chatChannelSelector = new ChatChannelSelector(client);
serverMessageLog = new ServerMessageLog(client); serverMessageLog = new ServerMessageLog(client);
userList = new UserList(client);
connect(gameSelector, SIGNAL(gameJoined(int)), this, SIGNAL(gameJoined(int))); connect(gameSelector, SIGNAL(gameJoined(int)), this, SIGNAL(gameJoined(int)));
connect(chatChannelSelector, SIGNAL(channelJoined(const QString &)), this, SIGNAL(chatChannelJoined(const QString &))); 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; QHBoxLayout *hbox = new QHBoxLayout;
hbox->addWidget(chatChannelSelector); hbox->addWidget(chatChannelSelector);
hbox->addWidget(serverMessageLog); hbox->addWidget(serverMessageLog);
QVBoxLayout *mainLayout = new QVBoxLayout; QVBoxLayout *vbox = new QVBoxLayout;
mainLayout->addWidget(gameSelector); vbox->addWidget(gameSelector);
mainLayout->addLayout(hbox); vbox->addLayout(hbox);
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addLayout(vbox, 3);
mainLayout->addWidget(userList, 1);
setLayout(mainLayout); setLayout(mainLayout);
} }
@ -261,4 +356,5 @@ void TabServer::retranslateUi()
gameSelector->retranslateUi(); gameSelector->retranslateUi();
chatChannelSelector->retranslateUi(); chatChannelSelector->retranslateUi();
serverMessageLog->retranslateUi(); serverMessageLog->retranslateUi();
userList->retranslateUi();
} }

View file

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

View file

@ -5,6 +5,7 @@
#include "tab_chatchannel.h" #include "tab_chatchannel.h"
#include "tab_game.h" #include "tab_game.h"
#include "tab_deck_storage.h" #include "tab_deck_storage.h"
#include "tab_message.h"
#include "protocol_items.h" #include "protocol_items.h"
#include "pixmapgenerator.h" #include "pixmapgenerator.h"
#include <QDebug> #include <QDebug>
@ -56,10 +57,13 @@ void TabSupervisor::start(AbstractClient *_client)
connect(client, SIGNAL(chatEventReceived(ChatEvent *)), this, SLOT(processChatEvent(ChatEvent *))); connect(client, SIGNAL(chatEventReceived(ChatEvent *)), this, SLOT(processChatEvent(ChatEvent *)));
connect(client, SIGNAL(gameEventContainerReceived(GameEventContainer *)), this, SLOT(processGameEventContainer(GameEventContainer *))); connect(client, SIGNAL(gameEventContainerReceived(GameEventContainer *)), this, SLOT(processGameEventContainer(GameEventContainer *)));
connect(client, SIGNAL(gameJoinedEventReceived(Event_GameJoined *)), this, SLOT(gameJoined(Event_GameJoined *))); 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))); connect(client, SIGNAL(maxPingTime(int, int)), this, SLOT(updatePingTime(int, int)));
tabServer = new TabServer(client); tabServer = new TabServer(client);
connect(tabServer, SIGNAL(chatChannelJoined(const QString &)), this, SLOT(addChatChannelTab(const QString &))); 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); myAddTab(tabServer);
updatePingTime(0, -1); updatePingTime(0, -1);
@ -173,6 +177,25 @@ void TabSupervisor::chatChannelLeft(TabChatChannel *tab)
removeTab(indexOf(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() void TabSupervisor::tabUserEvent()
{ {
Tab *tab = static_cast<Tab *>(sender()); Tab *tab = static_cast<Tab *>(sender());
@ -200,6 +223,23 @@ void TabSupervisor::processGameEventContainer(GameEventContainer *cont)
qDebug() << "gameEvent: invalid gameId"; 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) void TabSupervisor::updateCurrent(int index)
{ {
if (index != -1) { if (index != -1) {

View file

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

View file

@ -398,27 +398,27 @@
<context> <context>
<name>ChatChannelSelector</name> <name>ChatChannelSelector</name>
<message> <message>
<location filename="../src/tab_server.cpp" line="150"/> <location filename="../src/tab_server.cpp" line="152"/>
<source>Chat channels</source> <source>Chat channels</source>
<translation>Chaträume</translation> <translation>Chaträume</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="151"/> <location filename="../src/tab_server.cpp" line="153"/>
<source>Joi&amp;n</source> <source>Joi&amp;n</source>
<translation>Teil&amp;nehmen</translation> <translation>Teil&amp;nehmen</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="154"/> <location filename="../src/tab_server.cpp" line="156"/>
<source>Channel</source> <source>Channel</source>
<translation>Raum</translation> <translation>Raum</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="155"/> <location filename="../src/tab_server.cpp" line="157"/>
<source>Description</source> <source>Description</source>
<translation>Beschreibung</translation> <translation>Beschreibung</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="156"/> <location filename="../src/tab_server.cpp" line="158"/>
<source>Players</source> <source>Players</source>
<translation>Spieler</translation> <translation>Spieler</translation>
</message> </message>
@ -1162,20 +1162,20 @@
<context> <context>
<name>GameSelector</name> <name>GameSelector</name>
<message> <message>
<location filename="../src/tab_server.cpp" line="114"/> <location filename="../src/tab_server.cpp" line="116"/>
<source>C&amp;reate</source> <source>C&amp;reate</source>
<translation>Spiel e&amp;rstellen</translation> <translation>Spiel e&amp;rstellen</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="115"/> <location filename="../src/tab_server.cpp" line="117"/>
<source>&amp;Join</source> <source>&amp;Join</source>
<translation>&amp;Teilnehmen</translation> <translation>&amp;Teilnehmen</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="77"/>
<location filename="../src/tab_server.cpp" line="78"/>
<location filename="../src/tab_server.cpp" line="79"/> <location filename="../src/tab_server.cpp" line="79"/>
<location filename="../src/tab_server.cpp" line="80"/> <location filename="../src/tab_server.cpp" line="80"/>
<location filename="../src/tab_server.cpp" line="81"/>
<location filename="../src/tab_server.cpp" line="82"/>
<source>Error</source> <source>Error</source>
<translation>Fehler</translation> <translation>Fehler</translation>
</message> </message>
@ -1184,47 +1184,47 @@
<translation type="obsolete">XXX</translation> <translation type="obsolete">XXX</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="77"/> <location filename="../src/tab_server.cpp" line="79"/>
<source>Wrong password.</source> <source>Wrong password.</source>
<translation>Falsches Passwort.</translation> <translation>Falsches Passwort.</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="78"/> <location filename="../src/tab_server.cpp" line="80"/>
<source>Spectators are not allowed in this game.</source> <source>Spectators are not allowed in this game.</source>
<translation>In diesem Spiel sind keine Zuschauer zugelassen.</translation> <translation>In diesem Spiel sind keine Zuschauer zugelassen.</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="79"/> <location filename="../src/tab_server.cpp" line="81"/>
<source>The game is already full.</source> <source>The game is already full.</source>
<translation>Das Spiel ist bereits voll.</translation> <translation>Das Spiel ist bereits voll.</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="80"/> <location filename="../src/tab_server.cpp" line="82"/>
<source>The game does not exist any more.</source> <source>The game does not exist any more.</source>
<translation>Dieses Spiel gibt es nicht mehr.</translation> <translation>Dieses Spiel gibt es nicht mehr.</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="96"/> <location filename="../src/tab_server.cpp" line="98"/>
<source>Join game</source> <source>Join game</source>
<translation>Spiel beitreten</translation> <translation>Spiel beitreten</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="96"/> <location filename="../src/tab_server.cpp" line="98"/>
<source>Password:</source> <source>Password:</source>
<translation>Passwort:</translation> <translation>Passwort:</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="112"/> <location filename="../src/tab_server.cpp" line="114"/>
<source>Games</source> <source>Games</source>
<translation>Spiele</translation> <translation>Spiele</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="113"/> <location filename="../src/tab_server.cpp" line="115"/>
<source>&amp;Show full games</source> <source>&amp;Show full games</source>
<translation>&amp;Volle Spiele anzeigen</translation> <translation>&amp;Volle Spiele anzeigen</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="116"/> <location filename="../src/tab_server.cpp" line="118"/>
<source>J&amp;oin as spectator</source> <source>J&amp;oin as spectator</source>
<translation>&amp;Zuschauen</translation> <translation>&amp;Zuschauen</translation>
</message> </message>
@ -1810,27 +1810,37 @@
<translation>%1 legt %2%3 in sein Sideboard.</translation> <translation>%1 legt %2%3 in sein Sideboard.</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="207"/> <location filename="../src/messagelogwidget.cpp" line="208"/>
<source>%1 flips %2 face-down.</source>
<translation>%1 wendet %2 auf die Rückseite.</translation>
</message>
<message>
<location filename="../src/messagelogwidget.cpp" line="210"/>
<source>%1 flips %2 face-up.</source>
<translation>%1 wendet %2 auf die Vorderseite.</translation>
</message>
<message>
<location filename="../src/messagelogwidget.cpp" line="215"/>
<source>%1 destroys %2.</source> <source>%1 destroys %2.</source>
<translation>%1 zerstört %2.</translation> <translation>%1 zerstört %2.</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="212"/> <location filename="../src/messagelogwidget.cpp" line="220"/>
<source>%1 attaches %2 to %3&apos;s %4.</source> <source>%1 attaches %2 to %3&apos;s %4.</source>
<translation>%1 legt %2 an %3s %4 an.</translation> <translation>%1 legt %2 an %3s %4 an.</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="217"/> <location filename="../src/messagelogwidget.cpp" line="225"/>
<source>%1 unattaches %2.</source> <source>%1 unattaches %2.</source>
<translation>%1 löst %2 ab.</translation> <translation>%1 löst %2 ab.</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="222"/> <location filename="../src/messagelogwidget.cpp" line="230"/>
<source>%1 creates token: %2%3.</source> <source>%1 creates token: %2%3.</source>
<translation>%1 erstellt Token: %2%3.</translation> <translation>%1 erstellt Token: %2%3.</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="228"/> <location filename="../src/messagelogwidget.cpp" line="236"/>
<source>%1 points from %2&apos;s %3 to %4.</source> <source>%1 points from %2&apos;s %3 to %4.</source>
<translation>%1 zeigt von %2s %3 auf %4.</translation> <translation>%1 zeigt von %2s %3 auf %4.</translation>
</message> </message>
@ -1839,12 +1849,12 @@
<translation type="obsolete">%1 erstellt einen Spielstein: %2 (%3).</translation> <translation type="obsolete">%1 erstellt einen Spielstein: %2 (%3).</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="235"/> <location filename="../src/messagelogwidget.cpp" line="243"/>
<source>%1 points from %2&apos;s %3 to %4&apos;s %5.</source> <source>%1 points from %2&apos;s %3 to %4&apos;s %5.</source>
<translation>%1 zeigt von %2s %3 auf %4s %5.</translation> <translation>%1 zeigt von %2s %3 auf %4s %5.</translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
<location filename="../src/messagelogwidget.cpp" line="250"/> <location filename="../src/messagelogwidget.cpp" line="258"/>
<source>%1 places %n counter(s) (%2) on %3 (now %4).</source> <source>%1 places %n counter(s) (%2) on %3 (now %4).</source>
<translation> <translation>
<numerusform>%1 legt eine Marke (%2) auf %3 (jetzt %4).</numerusform> <numerusform>%1 legt eine Marke (%2) auf %3 (jetzt %4).</numerusform>
@ -1852,7 +1862,7 @@
</translation> </translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
<location filename="../src/messagelogwidget.cpp" line="252"/> <location filename="../src/messagelogwidget.cpp" line="260"/>
<source>%1 removes %n counter(s) (%2) from %3 (now %4).</source> <source>%1 removes %n counter(s) (%2) from %3 (now %4).</source>
<translation> <translation>
<numerusform>%1 entfernt eine Marke (%2) von %3 (jetzt %4).</numerusform> <numerusform>%1 entfernt eine Marke (%2) von %3 (jetzt %4).</numerusform>
@ -1860,37 +1870,37 @@
</translation> </translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="255"/> <location filename="../src/messagelogwidget.cpp" line="263"/>
<source>red</source> <source>red</source>
<translation>rot</translation> <translation>rot</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="256"/> <location filename="../src/messagelogwidget.cpp" line="264"/>
<source>yellow</source> <source>yellow</source>
<translation>gelb</translation> <translation>gelb</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="257"/> <location filename="../src/messagelogwidget.cpp" line="265"/>
<source>green</source> <source>green</source>
<translation>grün</translation> <translation>grün</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="276"/> <location filename="../src/messagelogwidget.cpp" line="284"/>
<source>%1 sets counter %2 to %3 (%4%5).</source> <source>%1 sets counter %2 to %3 (%4%5).</source>
<translation>%1 setzt Zähler %2 auf %3 (%4%5).</translation> <translation>%1 setzt Zähler %2 auf %3 (%4%5).</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="291"/> <location filename="../src/messagelogwidget.cpp" line="299"/>
<source>%1 sets PT of %2 to %3.</source> <source>%1 sets PT of %2 to %3.</source>
<translation>%1 setzt Kampfwerte von %2 auf %3.</translation> <translation>%1 setzt Kampfwerte von %2 auf %3.</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="296"/> <location filename="../src/messagelogwidget.cpp" line="304"/>
<source>%1 sets annotation of %2 to %3.</source> <source>%1 sets annotation of %2 to %3.</source>
<translation>%1 versieht %2 mit dem Hinweis %3.</translation> <translation>%1 versieht %2 mit dem Hinweis %3.</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="302"/> <location filename="../src/messagelogwidget.cpp" line="310"/>
<source>%1 is looking at the top %2 cards %3.</source> <source>%1 is looking at the top %2 cards %3.</source>
<translation>%1 sieht sich die obersten %2 Karten %3 an.</translation> <translation>%1 sieht sich die obersten %2 Karten %3 an.</translation>
</message> </message>
@ -1987,7 +1997,7 @@
<translation type="obsolete">%1 entfernt %2 Zählmarken von %3 (jetzt %4).</translation> <translation type="obsolete">%1 entfernt %2 Zählmarken von %3 (jetzt %4).</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="271"/> <location filename="../src/messagelogwidget.cpp" line="279"/>
<source>%1 %2 %3.</source> <source>%1 %2 %3.</source>
<translation>%1 %2 %3.</translation> <translation>%1 %2 %3.</translation>
</message> </message>
@ -2000,17 +2010,17 @@
<translation type="obsolete">%1 sieht sich die obersten %2 Karten %3 an.</translation> <translation type="obsolete">%1 sieht sich die obersten %2 Karten %3 an.</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="304"/> <location filename="../src/messagelogwidget.cpp" line="312"/>
<source>%1 is looking at %2.</source> <source>%1 is looking at %2.</source>
<translation>%1 sieht sich %2 an.</translation> <translation>%1 sieht sich %2 an.</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="310"/> <location filename="../src/messagelogwidget.cpp" line="318"/>
<source>%1 stops looking at %2.</source> <source>%1 stops looking at %2.</source>
<translation>%1 sieht sich %2 nicht mehr an.</translation> <translation>%1 sieht sich %2 nicht mehr an.</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="334"/> <location filename="../src/messagelogwidget.cpp" line="342"/>
<source>ending phase</source> <source>ending phase</source>
<translation>die Zugendphase</translation> <translation>die Zugendphase</translation>
</message> </message>
@ -2039,57 +2049,57 @@
<translation type="obsolete">%1 sieht sich %2s %3 nicht mehr an</translation> <translation type="obsolete">%1 sieht sich %2s %3 nicht mehr an</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="316"/> <location filename="../src/messagelogwidget.cpp" line="324"/>
<source>It is now %1&apos;s turn.</source> <source>It is now %1&apos;s turn.</source>
<translation>%1 ist am Zug.</translation> <translation>%1 ist am Zug.</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="324"/> <location filename="../src/messagelogwidget.cpp" line="332"/>
<source>untap step</source> <source>untap step</source>
<translation>das Enttappsegment</translation> <translation>das Enttappsegment</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="325"/> <location filename="../src/messagelogwidget.cpp" line="333"/>
<source>upkeep step</source> <source>upkeep step</source>
<translation>das Versorgungssegment</translation> <translation>das Versorgungssegment</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="326"/> <location filename="../src/messagelogwidget.cpp" line="334"/>
<source>draw step</source> <source>draw step</source>
<translation>das Ziehsegment</translation> <translation>das Ziehsegment</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="327"/> <location filename="../src/messagelogwidget.cpp" line="335"/>
<source>first main phase</source> <source>first main phase</source>
<translation>die erste Hauptphase</translation> <translation>die erste Hauptphase</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="328"/> <location filename="../src/messagelogwidget.cpp" line="336"/>
<source>beginning of combat step</source> <source>beginning of combat step</source>
<translation>das Anfangssegment der Kampfphase</translation> <translation>das Anfangssegment der Kampfphase</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="329"/> <location filename="../src/messagelogwidget.cpp" line="337"/>
<source>declare attackers step</source> <source>declare attackers step</source>
<translation>das Angreifer-Deklarieren-Segment</translation> <translation>das Angreifer-Deklarieren-Segment</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="330"/> <location filename="../src/messagelogwidget.cpp" line="338"/>
<source>declare blockers step</source> <source>declare blockers step</source>
<translation>das Blocker-Deklarieren-Segment</translation> <translation>das Blocker-Deklarieren-Segment</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="331"/> <location filename="../src/messagelogwidget.cpp" line="339"/>
<source>combat damage step</source> <source>combat damage step</source>
<translation>das Kampfschadenssegment</translation> <translation>das Kampfschadenssegment</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="332"/> <location filename="../src/messagelogwidget.cpp" line="340"/>
<source>end of combat step</source> <source>end of combat step</source>
<translation>das Endsegment der Kampfphase</translation> <translation>das Endsegment der Kampfphase</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="333"/> <location filename="../src/messagelogwidget.cpp" line="341"/>
<source>second main phase</source> <source>second main phase</source>
<translation>die zweite Hauptphase</translation> <translation>die zweite Hauptphase</translation>
</message> </message>
@ -2098,7 +2108,7 @@
<translation type="obsolete">das Ende-des-Zuges-Segment</translation> <translation type="obsolete">das Ende-des-Zuges-Segment</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="336"/> <location filename="../src/messagelogwidget.cpp" line="344"/>
<source>It is now the %1.</source> <source>It is now the %1.</source>
<translation>Es ist nun %1.</translation> <translation>Es ist nun %1.</translation>
</message> </message>
@ -2107,12 +2117,12 @@
<translation type="obsolete">%1 bewegt %2 %3 nach %4</translation> <translation type="obsolete">%1 bewegt %2 %3 nach %4</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="271"/> <location filename="../src/messagelogwidget.cpp" line="279"/>
<source>taps</source> <source>taps</source>
<translation>tappt</translation> <translation>tappt</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="271"/> <location filename="../src/messagelogwidget.cpp" line="279"/>
<source>untaps</source> <source>untaps</source>
<translation>enttappt</translation> <translation>enttappt</translation>
</message> </message>
@ -2137,7 +2147,7 @@
<translation type="obsolete">%1 entfernt %2 Zählmarken von %3 (jetzt %4)</translation> <translation type="obsolete">%1 entfernt %2 Zählmarken von %3 (jetzt %4)</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="268"/> <location filename="../src/messagelogwidget.cpp" line="276"/>
<source>his permanents</source> <source>his permanents</source>
<translation>seine bleibenden Karten</translation> <translation>seine bleibenden Karten</translation>
</message> </message>
@ -2150,12 +2160,12 @@
<translation type="obsolete">%1 setzt Zähler &quot;%2&quot; auf %3 (%4%5)</translation> <translation type="obsolete">%1 setzt Zähler &quot;%2&quot; auf %3 (%4%5)</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="283"/> <location filename="../src/messagelogwidget.cpp" line="291"/>
<source>%1 sets %2 to not untap normally.</source> <source>%1 sets %2 to not untap normally.</source>
<translation>%1 setzt %2 auf explizites Enttappen.</translation> <translation>%1 setzt %2 auf explizites Enttappen.</translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="285"/> <location filename="../src/messagelogwidget.cpp" line="293"/>
<source>%1 sets %2 to untap normally.</source> <source>%1 sets %2 to untap normally.</source>
<translation>%1 setzt %2 auf normales Enttappen.</translation> <translation>%1 setzt %2 auf normales Enttappen.</translation>
</message> </message>
@ -2260,41 +2270,51 @@
<context> <context>
<name>Player</name> <name>Player</name>
<message> <message>
<location filename="../src/player.cpp" line="290"/> <location filename="../src/player.cpp" line="297"/>
<location filename="../src/player.cpp" line="294"/> <location filename="../src/player.cpp" line="301"/>
<location filename="../src/player.cpp" line="298"/> <location filename="../src/player.cpp" line="305"/>
<source>Move to &amp;top of library</source> <source>Move to &amp;top of library</source>
<translation>Oben auf die Biblio&amp;thek legen</translation> <translation>Oben auf die Biblio&amp;thek legen</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="291"/> <location filename="../src/player.cpp" line="298"/>
<location filename="../src/player.cpp" line="295"/> <location filename="../src/player.cpp" line="302"/>
<location filename="../src/player.cpp" line="299"/> <location filename="../src/player.cpp" line="306"/>
<source>Move to &amp;bottom of library</source> <source>Move to &amp;bottom of library</source>
<translation>Unter die &amp;Bibliothek legen</translation> <translation>Unter die &amp;Bibliothek legen</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="302"/> <location filename="../src/player.cpp" line="309"/>
<source>&amp;View library</source> <source>&amp;View library</source>
<translation>&amp;Zeige Bibliothek</translation> <translation>&amp;Zeige Bibliothek</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="337"/> <location filename="../src/player.cpp" line="316"/>
<source>Move top cards to g&amp;raveyard...</source>
<translation>Oberste Karten in den F&amp;riedhof legen...</translation>
</message>
<message>
<location filename="../src/player.cpp" line="317"/>
<source>Move top cards to &amp;exile...</source>
<translation>Oberste Karten ins &amp;Exil schicken...</translation>
</message>
<message>
<location filename="../src/player.cpp" line="346"/>
<source>F3</source> <source>F3</source>
<translation>F3</translation> <translation>F3</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="303"/> <location filename="../src/player.cpp" line="310"/>
<source>View &amp;top cards of library...</source> <source>View &amp;top cards of library...</source>
<translation>Zeige die oberen Kar&amp;ten der Bibliothek...</translation> <translation>Zeige die oberen Kar&amp;ten der Bibliothek...</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="283"/> <location filename="../src/player.cpp" line="290"/>
<source>&amp;View graveyard</source> <source>&amp;View graveyard</source>
<translation>&amp;Zeige Friedhof</translation> <translation>&amp;Zeige Friedhof</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="339"/> <location filename="../src/player.cpp" line="348"/>
<source>F4</source> <source>F4</source>
<translation>F4</translation> <translation>F4</translation>
</message> </message>
@ -2303,32 +2323,32 @@
<translation type="obsolete">Zeige ent&amp;fernte Karten</translation> <translation type="obsolete">Zeige ent&amp;fernte Karten</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="304"/> <location filename="../src/player.cpp" line="311"/>
<source>&amp;View sideboard</source> <source>&amp;View sideboard</source>
<translation>Zeige &amp;Sideboard</translation> <translation>Zeige &amp;Sideboard</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="285"/> <location filename="../src/player.cpp" line="292"/>
<source>Player &quot;%1&quot;</source> <source>Player &quot;%1&quot;</source>
<translation>Spieler &quot;%1&quot;</translation> <translation>Spieler &quot;%1&quot;</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="307"/> <location filename="../src/player.cpp" line="314"/>
<source>Take &amp;mulligan</source> <source>Take &amp;mulligan</source>
<translation>&amp;Mulligan nehmen</translation> <translation>&amp;Mulligan nehmen</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="310"/> <location filename="../src/player.cpp" line="319"/>
<source>&amp;Hand</source> <source>&amp;Hand</source>
<translation>&amp;Hand</translation> <translation>&amp;Hand</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="312"/> <location filename="../src/player.cpp" line="321"/>
<source>&amp;Library</source> <source>&amp;Library</source>
<translation>Bib&amp;liothek</translation> <translation>Bib&amp;liothek</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="286"/> <location filename="../src/player.cpp" line="293"/>
<source>&amp;Graveyard</source> <source>&amp;Graveyard</source>
<translation>&amp;Friedhof</translation> <translation>&amp;Friedhof</translation>
</message> </message>
@ -2337,7 +2357,7 @@
<translation type="obsolete">Entfe&amp;rnte Karten</translation> <translation type="obsolete">Entfe&amp;rnte Karten</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="311"/> <location filename="../src/player.cpp" line="320"/>
<source>&amp;Sideboard</source> <source>&amp;Sideboard</source>
<translation>&amp;Sideboard</translation> <translation>&amp;Sideboard</translation>
</message> </message>
@ -2350,65 +2370,65 @@
<translation type="obsolete">&amp;Hinweis setzen...</translation> <translation type="obsolete">&amp;Hinweis setzen...</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="399"/> <location filename="../src/player.cpp" line="408"/>
<source>View top cards of library</source> <source>View top cards of library</source>
<translation>Zeige die obersten Karten der Bibliothek</translation> <translation>Zeige die obersten Karten der Bibliothek</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="399"/> <location filename="../src/player.cpp" line="408"/>
<source>Number of cards:</source> <source>Number of cards:</source>
<translation>Anzahl der Karten:</translation> <translation>Anzahl der Karten:</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="305"/> <location filename="../src/player.cpp" line="312"/>
<source>&amp;Draw card</source> <source>&amp;Draw card</source>
<translation>Karte &amp;ziehen</translation> <translation>Karte &amp;ziehen</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="284"/> <location filename="../src/player.cpp" line="291"/>
<source>&amp;View exile</source> <source>&amp;View exile</source>
<translation>&amp;Zeige Exil</translation> <translation>&amp;Zeige Exil</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="287"/> <location filename="../src/player.cpp" line="294"/>
<source>&amp;Exile</source> <source>&amp;Exile</source>
<translation>&amp;Exil</translation> <translation>&amp;Exil</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="296"/> <location filename="../src/player.cpp" line="303"/>
<location filename="../src/player.cpp" line="300"/> <location filename="../src/player.cpp" line="307"/>
<source>Move to &amp;hand</source> <source>Move to &amp;hand</source>
<translation>auf die &amp;Hand nehmen</translation> <translation>auf die &amp;Hand nehmen</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="292"/> <location filename="../src/player.cpp" line="299"/>
<location filename="../src/player.cpp" line="301"/> <location filename="../src/player.cpp" line="308"/>
<source>Move to g&amp;raveyard</source> <source>Move to g&amp;raveyard</source>
<translation>auf den &amp;Friedhof legen</translation> <translation>auf den &amp;Friedhof legen</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="293"/> <location filename="../src/player.cpp" line="300"/>
<location filename="../src/player.cpp" line="297"/> <location filename="../src/player.cpp" line="304"/>
<source>Move to &amp;exile</source> <source>Move to &amp;exile</source>
<translation>ins &amp;Exil schicken</translation> <translation>ins &amp;Exil schicken</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="338"/> <location filename="../src/player.cpp" line="347"/>
<source>Ctrl+W</source> <source>Ctrl+W</source>
<translation>Ctrl+W</translation> <translation>Ctrl+W</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="340"/> <location filename="../src/player.cpp" line="349"/>
<source>Ctrl+D</source> <source>Ctrl+D</source>
<translation>Ctrl+D</translation> <translation>Ctrl+D</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="306"/> <location filename="../src/player.cpp" line="313"/>
<source>D&amp;raw cards...</source> <source>D&amp;raw cards...</source>
<translation>Ka&amp;rten ziehen...</translation> <translation>Ka&amp;rten ziehen...</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="341"/> <location filename="../src/player.cpp" line="350"/>
<source>Ctrl+E</source> <source>Ctrl+E</source>
<translation>Ctrl+E</translation> <translation>Ctrl+E</translation>
</message> </message>
@ -2417,32 +2437,32 @@
<translation type="obsolete">&amp;Mulligan nehmen...</translation> <translation type="obsolete">&amp;Mulligan nehmen...</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="342"/> <location filename="../src/player.cpp" line="351"/>
<source>Ctrl+M</source> <source>Ctrl+M</source>
<translation>Ctrl+M</translation> <translation>Ctrl+M</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="308"/> <location filename="../src/player.cpp" line="315"/>
<source>&amp;Shuffle</source> <source>&amp;Shuffle</source>
<translation>Mi&amp;schen</translation> <translation>Mi&amp;schen</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="343"/> <location filename="../src/player.cpp" line="352"/>
<source>Ctrl+S</source> <source>Ctrl+S</source>
<translation>Ctrl+S</translation> <translation>Ctrl+S</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="313"/> <location filename="../src/player.cpp" line="322"/>
<source>&amp;Counters</source> <source>&amp;Counters</source>
<translation>&amp;Zähler</translation> <translation>&amp;Zähler</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="315"/> <location filename="../src/player.cpp" line="324"/>
<source>&amp;Untap all permanents</source> <source>&amp;Untap all permanents</source>
<translation>&amp;Enttappe alle bleibenden Karten</translation> <translation>&amp;Enttappe alle bleibenden Karten</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="344"/> <location filename="../src/player.cpp" line="353"/>
<source>Ctrl+U</source> <source>Ctrl+U</source>
<translation>Ctrl+U</translation> <translation>Ctrl+U</translation>
</message> </message>
@ -2471,42 +2491,42 @@
<translation type="obsolete">Ctrl+L</translation> <translation type="obsolete">Ctrl+L</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="316"/> <location filename="../src/player.cpp" line="325"/>
<source>R&amp;oll die...</source> <source>R&amp;oll die...</source>
<translation>&amp;Würfeln...</translation> <translation>&amp;Würfeln...</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="345"/> <location filename="../src/player.cpp" line="354"/>
<source>Ctrl+I</source> <source>Ctrl+I</source>
<translation>Ctrl+I</translation> <translation>Ctrl+I</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="317"/> <location filename="../src/player.cpp" line="326"/>
<source>&amp;Create token...</source> <source>&amp;Create token...</source>
<translation>Spiels&amp;tein erstellen...</translation> <translation>Spiels&amp;tein erstellen...</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="346"/> <location filename="../src/player.cpp" line="355"/>
<source>Ctrl+T</source> <source>Ctrl+T</source>
<translation>Ctrl+T</translation> <translation>Ctrl+T</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="318"/> <location filename="../src/player.cpp" line="327"/>
<source>C&amp;reate another token</source> <source>C&amp;reate another token</source>
<translation>&amp;Noch einen Spielstein erstellen</translation> <translation>&amp;Noch einen Spielstein erstellen</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="347"/> <location filename="../src/player.cpp" line="356"/>
<source>Ctrl+G</source> <source>Ctrl+G</source>
<translation>Ctrl+G</translation> <translation>Ctrl+G</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="319"/> <location filename="../src/player.cpp" line="328"/>
<source>S&amp;ay</source> <source>S&amp;ay</source>
<translation>S&amp;agen</translation> <translation>S&amp;agen</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="325"/> <location filename="../src/player.cpp" line="334"/>
<source>C&amp;ard</source> <source>C&amp;ard</source>
<translation>&amp;Karte</translation> <translation>&amp;Karte</translation>
</message> </message>
@ -2599,38 +2619,50 @@
<translation type="obsolete">F10</translation> <translation type="obsolete">F10</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="438"/> <location filename="../src/player.cpp" line="447"/>
<source>Draw cards</source> <source>Draw cards</source>
<translation>Karten ziehen</translation> <translation>Karten ziehen</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="438"/> <location filename="../src/player.cpp" line="447"/>
<location filename="../src/player.cpp" line="1185"/> <location filename="../src/player.cpp" line="454"/>
<location filename="../src/player.cpp" line="469"/>
<location filename="../src/player.cpp" line="1242"/>
<source>Number:</source> <source>Number:</source>
<translation>Anzahl:</translation> <translation>Anzahl:</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="1103"/> <location filename="../src/player.cpp" line="454"/>
<source>Move top cards to grave</source>
<translation>Oberste Karten in den Friedhof legen</translation>
</message>
<message>
<location filename="../src/player.cpp" line="469"/>
<source>Move top cards to exile</source>
<translation>Oberste Karten ins Exil schicken</translation>
</message>
<message>
<location filename="../src/player.cpp" line="1160"/>
<source>Set power/toughness</source> <source>Set power/toughness</source>
<translation>Kampfwerte setzen</translation> <translation>Kampfwerte setzen</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="1103"/> <location filename="../src/player.cpp" line="1160"/>
<source>Please enter the new PT:</source> <source>Please enter the new PT:</source>
<translation>Bitte die neuen Kampfwerte eingeben:</translation> <translation>Bitte die neuen Kampfwerte eingeben:</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="1129"/> <location filename="../src/player.cpp" line="1186"/>
<source>Set annotation</source> <source>Set annotation</source>
<translation>Hinweis setzen</translation> <translation>Hinweis setzen</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="1129"/> <location filename="../src/player.cpp" line="1186"/>
<source>Please enter the new annotation:</source> <source>Please enter the new annotation:</source>
<translation>Bitte den Hinweis eingeben:</translation> <translation>Bitte den Hinweis eingeben:</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="1185"/> <location filename="../src/player.cpp" line="1242"/>
<source>Set counters</source> <source>Set counters</source>
<translation>Setze Zählmarken</translation> <translation>Setze Zählmarken</translation>
</message> </message>
@ -2643,12 +2675,12 @@
<translation type="obsolete">Neue Lebenspunkte insgesamt:</translation> <translation type="obsolete">Neue Lebenspunkte insgesamt:</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="451"/> <location filename="../src/player.cpp" line="490"/>
<source>Roll die</source> <source>Roll die</source>
<translation>Würfeln</translation> <translation>Würfeln</translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="451"/> <location filename="../src/player.cpp" line="490"/>
<source>Number of sides:</source> <source>Number of sides:</source>
<translation>Anzahl der Seiten:</translation> <translation>Anzahl der Seiten:</translation>
</message> </message>
@ -2664,29 +2696,41 @@
<context> <context>
<name>PlayerListWidget</name> <name>PlayerListWidget</name>
<message> <message>
<location filename="../src/playerlistwidget.cpp" line="27"/> <location filename="../src/playerlistwidget.cpp" line="29"/>
<source>Player name</source> <source>Player name</source>
<translation>Spielername</translation> <translation>Spielername</translation>
</message> </message>
<message> <message>
<location filename="../src/playerlistwidget.cpp" line="28"/> <location filename="../src/playerlistwidget.cpp" line="30"/>
<source>Deck</source> <source>Deck</source>
<translation>Deck</translation> <translation>Deck</translation>
</message> </message>
<message> <message>
<location filename="../src/playerlistwidget.cpp" line="52"/> <location filename="../src/playerlistwidget.cpp" line="56"/>
<source>---</source>
<translation>---</translation>
</message>
<message>
<location filename="../src/playerlistwidget.cpp" line="57"/>
<source>local</source>
<translation>lokal</translation>
</message>
<message>
<location filename="../src/playerlistwidget.cpp" line="58"/>
<source>#%1</source>
<translation>#%1</translation>
</message>
<message>
<source>no deck</source> <source>no deck</source>
<translation>kein Deck</translation> <translation type="obsolete">kein Deck</translation>
</message> </message>
<message> <message>
<location filename="../src/playerlistwidget.cpp" line="53"/>
<source>local deck</source> <source>local deck</source>
<translation>lokales Deck</translation> <translation type="obsolete">lokales Deck</translation>
</message> </message>
<message> <message>
<location filename="../src/playerlistwidget.cpp" line="54"/>
<source>ID #%1</source> <source>ID #%1</source>
<translation>ID #%1</translation> <translation type="obsolete">ID #%1</translation>
</message> </message>
<message> <message>
<source>Role</source> <source>Role</source>
@ -2750,7 +2794,7 @@
<context> <context>
<name>ServerMessageLog</name> <name>ServerMessageLog</name>
<message> <message>
<location filename="../src/tab_server.cpp" line="230"/> <location filename="../src/tab_server.cpp" line="232"/>
<source>Server messages</source> <source>Server messages</source>
<translation>Servernachrichten</translation> <translation>Servernachrichten</translation>
</message> </message>
@ -2781,12 +2825,12 @@
<translation>Raum ver&amp;lassen</translation> <translation>Raum ver&amp;lassen</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_chatchannel.cpp" line="87"/> <location filename="../src/tab_chatchannel.cpp" line="95"/>
<source>%1 has joined the channel.</source> <source>%1 has joined the channel.</source>
<translation>%1 hat den Raum betreten.</translation> <translation>%1 hat den Raum betreten.</translation>
</message> </message>
<message> <message>
<location filename="../src/tab_chatchannel.cpp" line="94"/> <location filename="../src/tab_chatchannel.cpp" line="102"/>
<source>%1 has left the channel.</source> <source>%1 has left the channel.</source>
<translation>%1 hat den Raum verlassen.</translation> <translation>%1 hat den Raum verlassen.</translation>
</message> </message>
@ -2975,10 +3019,33 @@ Bitte geben Sie einen Namen ein:</translation>
<translation>Spiel %1: %2</translation> <translation>Spiel %1: %2</translation>
</message> </message>
</context> </context>
<context>
<name>TabMessage</name>
<message>
<location filename="../src/tab_message.cpp" line="40"/>
<source>Personal &amp;talk</source>
<translation>Persönliches &amp;Gespräch</translation>
</message>
<message>
<location filename="../src/tab_message.cpp" line="41"/>
<source>&amp;Leave</source>
<translation>Ver&amp;lassen</translation>
</message>
<message>
<location filename="../src/tab_message.cpp" line="75"/>
<source>%1 has left the server.</source>
<translation>%1 hat den Server verlassen.</translation>
</message>
<message>
<location filename="../src/tab_message.h" line="35"/>
<source>Talking to %1</source>
<translation>Gespräch mit %1</translation>
</message>
</context>
<context> <context>
<name>TabServer</name> <name>TabServer</name>
<message> <message>
<location filename="../src/tab_server.h" line="88"/> <location filename="../src/tab_server.h" line="113"/>
<source>Server</source> <source>Server</source>
<translation>Server</translation> <translation>Server</translation>
</message> </message>
@ -3011,6 +3078,14 @@ Bitte geben Sie einen Namen ein:</translation>
<translation>Karten durch &amp;Doppelklick ausspielen (statt Einzelklick)</translation> <translation>Karten durch &amp;Doppelklick ausspielen (statt Einzelklick)</translation>
</message> </message>
</context> </context>
<context>
<name>UserList</name>
<message>
<location filename="../src/tab_server.cpp" line="268"/>
<source>Users online: %1</source>
<translation>Benutzer online: %1</translation>
</message>
</context>
<context> <context>
<name>WndDeckEditor</name> <name>WndDeckEditor</name>
<message> <message>

View file

@ -352,27 +352,27 @@
<context> <context>
<name>ChatChannelSelector</name> <name>ChatChannelSelector</name>
<message> <message>
<location filename="../src/tab_server.cpp" line="150"/> <location filename="../src/tab_server.cpp" line="152"/>
<source>Chat channels</source> <source>Chat channels</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="151"/> <location filename="../src/tab_server.cpp" line="153"/>
<source>Joi&amp;n</source> <source>Joi&amp;n</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="154"/> <location filename="../src/tab_server.cpp" line="156"/>
<source>Channel</source> <source>Channel</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="155"/> <location filename="../src/tab_server.cpp" line="157"/>
<source>Description</source> <source>Description</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="156"/> <location filename="../src/tab_server.cpp" line="158"/>
<source>Players</source> <source>Players</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -785,65 +785,65 @@
<context> <context>
<name>GameSelector</name> <name>GameSelector</name>
<message> <message>
<location filename="../src/tab_server.cpp" line="114"/> <location filename="../src/tab_server.cpp" line="116"/>
<source>C&amp;reate</source> <source>C&amp;reate</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="115"/> <location filename="../src/tab_server.cpp" line="117"/>
<source>&amp;Join</source> <source>&amp;Join</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="77"/>
<location filename="../src/tab_server.cpp" line="78"/>
<location filename="../src/tab_server.cpp" line="79"/> <location filename="../src/tab_server.cpp" line="79"/>
<location filename="../src/tab_server.cpp" line="80"/> <location filename="../src/tab_server.cpp" line="80"/>
<location filename="../src/tab_server.cpp" line="81"/>
<location filename="../src/tab_server.cpp" line="82"/>
<source>Error</source> <source>Error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="77"/> <location filename="../src/tab_server.cpp" line="79"/>
<source>Wrong password.</source> <source>Wrong password.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="78"/> <location filename="../src/tab_server.cpp" line="80"/>
<source>Spectators are not allowed in this game.</source> <source>Spectators are not allowed in this game.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="79"/> <location filename="../src/tab_server.cpp" line="81"/>
<source>The game is already full.</source> <source>The game is already full.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="80"/> <location filename="../src/tab_server.cpp" line="82"/>
<source>The game does not exist any more.</source> <source>The game does not exist any more.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="96"/> <location filename="../src/tab_server.cpp" line="98"/>
<source>Join game</source> <source>Join game</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="96"/> <location filename="../src/tab_server.cpp" line="98"/>
<source>Password:</source> <source>Password:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="112"/> <location filename="../src/tab_server.cpp" line="114"/>
<source>Games</source> <source>Games</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="113"/> <location filename="../src/tab_server.cpp" line="115"/>
<source>&amp;Show full games</source> <source>&amp;Show full games</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_server.cpp" line="116"/> <location filename="../src/tab_server.cpp" line="118"/>
<source>J&amp;oin as spectator</source> <source>J&amp;oin as spectator</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -1220,22 +1220,32 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="212"/> <location filename="../src/messagelogwidget.cpp" line="208"/>
<source>%1 flips %2 face-down.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/messagelogwidget.cpp" line="210"/>
<source>%1 flips %2 face-up.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/messagelogwidget.cpp" line="220"/>
<source>%1 attaches %2 to %3&apos;s %4.</source> <source>%1 attaches %2 to %3&apos;s %4.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="217"/> <location filename="../src/messagelogwidget.cpp" line="225"/>
<source>%1 unattaches %2.</source> <source>%1 unattaches %2.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="235"/> <location filename="../src/messagelogwidget.cpp" line="243"/>
<source>%1 points from %2&apos;s %3 to %4&apos;s %5.</source> <source>%1 points from %2&apos;s %3 to %4&apos;s %5.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
<location filename="../src/messagelogwidget.cpp" line="250"/> <location filename="../src/messagelogwidget.cpp" line="258"/>
<source>%1 places %n counter(s) (%2) on %3 (now %4).</source> <source>%1 places %n counter(s) (%2) on %3 (now %4).</source>
<translation> <translation>
<numerusform>%1 places a counter (%2) on %3 (now %4).</numerusform> <numerusform>%1 places a counter (%2) on %3 (now %4).</numerusform>
@ -1243,7 +1253,7 @@
</translation> </translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
<location filename="../src/messagelogwidget.cpp" line="252"/> <location filename="../src/messagelogwidget.cpp" line="260"/>
<source>%1 removes %n counter(s) (%2) from %3 (now %4).</source> <source>%1 removes %n counter(s) (%2) from %3 (now %4).</source>
<translation> <translation>
<numerusform>%1 removes a counter (%2) from %3 (now %4).</numerusform> <numerusform>%1 removes a counter (%2) from %3 (now %4).</numerusform>
@ -1251,37 +1261,37 @@
</translation> </translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="255"/> <location filename="../src/messagelogwidget.cpp" line="263"/>
<source>red</source> <source>red</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="256"/> <location filename="../src/messagelogwidget.cpp" line="264"/>
<source>yellow</source> <source>yellow</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="257"/> <location filename="../src/messagelogwidget.cpp" line="265"/>
<source>green</source> <source>green</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="276"/> <location filename="../src/messagelogwidget.cpp" line="284"/>
<source>%1 sets counter %2 to %3 (%4%5).</source> <source>%1 sets counter %2 to %3 (%4%5).</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="291"/> <location filename="../src/messagelogwidget.cpp" line="299"/>
<source>%1 sets PT of %2 to %3.</source> <source>%1 sets PT of %2 to %3.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="296"/> <location filename="../src/messagelogwidget.cpp" line="304"/>
<source>%1 sets annotation of %2 to %3.</source> <source>%1 sets annotation of %2 to %3.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="302"/> <location filename="../src/messagelogwidget.cpp" line="310"/>
<source>%1 is looking at the top %2 cards %3.</source> <source>%1 is looking at the top %2 cards %3.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -1346,42 +1356,42 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="207"/> <location filename="../src/messagelogwidget.cpp" line="215"/>
<source>%1 destroys %2.</source> <source>%1 destroys %2.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="222"/> <location filename="../src/messagelogwidget.cpp" line="230"/>
<source>%1 creates token: %2%3.</source> <source>%1 creates token: %2%3.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="228"/> <location filename="../src/messagelogwidget.cpp" line="236"/>
<source>%1 points from %2&apos;s %3 to %4.</source> <source>%1 points from %2&apos;s %3 to %4.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="271"/> <location filename="../src/messagelogwidget.cpp" line="279"/>
<source>%1 %2 %3.</source> <source>%1 %2 %3.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="304"/> <location filename="../src/messagelogwidget.cpp" line="312"/>
<source>%1 is looking at %2.</source> <source>%1 is looking at %2.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="310"/> <location filename="../src/messagelogwidget.cpp" line="318"/>
<source>%1 stops looking at %2.</source> <source>%1 stops looking at %2.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="334"/> <location filename="../src/messagelogwidget.cpp" line="342"/>
<source>ending phase</source> <source>ending phase</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="316"/> <location filename="../src/messagelogwidget.cpp" line="324"/>
<source>It is now %1&apos;s turn.</source> <source>It is now %1&apos;s turn.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -1391,82 +1401,82 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="324"/> <location filename="../src/messagelogwidget.cpp" line="332"/>
<source>untap step</source> <source>untap step</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="325"/> <location filename="../src/messagelogwidget.cpp" line="333"/>
<source>upkeep step</source> <source>upkeep step</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="326"/> <location filename="../src/messagelogwidget.cpp" line="334"/>
<source>draw step</source> <source>draw step</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="327"/> <location filename="../src/messagelogwidget.cpp" line="335"/>
<source>first main phase</source> <source>first main phase</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="328"/> <location filename="../src/messagelogwidget.cpp" line="336"/>
<source>beginning of combat step</source> <source>beginning of combat step</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="329"/> <location filename="../src/messagelogwidget.cpp" line="337"/>
<source>declare attackers step</source> <source>declare attackers step</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="330"/> <location filename="../src/messagelogwidget.cpp" line="338"/>
<source>declare blockers step</source> <source>declare blockers step</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="331"/> <location filename="../src/messagelogwidget.cpp" line="339"/>
<source>combat damage step</source> <source>combat damage step</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="332"/> <location filename="../src/messagelogwidget.cpp" line="340"/>
<source>end of combat step</source> <source>end of combat step</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="333"/> <location filename="../src/messagelogwidget.cpp" line="341"/>
<source>second main phase</source> <source>second main phase</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="336"/> <location filename="../src/messagelogwidget.cpp" line="344"/>
<source>It is now the %1.</source> <source>It is now the %1.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="271"/> <location filename="../src/messagelogwidget.cpp" line="279"/>
<source>taps</source> <source>taps</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="271"/> <location filename="../src/messagelogwidget.cpp" line="279"/>
<source>untaps</source> <source>untaps</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="283"/> <location filename="../src/messagelogwidget.cpp" line="291"/>
<source>%1 sets %2 to not untap normally.</source> <source>%1 sets %2 to not untap normally.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="285"/> <location filename="../src/messagelogwidget.cpp" line="293"/>
<source>%1 sets %2 to untap normally.</source> <source>%1 sets %2 to untap normally.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/messagelogwidget.cpp" line="268"/> <location filename="../src/messagelogwidget.cpp" line="276"/>
<source>his permanents</source> <source>his permanents</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -1555,255 +1565,277 @@
<context> <context>
<name>Player</name> <name>Player</name>
<message> <message>
<location filename="../src/player.cpp" line="290"/> <location filename="../src/player.cpp" line="297"/>
<location filename="../src/player.cpp" line="294"/> <location filename="../src/player.cpp" line="301"/>
<location filename="../src/player.cpp" line="298"/> <location filename="../src/player.cpp" line="305"/>
<source>Move to &amp;top of library</source> <source>Move to &amp;top of library</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="291"/> <location filename="../src/player.cpp" line="298"/>
<location filename="../src/player.cpp" line="295"/> <location filename="../src/player.cpp" line="302"/>
<location filename="../src/player.cpp" line="299"/> <location filename="../src/player.cpp" line="306"/>
<source>Move to &amp;bottom of library</source> <source>Move to &amp;bottom of library</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="302"/> <location filename="../src/player.cpp" line="309"/>
<source>&amp;View library</source> <source>&amp;View library</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="337"/> <location filename="../src/player.cpp" line="346"/>
<source>F3</source> <source>F3</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="303"/> <location filename="../src/player.cpp" line="310"/>
<source>View &amp;top cards of library...</source> <source>View &amp;top cards of library...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="283"/> <location filename="../src/player.cpp" line="290"/>
<source>&amp;View graveyard</source> <source>&amp;View graveyard</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="339"/> <location filename="../src/player.cpp" line="348"/>
<source>F4</source> <source>F4</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="304"/> <location filename="../src/player.cpp" line="311"/>
<source>&amp;View sideboard</source> <source>&amp;View sideboard</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="285"/> <location filename="../src/player.cpp" line="292"/>
<source>Player &quot;%1&quot;</source> <source>Player &quot;%1&quot;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="310"/> <location filename="../src/player.cpp" line="319"/>
<source>&amp;Hand</source> <source>&amp;Hand</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="312"/> <location filename="../src/player.cpp" line="321"/>
<source>&amp;Library</source> <source>&amp;Library</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="286"/> <location filename="../src/player.cpp" line="293"/>
<source>&amp;Graveyard</source> <source>&amp;Graveyard</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="311"/> <location filename="../src/player.cpp" line="320"/>
<source>&amp;Sideboard</source> <source>&amp;Sideboard</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="399"/> <location filename="../src/player.cpp" line="408"/>
<source>View top cards of library</source> <source>View top cards of library</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="399"/> <location filename="../src/player.cpp" line="408"/>
<source>Number of cards:</source> <source>Number of cards:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="305"/> <location filename="../src/player.cpp" line="312"/>
<source>&amp;Draw card</source> <source>&amp;Draw card</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="284"/> <location filename="../src/player.cpp" line="291"/>
<source>&amp;View exile</source> <source>&amp;View exile</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="287"/> <location filename="../src/player.cpp" line="294"/>
<source>&amp;Exile</source> <source>&amp;Exile</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="296"/> <location filename="../src/player.cpp" line="303"/>
<location filename="../src/player.cpp" line="300"/> <location filename="../src/player.cpp" line="307"/>
<source>Move to &amp;hand</source> <source>Move to &amp;hand</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="292"/> <location filename="../src/player.cpp" line="299"/>
<location filename="../src/player.cpp" line="301"/> <location filename="../src/player.cpp" line="308"/>
<source>Move to g&amp;raveyard</source> <source>Move to g&amp;raveyard</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="293"/> <location filename="../src/player.cpp" line="300"/>
<location filename="../src/player.cpp" line="297"/> <location filename="../src/player.cpp" line="304"/>
<source>Move to &amp;exile</source> <source>Move to &amp;exile</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="338"/> <location filename="../src/player.cpp" line="347"/>
<source>Ctrl+W</source> <source>Ctrl+W</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="340"/> <location filename="../src/player.cpp" line="349"/>
<source>Ctrl+D</source> <source>Ctrl+D</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="306"/> <location filename="../src/player.cpp" line="313"/>
<source>D&amp;raw cards...</source> <source>D&amp;raw cards...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="341"/> <location filename="../src/player.cpp" line="350"/>
<source>Ctrl+E</source> <source>Ctrl+E</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="307"/> <location filename="../src/player.cpp" line="314"/>
<source>Take &amp;mulligan</source> <source>Take &amp;mulligan</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="342"/> <location filename="../src/player.cpp" line="351"/>
<source>Ctrl+M</source> <source>Ctrl+M</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="308"/> <location filename="../src/player.cpp" line="315"/>
<source>&amp;Shuffle</source> <source>&amp;Shuffle</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="343"/> <location filename="../src/player.cpp" line="352"/>
<source>Ctrl+S</source> <source>Ctrl+S</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="313"/> <location filename="../src/player.cpp" line="322"/>
<source>&amp;Counters</source> <source>&amp;Counters</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="315"/> <location filename="../src/player.cpp" line="324"/>
<source>&amp;Untap all permanents</source> <source>&amp;Untap all permanents</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="344"/> <location filename="../src/player.cpp" line="353"/>
<source>Ctrl+U</source> <source>Ctrl+U</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="316"/> <location filename="../src/player.cpp" line="325"/>
<source>R&amp;oll die...</source> <source>R&amp;oll die...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="345"/> <location filename="../src/player.cpp" line="354"/>
<source>Ctrl+I</source> <source>Ctrl+I</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="317"/> <location filename="../src/player.cpp" line="326"/>
<source>&amp;Create token...</source> <source>&amp;Create token...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="346"/> <location filename="../src/player.cpp" line="355"/>
<source>Ctrl+T</source> <source>Ctrl+T</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="318"/> <location filename="../src/player.cpp" line="327"/>
<source>C&amp;reate another token</source> <source>C&amp;reate another token</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="347"/> <location filename="../src/player.cpp" line="356"/>
<source>Ctrl+G</source> <source>Ctrl+G</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="319"/> <location filename="../src/player.cpp" line="328"/>
<source>S&amp;ay</source> <source>S&amp;ay</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="325"/> <location filename="../src/player.cpp" line="316"/>
<source>Move top cards to g&amp;raveyard...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/player.cpp" line="317"/>
<source>Move top cards to &amp;exile...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/player.cpp" line="334"/>
<source>C&amp;ard</source> <source>C&amp;ard</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="438"/> <location filename="../src/player.cpp" line="447"/>
<source>Draw cards</source> <source>Draw cards</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="438"/> <location filename="../src/player.cpp" line="447"/>
<location filename="../src/player.cpp" line="1185"/> <location filename="../src/player.cpp" line="454"/>
<location filename="../src/player.cpp" line="469"/>
<location filename="../src/player.cpp" line="1242"/>
<source>Number:</source> <source>Number:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="451"/> <location filename="../src/player.cpp" line="454"/>
<source>Move top cards to grave</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/player.cpp" line="469"/>
<source>Move top cards to exile</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/player.cpp" line="490"/>
<source>Roll die</source> <source>Roll die</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="451"/> <location filename="../src/player.cpp" line="490"/>
<source>Number of sides:</source> <source>Number of sides:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="1103"/> <location filename="../src/player.cpp" line="1160"/>
<source>Set power/toughness</source> <source>Set power/toughness</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="1103"/> <location filename="../src/player.cpp" line="1160"/>
<source>Please enter the new PT:</source> <source>Please enter the new PT:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="1129"/> <location filename="../src/player.cpp" line="1186"/>
<source>Set annotation</source> <source>Set annotation</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="1129"/> <location filename="../src/player.cpp" line="1186"/>
<source>Please enter the new annotation:</source> <source>Please enter the new annotation:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/player.cpp" line="1185"/> <location filename="../src/player.cpp" line="1242"/>
<source>Set counters</source> <source>Set counters</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -1811,28 +1843,28 @@
<context> <context>
<name>PlayerListWidget</name> <name>PlayerListWidget</name>
<message> <message>
<location filename="../src/playerlistwidget.cpp" line="27"/> <location filename="../src/playerlistwidget.cpp" line="29"/>
<source>Player name</source> <source>Player name</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/playerlistwidget.cpp" line="28"/> <location filename="../src/playerlistwidget.cpp" line="30"/>
<source>Deck</source> <source>Deck</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/playerlistwidget.cpp" line="52"/> <location filename="../src/playerlistwidget.cpp" line="56"/>
<source>no deck</source> <source>---</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/playerlistwidget.cpp" line="53"/> <location filename="../src/playerlistwidget.cpp" line="57"/>
<source>local deck</source> <source>local</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/playerlistwidget.cpp" line="54"/> <location filename="../src/playerlistwidget.cpp" line="58"/>
<source>ID #%1</source> <source>#%1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
@ -1885,7 +1917,7 @@
<context> <context>
<name>ServerMessageLog</name> <name>ServerMessageLog</name>
<message> <message>
<location filename="../src/tab_server.cpp" line="230"/> <location filename="../src/tab_server.cpp" line="232"/>
<source>Server messages</source> <source>Server messages</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -1916,12 +1948,12 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_chatchannel.cpp" line="87"/> <location filename="../src/tab_chatchannel.cpp" line="95"/>
<source>%1 has joined the channel.</source> <source>%1 has joined the channel.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/tab_chatchannel.cpp" line="94"/> <location filename="../src/tab_chatchannel.cpp" line="102"/>
<source>%1 has left the channel.</source> <source>%1 has left the channel.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -2081,10 +2113,33 @@ Please enter a name:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>TabMessage</name>
<message>
<location filename="../src/tab_message.cpp" line="40"/>
<source>Personal &amp;talk</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/tab_message.cpp" line="41"/>
<source>&amp;Leave</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/tab_message.cpp" line="75"/>
<source>%1 has left the server.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/tab_message.h" line="35"/>
<source>Talking to %1</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>TabServer</name> <name>TabServer</name>
<message> <message>
<location filename="../src/tab_server.h" line="88"/> <location filename="../src/tab_server.h" line="113"/>
<source>Server</source> <source>Server</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -2102,6 +2157,14 @@ Please enter a name:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>UserList</name>
<message>
<location filename="../src/tab_server.cpp" line="268"/>
<source>Users online: %1</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>WndDeckEditor</name> <name>WndDeckEditor</name>
<message> <message>

View file

@ -37,12 +37,14 @@ void ProtocolItem::initializeHash()
registerSerializableItem("resp", ProtocolResponse::newItem); registerSerializableItem("resp", ProtocolResponse::newItem);
ProtocolResponse::initializeHash(); ProtocolResponse::initializeHash();
registerSerializableItem("resplist_users", Response_ListUsers::newItem);
registerSerializableItem("respdeck_list", Response_DeckList::newItem); registerSerializableItem("respdeck_list", Response_DeckList::newItem);
registerSerializableItem("respdeck_download", Response_DeckDownload::newItem); registerSerializableItem("respdeck_download", Response_DeckDownload::newItem);
registerSerializableItem("respdeck_upload", Response_DeckUpload::newItem); registerSerializableItem("respdeck_upload", Response_DeckUpload::newItem);
registerSerializableItem("respdump_zone", Response_DumpZone::newItem); registerSerializableItem("respdump_zone", Response_DumpZone::newItem);
registerSerializableItem("generic_eventlist_games", Event_ListGames::newItem); registerSerializableItem("generic_eventlist_games", Event_ListGames::newItem);
registerSerializableItem("generic_eventuser_joined", Event_UserJoined::newItem);
registerSerializableItem("generic_eventlist_chat_channels", Event_ListChatChannels::newItem); registerSerializableItem("generic_eventlist_chat_channels", Event_ListChatChannels::newItem);
registerSerializableItem("game_eventjoin", Event_Join::newItem); registerSerializableItem("game_eventjoin", Event_Join::newItem);
registerSerializableItem("game_eventgame_state_changed", Event_GameStateChanged::newItem); registerSerializableItem("game_eventgame_state_changed", Event_GameStateChanged::newItem);
@ -215,6 +217,13 @@ void ProtocolResponse::initializeHash()
responseHash.insert("spectators_not_allowed", RespSpectatorsNotAllowed); responseHash.insert("spectators_not_allowed", RespSpectatorsNotAllowed);
} }
Response_ListUsers::Response_ListUsers(int _cmdId, ResponseCode _responseCode, const QList<ServerInfo_User *> &_userList)
: ProtocolResponse(_cmdId, _responseCode, "list_users")
{
for (int i = 0; i < _userList.size(); ++i)
itemList.append(_userList[i]);
}
Response_DeckList::Response_DeckList(int _cmdId, ResponseCode _responseCode, DeckList_Directory *_root) Response_DeckList::Response_DeckList(int _cmdId, ResponseCode _responseCode, DeckList_Directory *_root)
: ProtocolResponse(_cmdId, _responseCode, "deck_list") : ProtocolResponse(_cmdId, _responseCode, "deck_list")
{ {
@ -298,6 +307,14 @@ Event_ListGames::Event_ListGames(const QList<ServerInfo_Game *> &_gameList)
itemList.append(_gameList[i]); itemList.append(_gameList[i]);
} }
Event_UserJoined::Event_UserJoined(ServerInfo_User *_userInfo)
: GenericEvent("user_joined")
{
if (!_userInfo)
_userInfo = new ServerInfo_User;
insertItem(_userInfo);
}
Event_Join::Event_Join(ServerInfo_PlayerProperties *player) Event_Join::Event_Join(ServerInfo_PlayerProperties *player)
: GameEvent("join", -1) : GameEvent("join", -1)
{ {

View file

@ -29,17 +29,19 @@ enum ItemId {
ItemId_Event_ChatListPlayers = ItemId_Other + 201, ItemId_Event_ChatListPlayers = ItemId_Other + 201,
ItemId_Event_ChatJoinChannel = ItemId_Other + 202, ItemId_Event_ChatJoinChannel = ItemId_Other + 202,
ItemId_Event_ListGames = ItemId_Other + 203, ItemId_Event_ListGames = ItemId_Other + 203,
ItemId_Event_GameStateChanged = ItemId_Other + 204, ItemId_Event_UserJoined = ItemId_Other + 204,
ItemId_Event_PlayerPropertiesChanged = ItemId_Other + 205, ItemId_Event_GameStateChanged = ItemId_Other + 205,
ItemId_Event_CreateArrows = ItemId_Other + 206, ItemId_Event_PlayerPropertiesChanged = ItemId_Other + 206,
ItemId_Event_CreateCounters = ItemId_Other + 207, ItemId_Event_CreateArrows = ItemId_Other + 207,
ItemId_Event_DrawCards = ItemId_Other + 208, ItemId_Event_CreateCounters = ItemId_Other + 208,
ItemId_Event_Join = ItemId_Other + 209, ItemId_Event_DrawCards = ItemId_Other + 209,
ItemId_Event_Ping = ItemId_Other + 210, ItemId_Event_Join = ItemId_Other + 210,
ItemId_Response_DeckList = ItemId_Other + 300, ItemId_Event_Ping = ItemId_Other + 211,
ItemId_Response_DeckDownload = ItemId_Other + 301, ItemId_Response_ListUsers = ItemId_Other + 300,
ItemId_Response_DeckUpload = ItemId_Other + 302, ItemId_Response_DeckList = ItemId_Other + 301,
ItemId_Response_DumpZone = ItemId_Other + 303, ItemId_Response_DeckDownload = ItemId_Other + 302,
ItemId_Response_DeckUpload = ItemId_Other + 303,
ItemId_Response_DumpZone = ItemId_Other + 304,
ItemId_Invalid = ItemId_Other + 1000 ItemId_Invalid = ItemId_Other + 1000
}; };
@ -199,6 +201,15 @@ public:
ResponseCode getResponseCode() const { return responseHash.value(static_cast<SerializableItem_String *>(itemMap.value("response_code"))->getData(), RespOk); } ResponseCode getResponseCode() const { return responseHash.value(static_cast<SerializableItem_String *>(itemMap.value("response_code"))->getData(), RespOk); }
}; };
class Response_ListUsers : public ProtocolResponse {
Q_OBJECT
public:
Response_ListUsers(int _cmdId = -1, ResponseCode _responseCode = RespOk, const QList<ServerInfo_User *> &_userList = QList<ServerInfo_User *>());
int getItemId() const { return ItemId_Response_ListUsers; }
static SerializableItem *newItem() { return new Response_ListUsers; }
QList<ServerInfo_User *> getUserList() const { return typecastItemList<ServerInfo_User *>(); }
};
class Response_DeckList : public ProtocolResponse { class Response_DeckList : public ProtocolResponse {
Q_OBJECT Q_OBJECT
public: public:
@ -323,6 +334,15 @@ public:
QList<ServerInfo_Game *> getGameList() const { return typecastItemList<ServerInfo_Game *>(); } QList<ServerInfo_Game *> getGameList() const { return typecastItemList<ServerInfo_Game *>(); }
}; };
class Event_UserJoined : public GenericEvent {
Q_OBJECT
public:
Event_UserJoined(ServerInfo_User *_userInfo = 0);
int getItemId() const { return ItemId_Event_UserJoined; }
static SerializableItem *newItem() { return new Event_UserJoined; }
ServerInfo_User *getUserInfo() const { return static_cast<ServerInfo_User *>(itemMap.value("user")); }
};
class Event_Join : public GameEvent { class Event_Join : public GameEvent {
Q_OBJECT Q_OBJECT
public: public:

View file

@ -1,68 +1,72 @@
enum AutoItemId { enum AutoItemId {
ItemId_Command_Ping = 1001, ItemId_Command_Ping = 1001,
ItemId_Command_Login = 1002, ItemId_Command_Login = 1002,
ItemId_Command_DeckList = 1003, ItemId_Command_Message = 1003,
ItemId_Command_DeckNewDir = 1004, ItemId_Command_DeckList = 1004,
ItemId_Command_DeckDelDir = 1005, ItemId_Command_DeckNewDir = 1005,
ItemId_Command_DeckDel = 1006, ItemId_Command_DeckDelDir = 1006,
ItemId_Command_DeckDownload = 1007, ItemId_Command_DeckDel = 1007,
ItemId_Command_ListChatChannels = 1008, ItemId_Command_DeckDownload = 1008,
ItemId_Command_ChatJoinChannel = 1009, ItemId_Command_ListChatChannels = 1009,
ItemId_Command_ChatLeaveChannel = 1010, ItemId_Command_ChatJoinChannel = 1010,
ItemId_Command_ChatSay = 1011, ItemId_Command_ChatLeaveChannel = 1011,
ItemId_Command_ListGames = 1012, ItemId_Command_ChatSay = 1012,
ItemId_Command_CreateGame = 1013, ItemId_Command_ListGames = 1013,
ItemId_Command_JoinGame = 1014, ItemId_Command_ListUsers = 1014,
ItemId_Command_LeaveGame = 1015, ItemId_Command_CreateGame = 1015,
ItemId_Command_Say = 1016, ItemId_Command_JoinGame = 1016,
ItemId_Command_Shuffle = 1017, ItemId_Command_LeaveGame = 1017,
ItemId_Command_Mulligan = 1018, ItemId_Command_Say = 1018,
ItemId_Command_RollDie = 1019, ItemId_Command_Shuffle = 1019,
ItemId_Command_DrawCards = 1020, ItemId_Command_Mulligan = 1020,
ItemId_Command_MoveCard = 1021, ItemId_Command_RollDie = 1021,
ItemId_Command_FlipCard = 1022, ItemId_Command_DrawCards = 1022,
ItemId_Command_AttachCard = 1023, ItemId_Command_MoveCard = 1023,
ItemId_Command_CreateToken = 1024, ItemId_Command_FlipCard = 1024,
ItemId_Command_CreateArrow = 1025, ItemId_Command_AttachCard = 1025,
ItemId_Command_DeleteArrow = 1026, ItemId_Command_CreateToken = 1026,
ItemId_Command_SetCardAttr = 1027, ItemId_Command_CreateArrow = 1027,
ItemId_Command_SetCardCounter = 1028, ItemId_Command_DeleteArrow = 1028,
ItemId_Command_IncCardCounter = 1029, ItemId_Command_SetCardAttr = 1029,
ItemId_Command_ReadyStart = 1030, ItemId_Command_SetCardCounter = 1030,
ItemId_Command_Concede = 1031, ItemId_Command_IncCardCounter = 1031,
ItemId_Command_IncCounter = 1032, ItemId_Command_ReadyStart = 1032,
ItemId_Command_CreateCounter = 1033, ItemId_Command_Concede = 1033,
ItemId_Command_SetCounter = 1034, ItemId_Command_IncCounter = 1034,
ItemId_Command_DelCounter = 1035, ItemId_Command_CreateCounter = 1035,
ItemId_Command_NextTurn = 1036, ItemId_Command_SetCounter = 1036,
ItemId_Command_SetActivePhase = 1037, ItemId_Command_DelCounter = 1037,
ItemId_Command_DumpZone = 1038, ItemId_Command_NextTurn = 1038,
ItemId_Command_StopDumpZone = 1039, ItemId_Command_SetActivePhase = 1039,
ItemId_Event_Say = 1040, ItemId_Command_DumpZone = 1040,
ItemId_Event_Leave = 1041, ItemId_Command_StopDumpZone = 1041,
ItemId_Event_GameClosed = 1042, ItemId_Event_Say = 1042,
ItemId_Event_Shuffle = 1043, ItemId_Event_Leave = 1043,
ItemId_Event_RollDie = 1044, ItemId_Event_GameClosed = 1044,
ItemId_Event_MoveCard = 1045, ItemId_Event_Shuffle = 1045,
ItemId_Event_FlipCard = 1046, ItemId_Event_RollDie = 1046,
ItemId_Event_DestroyCard = 1047, ItemId_Event_MoveCard = 1047,
ItemId_Event_AttachCard = 1048, ItemId_Event_FlipCard = 1048,
ItemId_Event_CreateToken = 1049, ItemId_Event_DestroyCard = 1049,
ItemId_Event_DeleteArrow = 1050, ItemId_Event_AttachCard = 1050,
ItemId_Event_SetCardAttr = 1051, ItemId_Event_CreateToken = 1051,
ItemId_Event_SetCardCounter = 1052, ItemId_Event_DeleteArrow = 1052,
ItemId_Event_SetCounter = 1053, ItemId_Event_SetCardAttr = 1053,
ItemId_Event_DelCounter = 1054, ItemId_Event_SetCardCounter = 1054,
ItemId_Event_SetActivePlayer = 1055, ItemId_Event_SetCounter = 1055,
ItemId_Event_SetActivePhase = 1056, ItemId_Event_DelCounter = 1056,
ItemId_Event_DumpZone = 1057, ItemId_Event_SetActivePlayer = 1057,
ItemId_Event_StopDumpZone = 1058, ItemId_Event_SetActivePhase = 1058,
ItemId_Event_ServerMessage = 1059, ItemId_Event_DumpZone = 1059,
ItemId_Event_GameJoined = 1060, ItemId_Event_StopDumpZone = 1060,
ItemId_Event_ChatLeaveChannel = 1061, ItemId_Event_ServerMessage = 1061,
ItemId_Event_ChatSay = 1062, ItemId_Event_Message = 1062,
ItemId_Context_ReadyStart = 1063, ItemId_Event_GameJoined = 1063,
ItemId_Context_Concede = 1064, ItemId_Event_UserLeft = 1064,
ItemId_Context_DeckSelect = 1065, ItemId_Event_ChatLeaveChannel = 1065,
ItemId_Other = 1066 ItemId_Event_ChatSay = 1066,
ItemId_Context_ReadyStart = 1067,
ItemId_Context_Concede = 1068,
ItemId_Context_DeckSelect = 1069,
ItemId_Other = 1070
}; };

View file

@ -11,6 +11,12 @@ Command_Login::Command_Login(const QString &_username, const QString &_password)
insertItem(new SerializableItem_String("username", _username)); insertItem(new SerializableItem_String("username", _username));
insertItem(new SerializableItem_String("password", _password)); insertItem(new SerializableItem_String("password", _password));
} }
Command_Message::Command_Message(const QString &_userName, const QString &_text)
: Command("message")
{
insertItem(new SerializableItem_String("user_name", _userName));
insertItem(new SerializableItem_String("text", _text));
}
Command_DeckList::Command_DeckList() Command_DeckList::Command_DeckList()
: Command("deck_list") : Command("deck_list")
{ {
@ -58,6 +64,10 @@ Command_ListGames::Command_ListGames()
: Command("list_games") : Command("list_games")
{ {
} }
Command_ListUsers::Command_ListUsers()
: Command("list_users")
{
}
Command_CreateGame::Command_CreateGame(const QString &_description, const QString &_password, int _maxPlayers, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything) Command_CreateGame::Command_CreateGame(const QString &_description, const QString &_password, int _maxPlayers, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything)
: Command("create_game") : Command("create_game")
{ {
@ -370,6 +380,13 @@ Event_ServerMessage::Event_ServerMessage(const QString &_message)
{ {
insertItem(new SerializableItem_String("message", _message)); insertItem(new SerializableItem_String("message", _message));
} }
Event_Message::Event_Message(const QString &_senderName, const QString &_receiverName, const QString &_text)
: GenericEvent("message")
{
insertItem(new SerializableItem_String("sender_name", _senderName));
insertItem(new SerializableItem_String("receiver_name", _receiverName));
insertItem(new SerializableItem_String("text", _text));
}
Event_GameJoined::Event_GameJoined(int _gameId, const QString &_gameDescription, int _playerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming) Event_GameJoined::Event_GameJoined(int _gameId, const QString &_gameDescription, int _playerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming)
: GenericEvent("game_joined") : GenericEvent("game_joined")
{ {
@ -381,6 +398,11 @@ Event_GameJoined::Event_GameJoined(int _gameId, const QString &_gameDescription,
insertItem(new SerializableItem_Bool("spectators_see_everything", _spectatorsSeeEverything)); insertItem(new SerializableItem_Bool("spectators_see_everything", _spectatorsSeeEverything));
insertItem(new SerializableItem_Bool("resuming", _resuming)); insertItem(new SerializableItem_Bool("resuming", _resuming));
} }
Event_UserLeft::Event_UserLeft(const QString &_userName)
: GenericEvent("user_left")
{
insertItem(new SerializableItem_String("user_name", _userName));
}
Event_ChatLeaveChannel::Event_ChatLeaveChannel(const QString &_channel, const QString &_playerName) Event_ChatLeaveChannel::Event_ChatLeaveChannel(const QString &_channel, const QString &_playerName)
: ChatEvent("chat_leave_channel", _channel) : ChatEvent("chat_leave_channel", _channel)
{ {
@ -409,6 +431,7 @@ void ProtocolItem::initializeHashAuto()
{ {
itemNameHash.insert("cmdping", Command_Ping::newItem); itemNameHash.insert("cmdping", Command_Ping::newItem);
itemNameHash.insert("cmdlogin", Command_Login::newItem); itemNameHash.insert("cmdlogin", Command_Login::newItem);
itemNameHash.insert("cmdmessage", Command_Message::newItem);
itemNameHash.insert("cmddeck_list", Command_DeckList::newItem); itemNameHash.insert("cmddeck_list", Command_DeckList::newItem);
itemNameHash.insert("cmddeck_new_dir", Command_DeckNewDir::newItem); itemNameHash.insert("cmddeck_new_dir", Command_DeckNewDir::newItem);
itemNameHash.insert("cmddeck_del_dir", Command_DeckDelDir::newItem); itemNameHash.insert("cmddeck_del_dir", Command_DeckDelDir::newItem);
@ -419,6 +442,7 @@ void ProtocolItem::initializeHashAuto()
itemNameHash.insert("cmdchat_leave_channel", Command_ChatLeaveChannel::newItem); itemNameHash.insert("cmdchat_leave_channel", Command_ChatLeaveChannel::newItem);
itemNameHash.insert("cmdchat_say", Command_ChatSay::newItem); itemNameHash.insert("cmdchat_say", Command_ChatSay::newItem);
itemNameHash.insert("cmdlist_games", Command_ListGames::newItem); itemNameHash.insert("cmdlist_games", Command_ListGames::newItem);
itemNameHash.insert("cmdlist_users", Command_ListUsers::newItem);
itemNameHash.insert("cmdcreate_game", Command_CreateGame::newItem); itemNameHash.insert("cmdcreate_game", Command_CreateGame::newItem);
itemNameHash.insert("cmdjoin_game", Command_JoinGame::newItem); itemNameHash.insert("cmdjoin_game", Command_JoinGame::newItem);
itemNameHash.insert("cmdleave_game", Command_LeaveGame::newItem); itemNameHash.insert("cmdleave_game", Command_LeaveGame::newItem);
@ -466,7 +490,9 @@ void ProtocolItem::initializeHashAuto()
itemNameHash.insert("game_eventdump_zone", Event_DumpZone::newItem); itemNameHash.insert("game_eventdump_zone", Event_DumpZone::newItem);
itemNameHash.insert("game_eventstop_dump_zone", Event_StopDumpZone::newItem); itemNameHash.insert("game_eventstop_dump_zone", Event_StopDumpZone::newItem);
itemNameHash.insert("generic_eventserver_message", Event_ServerMessage::newItem); itemNameHash.insert("generic_eventserver_message", Event_ServerMessage::newItem);
itemNameHash.insert("generic_eventmessage", Event_Message::newItem);
itemNameHash.insert("generic_eventgame_joined", Event_GameJoined::newItem); itemNameHash.insert("generic_eventgame_joined", Event_GameJoined::newItem);
itemNameHash.insert("generic_eventuser_left", Event_UserLeft::newItem);
itemNameHash.insert("chat_eventchat_leave_channel", Event_ChatLeaveChannel::newItem); itemNameHash.insert("chat_eventchat_leave_channel", Event_ChatLeaveChannel::newItem);
itemNameHash.insert("chat_eventchat_say", Event_ChatSay::newItem); itemNameHash.insert("chat_eventchat_say", Event_ChatSay::newItem);
itemNameHash.insert("game_event_contextready_start", Context_ReadyStart::newItem); itemNameHash.insert("game_event_contextready_start", Context_ReadyStart::newItem);

View file

@ -1,5 +1,6 @@
0:ping 0:ping
0:login:s,username:s,password 0:login:s,username:s,password
0:message:s,user_name:s,text
0:deck_list 0:deck_list
0:deck_new_dir:s,path:s,dir_name 0:deck_new_dir:s,path:s,dir_name
0:deck_del_dir:s,path 0:deck_del_dir:s,path
@ -10,6 +11,7 @@
1:chat_leave_channel 1:chat_leave_channel
1:chat_say:s,message 1:chat_say:s,message
0:list_games 0:list_games
0:list_users
0:create_game:s,description:s,password:i,max_players:b,spectators_allowed:b,spectators_need_password:b,spectators_can_talk:b,spectators_see_everything 0:create_game:s,description:s,password:i,max_players:b,spectators_allowed:b,spectators_need_password:b,spectators_can_talk:b,spectators_see_everything
0:join_game:i,game_id:s,password:b,spectator 0:join_game:i,game_id:s,password:b,spectator
2:leave_game 2:leave_game
@ -57,7 +59,9 @@
3:dump_zone:i,zone_owner_id:s,zone:i,number_cards 3:dump_zone:i,zone_owner_id:s,zone:i,number_cards
3:stop_dump_zone:i,zone_owner_id:s,zone 3:stop_dump_zone:i,zone_owner_id:s,zone
4:server_message:s,message 4:server_message:s,message
4:message:s,sender_name:s,receiver_name:s,text
4:game_joined:i,game_id:s,game_description:i,player_id:b,spectator:b,spectators_can_talk:b,spectators_see_everything:b,resuming 4:game_joined:i,game_id:s,game_description:i,player_id:b,spectator:b,spectators_can_talk:b,spectators_see_everything:b,resuming
4:user_left:s,user_name
5:chat_leave_channel:s,player_name 5:chat_leave_channel:s,player_name
5:chat_say:s,player_name:s,message 5:chat_say:s,player_name:s,message
6:ready_start 6:ready_start

View file

@ -19,6 +19,15 @@ public:
static SerializableItem *newItem() { return new Command_Login; } static SerializableItem *newItem() { return new Command_Login; }
int getItemId() const { return ItemId_Command_Login; } int getItemId() const { return ItemId_Command_Login; }
}; };
class Command_Message : public Command {
Q_OBJECT
public:
Command_Message(const QString &_userName = QString(), const QString &_text = QString());
QString getUserName() const { return static_cast<SerializableItem_String *>(itemMap.value("user_name"))->getData(); };
QString getText() const { return static_cast<SerializableItem_String *>(itemMap.value("text"))->getData(); };
static SerializableItem *newItem() { return new Command_Message; }
int getItemId() const { return ItemId_Command_Message; }
};
class Command_DeckList : public Command { class Command_DeckList : public Command {
Q_OBJECT Q_OBJECT
public: public:
@ -96,6 +105,13 @@ public:
static SerializableItem *newItem() { return new Command_ListGames; } static SerializableItem *newItem() { return new Command_ListGames; }
int getItemId() const { return ItemId_Command_ListGames; } int getItemId() const { return ItemId_Command_ListGames; }
}; };
class Command_ListUsers : public Command {
Q_OBJECT
public:
Command_ListUsers();
static SerializableItem *newItem() { return new Command_ListUsers; }
int getItemId() const { return ItemId_Command_ListUsers; }
};
class Command_CreateGame : public Command { class Command_CreateGame : public Command {
Q_OBJECT Q_OBJECT
public: public:
@ -549,6 +565,16 @@ public:
static SerializableItem *newItem() { return new Event_ServerMessage; } static SerializableItem *newItem() { return new Event_ServerMessage; }
int getItemId() const { return ItemId_Event_ServerMessage; } int getItemId() const { return ItemId_Event_ServerMessage; }
}; };
class Event_Message : public GenericEvent {
Q_OBJECT
public:
Event_Message(const QString &_senderName = QString(), const QString &_receiverName = QString(), const QString &_text = QString());
QString getSenderName() const { return static_cast<SerializableItem_String *>(itemMap.value("sender_name"))->getData(); };
QString getReceiverName() const { return static_cast<SerializableItem_String *>(itemMap.value("receiver_name"))->getData(); };
QString getText() const { return static_cast<SerializableItem_String *>(itemMap.value("text"))->getData(); };
static SerializableItem *newItem() { return new Event_Message; }
int getItemId() const { return ItemId_Event_Message; }
};
class Event_GameJoined : public GenericEvent { class Event_GameJoined : public GenericEvent {
Q_OBJECT Q_OBJECT
public: public:
@ -563,6 +589,14 @@ public:
static SerializableItem *newItem() { return new Event_GameJoined; } static SerializableItem *newItem() { return new Event_GameJoined; }
int getItemId() const { return ItemId_Event_GameJoined; } int getItemId() const { return ItemId_Event_GameJoined; }
}; };
class Event_UserLeft : public GenericEvent {
Q_OBJECT
public:
Event_UserLeft(const QString &_userName = QString());
QString getUserName() const { return static_cast<SerializableItem_String *>(itemMap.value("user_name"))->getData(); };
static SerializableItem *newItem() { return new Event_UserLeft; }
int getItemId() const { return ItemId_Event_UserLeft; }
};
class Event_ChatLeaveChannel : public ChatEvent { class Event_ChatLeaveChannel : public ChatEvent {
Q_OBJECT Q_OBJECT
public: public:

View file

@ -62,6 +62,12 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString
users.insert(name, session); users.insert(name, session);
Event_UserJoined *event = new Event_UserJoined(new ServerInfo_User(data));
for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsUserListChanges())
clients[i]->sendProtocolItem(event, false);
delete event;
return authState; return authState;
} }
@ -85,8 +91,15 @@ void Server::removeClient(Server_ProtocolHandler *client)
{ {
clients.removeAt(clients.indexOf(client)); clients.removeAt(clients.indexOf(client));
ServerInfo_User *data = client->getUserInfo(); ServerInfo_User *data = client->getUserInfo();
if (data) if (data) {
Event_UserLeft *event = new Event_UserLeft(data->getName());
for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsUserListChanges())
clients[i]->sendProtocolItem(event, false);
delete event;
users.remove(data->getName()); users.remove(data->getName());
}
qDebug() << "Server::removeClient: " << clients.size() << "clients; " << users.size() << "users left"; qDebug() << "Server::removeClient: " << clients.size() << "clients; " << users.size() << "users left";
} }

View file

@ -29,6 +29,7 @@ public:
const QMap<QString, Server_ChatChannel *> &getChatChannels() { return chatChannels; } const QMap<QString, Server_ChatChannel *> &getChatChannels() { return chatChannels; }
void broadcastGameListUpdate(Server_Game *game); void broadcastGameListUpdate(Server_Game *game);
const QMap<QString, Server_ProtocolHandler *> &getUsers() const { return users; }
void addClient(Server_ProtocolHandler *player); void addClient(Server_ProtocolHandler *player);
void removeClient(Server_ProtocolHandler *player); void removeClient(Server_ProtocolHandler *player);
virtual QString getLoginMessage() const = 0; virtual QString getLoginMessage() const = 0;

View file

@ -14,7 +14,7 @@
#include <QDateTime> #include <QDateTime>
Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, QObject *parent) Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, QObject *parent)
: QObject(parent), server(_server), authState(PasswordWrong), acceptsGameListChanges(false), userInfo(0), lastCommandTime(QDateTime::currentDateTime()) : QObject(parent), server(_server), authState(PasswordWrong), acceptsGameListChanges(false), acceptsUserListChanges(false), acceptsChatChannelListChanges(false), userInfo(0), lastCommandTime(QDateTime::currentDateTime())
{ {
connect(server, SIGNAL(pingClockTimeout()), this, SLOT(pingClockTimeout())); connect(server, SIGNAL(pingClockTimeout()), this, SLOT(pingClockTimeout()));
} }
@ -116,6 +116,7 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm
switch (command->getItemId()) { switch (command->getItemId()) {
case ItemId_Command_Ping: return cmdPing(qobject_cast<Command_Ping *>(command), cont); case ItemId_Command_Ping: return cmdPing(qobject_cast<Command_Ping *>(command), cont);
case ItemId_Command_Login: return cmdLogin(qobject_cast<Command_Login *>(command), cont); case ItemId_Command_Login: return cmdLogin(qobject_cast<Command_Login *>(command), cont);
case ItemId_Command_Message: return cmdMessage(qobject_cast<Command_Message *>(command), cont);
case ItemId_Command_DeckList: return cmdDeckList(qobject_cast<Command_DeckList *>(command), cont); case ItemId_Command_DeckList: return cmdDeckList(qobject_cast<Command_DeckList *>(command), cont);
case ItemId_Command_DeckNewDir: return cmdDeckNewDir(qobject_cast<Command_DeckNewDir *>(command), cont); case ItemId_Command_DeckNewDir: return cmdDeckNewDir(qobject_cast<Command_DeckNewDir *>(command), cont);
case ItemId_Command_DeckDelDir: return cmdDeckDelDir(qobject_cast<Command_DeckDelDir *>(command), cont); case ItemId_Command_DeckDelDir: return cmdDeckDelDir(qobject_cast<Command_DeckDelDir *>(command), cont);
@ -124,6 +125,7 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm
case ItemId_Command_DeckDownload: return cmdDeckDownload(qobject_cast<Command_DeckDownload *>(command), cont); case ItemId_Command_DeckDownload: return cmdDeckDownload(qobject_cast<Command_DeckDownload *>(command), cont);
case ItemId_Command_ListChatChannels: return cmdListChatChannels(qobject_cast<Command_ListChatChannels *>(command), cont); case ItemId_Command_ListChatChannels: return cmdListChatChannels(qobject_cast<Command_ListChatChannels *>(command), cont);
case ItemId_Command_ChatJoinChannel: return cmdChatJoinChannel(qobject_cast<Command_ChatJoinChannel *>(command), cont); case ItemId_Command_ChatJoinChannel: return cmdChatJoinChannel(qobject_cast<Command_ChatJoinChannel *>(command), cont);
case ItemId_Command_ListUsers: return cmdListUsers(qobject_cast<Command_ListUsers *>(command), cont);
case ItemId_Command_ListGames: return cmdListGames(qobject_cast<Command_ListGames *>(command), cont); case ItemId_Command_ListGames: return cmdListGames(qobject_cast<Command_ListGames *>(command), cont);
case ItemId_Command_CreateGame: return cmdCreateGame(qobject_cast<Command_CreateGame *>(command), cont); case ItemId_Command_CreateGame: return cmdCreateGame(qobject_cast<Command_CreateGame *>(command), cont);
case ItemId_Command_JoinGame: return cmdJoinGame(qobject_cast<Command_JoinGame *>(command), cont); case ItemId_Command_JoinGame: return cmdJoinGame(qobject_cast<Command_JoinGame *>(command), cont);
@ -229,6 +231,21 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain
return RespOk; return RespOk;
} }
ResponseCode Server_ProtocolHandler::cmdMessage(Command_Message *cmd, CommandContainer *cont)
{
if (authState == PasswordWrong)
return RespLoginNeeded;
QString receiver = cmd->getUserName();
Server_ProtocolHandler *userHandler = server->getUsers().value(receiver);
if (!userHandler)
return RespNameNotFound;
cont->enqueueItem(new Event_Message(userInfo->getName(), receiver, cmd->getText()));
userHandler->sendProtocolItem(new Event_Message(userInfo->getName(), receiver, cmd->getText()));
return RespOk;
}
ResponseCode Server_ProtocolHandler::cmdListChatChannels(Command_ListChatChannels * /*cmd*/, CommandContainer *cont) ResponseCode Server_ProtocolHandler::cmdListChatChannels(Command_ListChatChannels * /*cmd*/, CommandContainer *cont)
{ {
if (authState == PasswordWrong) if (authState == PasswordWrong)
@ -277,6 +294,22 @@ ResponseCode Server_ProtocolHandler::cmdChatSay(Command_ChatSay *cmd, CommandCon
return RespOk; return RespOk;
} }
ResponseCode Server_ProtocolHandler::cmdListUsers(Command_ListUsers * /*cmd*/, CommandContainer *cont)
{
if (authState == PasswordWrong)
return RespLoginNeeded;
QList<ServerInfo_User *> resultList;
QMapIterator<QString, Server_ProtocolHandler *> userIterator = server->getUsers();
while (userIterator.hasNext())
resultList.append(new ServerInfo_User(userIterator.next().value()->getUserInfo()));
acceptsUserListChanges = true;
cont->setResponse(new Response_ListUsers(cont->getCmdId(), RespOk, resultList));
return RespNothing;
}
ResponseCode Server_ProtocolHandler::cmdListGames(Command_ListGames * /*cmd*/, CommandContainer *cont) ResponseCode Server_ProtocolHandler::cmdListGames(Command_ListGames * /*cmd*/, CommandContainer *cont)
{ {
if (authState == PasswordWrong) if (authState == PasswordWrong)

View file

@ -24,6 +24,7 @@ protected:
AuthenticationResult authState; AuthenticationResult authState;
bool acceptsGameListChanges; bool acceptsGameListChanges;
bool acceptsUserListChanges;
bool acceptsChatChannelListChanges; bool acceptsChatChannelListChanges;
ServerInfo_User *userInfo; ServerInfo_User *userInfo;
@ -36,6 +37,7 @@ private:
ResponseCode cmdPing(Command_Ping *cmd, CommandContainer *cont); ResponseCode cmdPing(Command_Ping *cmd, CommandContainer *cont);
ResponseCode cmdLogin(Command_Login *cmd, CommandContainer *cont); ResponseCode cmdLogin(Command_Login *cmd, CommandContainer *cont);
ResponseCode cmdMessage(Command_Message *cmd, CommandContainer *cont);
virtual ResponseCode cmdDeckList(Command_DeckList *cmd, CommandContainer *cont) = 0; virtual ResponseCode cmdDeckList(Command_DeckList *cmd, CommandContainer *cont) = 0;
virtual ResponseCode cmdDeckNewDir(Command_DeckNewDir *cmd, CommandContainer *cont) = 0; virtual ResponseCode cmdDeckNewDir(Command_DeckNewDir *cmd, CommandContainer *cont) = 0;
virtual ResponseCode cmdDeckDelDir(Command_DeckDelDir *cmd, CommandContainer *cont) = 0; virtual ResponseCode cmdDeckDelDir(Command_DeckDelDir *cmd, CommandContainer *cont) = 0;
@ -46,6 +48,7 @@ private:
ResponseCode cmdChatJoinChannel(Command_ChatJoinChannel *cmd, CommandContainer *cont); ResponseCode cmdChatJoinChannel(Command_ChatJoinChannel *cmd, CommandContainer *cont);
ResponseCode cmdChatLeaveChannel(Command_ChatLeaveChannel *cmd, CommandContainer *cont, Server_ChatChannel *channel); ResponseCode cmdChatLeaveChannel(Command_ChatLeaveChannel *cmd, CommandContainer *cont, Server_ChatChannel *channel);
ResponseCode cmdChatSay(Command_ChatSay *cmd, CommandContainer *cont, Server_ChatChannel *channel); ResponseCode cmdChatSay(Command_ChatSay *cmd, CommandContainer *cont, Server_ChatChannel *channel);
ResponseCode cmdListUsers(Command_ListUsers *cmd, CommandContainer *cont);
ResponseCode cmdListGames(Command_ListGames *cmd, CommandContainer *cont); ResponseCode cmdListGames(Command_ListGames *cmd, CommandContainer *cont);
ResponseCode cmdCreateGame(Command_CreateGame *cmd, CommandContainer *cont); ResponseCode cmdCreateGame(Command_CreateGame *cmd, CommandContainer *cont);
ResponseCode cmdJoinGame(Command_JoinGame *cmd, CommandContainer *cont); ResponseCode cmdJoinGame(Command_JoinGame *cmd, CommandContainer *cont);
@ -91,6 +94,7 @@ public:
void playerRemovedFromGame(Server_Game *game); void playerRemovedFromGame(Server_Game *game);
bool getAcceptsGameListChanges() const { return acceptsGameListChanges; } bool getAcceptsGameListChanges() const { return acceptsGameListChanges; }
bool getAcceptsUserListChanges() const { return acceptsUserListChanges; }
bool getAcceptsChatChannelListChanges() const { return acceptsChatChannelListChanges; } bool getAcceptsChatChannelListChanges() const { return acceptsChatChannelListChanges; }
ServerInfo_User *getUserInfo() const { return userInfo; } ServerInfo_User *getUserInfo() const { return userInfo; }
void setUserInfo(ServerInfo_User *_userInfo) { userInfo = _userInfo; } void setUserInfo(ServerInfo_User *_userInfo) { userInfo = _userInfo; }