fixed direct chat, fixed in-game attachment bugs

This commit is contained in:
Max-Wilhelm Bruker 2011-01-25 00:12:35 +01:00
parent c39539b73a
commit 92e842bb74
18 changed files with 127 additions and 96 deletions

View file

@ -58,6 +58,7 @@ HEADERS += src/abstractcounter.h \
src/tab_deck_storage.h \
src/tab_supervisor.h \
src/tab_admin.h \
src/chatview.h \
src/userlist.h \
src/userinfobox.h \
src/remotedecklist_treewidget.h \
@ -139,6 +140,7 @@ SOURCES += src/abstractcounter.cpp \
src/tab_deck_storage.cpp \
src/tab_supervisor.cpp \
src/tab_admin.cpp \
src/chatview.cpp \
src/userlist.cpp \
src/userinfobox.cpp \
src/remotedecklist_treewidget.cpp \

View file

@ -0,0 +1,42 @@
#include <QTextEdit>
#include <QDateTime>
#include <QTextTable>
#include <QScrollBar>
#include "chatview.h"
ChatView::ChatView(const QString &_ownName, QWidget *parent)
: QTextEdit(parent), ownName(_ownName)
{
setTextInteractionFlags(Qt::TextSelectableByMouse);
QTextTableFormat format;
format.setBorderStyle(QTextFrameFormat::BorderStyle_None);
table = textCursor().insertTable(1, 3, format);
}
void ChatView::appendMessage(const QString &sender, const QString &message)
{
QTextCursor cellCursor = table->cellAt(table->rows() - 1, 0).lastCursorPosition();
cellCursor.insertText(QDateTime::currentDateTime().toString("[hh:mm]"));
QTextTableCell senderCell = table->cellAt(table->rows() - 1, 1);
QTextCharFormat senderFormat;
if (sender == ownName) {
senderFormat.setFontWeight(QFont::Bold);
senderFormat.setForeground(Qt::red);
} else
senderFormat.setForeground(Qt::blue);
senderCell.setFormat(senderFormat);
cellCursor = senderCell.lastCursorPosition();
cellCursor.insertText(sender);
QTextTableCell messageCell = table->cellAt(table->rows() - 1, 2);
QTextCharFormat messageFormat;
if (sender.isEmpty())
messageFormat.setForeground(Qt::darkGreen);
messageCell.setFormat(messageFormat);
cellCursor = messageCell.lastCursorPosition();
cellCursor.insertText(message);
table->appendRows(1);
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
}

18
cockatrice/src/chatview.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef CHATVIEW_H
#define CHATVIEW_H
#include <QTextEdit>
class QTextTable;
class ChatView : public QTextEdit {
Q_OBJECT;
private:
QTextTable *table;
QString ownName;
public:
ChatView(const QString &_ownName, QWidget *parent = 0);
void appendMessage(const QString &sender, const QString &message);
};
#endif

View file

@ -886,6 +886,11 @@ void Player::eventDestroyCard(Event_DestroyCard *event)
if (!card)
return;
QList<CardItem *> attachedCards = card->getAttachedCards();
// This list is always empty except for buggy server implementations.
for (int i = 0; i < attachedCards.size(); ++i)
attachedCards[i]->setAttachedTo(0);
emit logDestroyCard(this, card->getName());
zone->takeCard(-1, event->getCardId(), true);
card->deleteLater();

View file

@ -1,4 +1,3 @@
#include <QTextEdit>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QHBoxLayout>
@ -7,17 +6,17 @@
#include "tab_message.h"
#include "abstractclient.h"
#include "protocol_items.h"
#include "chatview.h"
TabMessage::TabMessage(AbstractClient *_client, const QString &_userName)
: Tab(), client(_client), userName(_userName)
TabMessage::TabMessage(AbstractClient *_client, const QString &_ownName, const QString &_userName)
: Tab(), client(_client), userName(_userName), userOnline(true)
{
textEdit = new QTextEdit;
textEdit->setReadOnly(true);
chatView = new ChatView(_ownName);
sayEdit = new QLineEdit;
connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(sendMessage()));
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(textEdit);
vbox->addWidget(chatView);
vbox->addWidget(sayEdit);
aLeave = new QAction(this);
@ -41,17 +40,9 @@ void TabMessage::retranslateUi()
aLeave->setText(tr("&Leave"));
}
QString TabMessage::sanitizeHtml(QString dirty) const
{
return dirty
.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;");
}
void TabMessage::sendMessage()
{
if (sayEdit->text().isEmpty())
if (sayEdit->text().isEmpty() || !userOnline)
return;
client->sendCommand(new Command_Message(userName, sayEdit->text()));
@ -65,14 +56,18 @@ void TabMessage::actLeave()
void TabMessage::processMessageEvent(Event_Message *event)
{
textEdit->append(QString("<font color=\"") + (event->getSenderName() == userName ? "#0000fe" : "red") + QString("\">%1:</font> %2").arg(sanitizeHtml(event->getSenderName())).arg(sanitizeHtml(event->getText())));
chatView->appendMessage(event->getSenderName(), event->getText());
emit userEvent();
}
void TabMessage::processUserLeft(const QString &name)
void TabMessage::processUserLeft()
{
if (userName == name) {
textEdit->append("<font color=\"blue\">" + tr("%1 has left the server.").arg(sanitizeHtml(name)) + "</font>");
sayEdit->setEnabled(false);
chatView->appendMessage(QString(), tr("%1 has left the server.").arg(userName));
userOnline = false;
}
void TabMessage::processUserJoined()
{
chatView->appendMessage(QString(), tr("%1 has joined the server.").arg(userName));
userOnline = true;
}

View file

@ -4,7 +4,7 @@
#include "tab.h"
class AbstractClient;
class QTextEdit;
class ChatView;
class QLineEdit;
class Event_Message;
@ -13,26 +13,27 @@ class TabMessage : public Tab {
private:
AbstractClient *client;
QString userName;
bool userOnline;
QTextEdit *textEdit;
ChatView *chatView;
QLineEdit *sayEdit;
QAction *aLeave;
QString sanitizeHtml(QString dirty) const;
signals:
void talkClosing(TabMessage *tab);
private slots:
void sendMessage();
void actLeave();
public slots:
void processMessageEvent(Event_Message *event);
void processUserLeft(const QString &userName);
public:
TabMessage(AbstractClient *_client, const QString &_userName);
TabMessage(AbstractClient *_client, const QString &_ownName, const QString &_userName);
~TabMessage();
void retranslateUi();
QString getUserName() const { return userName; }
QString getTabText() const { return tr("Talking to %1").arg(userName); }
void processMessageEvent(Event_Message *event);
void processUserLeft();
void processUserJoined();
};
#endif

View file

@ -1,4 +1,3 @@
#include <QTextEdit>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QHBoxLayout>
@ -10,15 +9,13 @@
#include <QCheckBox>
#include <QInputDialog>
#include <QLabel>
#include <QScrollBar>
#include "dlg_creategame.h"
#include "tab_room.h"
#include "userlist.h"
#include "abstractclient.h"
#include "protocol_items.h"
#include "gamesmodel.h"
#include <QTextTable>
#include "chatview.h"
GameSelector::GameSelector(AbstractClient *_client, int _roomId, QWidget *parent)
: QGroupBox(parent), client(_client), roomId(_roomId)
@ -122,43 +119,6 @@ void GameSelector::processGameInfo(ServerInfo_Game *info)
gameListModel->updateGameList(info);
}
ChatView::ChatView(const QString &_ownName, QWidget *parent)
: QTextEdit(parent), ownName(_ownName)
{
setTextInteractionFlags(Qt::TextSelectableByMouse);
QTextTableFormat format;
format.setBorderStyle(QTextFrameFormat::BorderStyle_None);
table = textCursor().insertTable(1, 3, format);
}
void ChatView::appendMessage(const QString &sender, const QString &message)
{
QTextCursor cellCursor = table->cellAt(table->rows() - 1, 0).lastCursorPosition();
cellCursor.insertText(QDateTime::currentDateTime().toString("[hh:mm]"));
QTextTableCell senderCell = table->cellAt(table->rows() - 1, 1);
QTextCharFormat senderFormat;
if (sender == ownName) {
senderFormat.setFontWeight(QFont::Bold);
senderFormat.setForeground(Qt::red);
} else
senderFormat.setForeground(Qt::blue);
senderCell.setFormat(senderFormat);
cellCursor = senderCell.lastCursorPosition();
cellCursor.insertText(sender);
QTextTableCell messageCell = table->cellAt(table->rows() - 1, 2);
QTextCharFormat messageFormat;
if (sender.isEmpty())
messageFormat.setForeground(Qt::darkGreen);
messageCell.setFormat(messageFormat);
cellCursor = messageCell.lastCursorPosition();
cellCursor.insertText(message);
table->appendRows(1);
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
}
TabRoom::TabRoom(AbstractClient *_client, const QString &_ownName, ServerInfo_Room *info)
: Tab(), client(_client), roomId(info->getRoomId()), roomName(info->getName()), ownName(_ownName)
{

View file

@ -4,12 +4,11 @@
#include "tab.h"
#include "protocol_datastructures.h"
#include <QGroupBox>
#include <QTextEdit>
class AbstractClient;
class UserList;
class QLabel;
class QTextEdit;
class ChatView;
class QLineEdit;
class QTreeView;
class QPushButton;
@ -49,16 +48,6 @@ public:
void processGameInfo(ServerInfo_Game *info);
};
class ChatView : public QTextEdit {
Q_OBJECT;
private:
QTextTable *table;
QString ownName;
public:
ChatView(const QString &_ownName, QWidget *parent = 0);
void appendMessage(const QString &sender, const QString &message);
};
class TabRoom : public Tab {
Q_OBJECT
private:

View file

@ -184,6 +184,8 @@ void TabServer::processUserJoinedEvent(Event_UserJoined *event)
{
userList->processUserInfo(event->getUserInfo());
userList->sortItems();
emit userJoined(event->getUserInfo()->getName());
}
void TabServer::processUserLeftEvent(Event_UserLeft *event)

View file

@ -46,6 +46,7 @@ signals:
void roomJoined(ServerInfo_Room *info, bool setCurrent);
void openMessageDialog(const QString &userName, bool focus);
void userLeft(const QString &userName);
void userJoined(const QString &userName);
private slots:
void processListUsersResponse(ProtocolResponse *response);
void processUserJoinedEvent(Event_UserJoined *event);

View file

@ -66,6 +66,7 @@ void TabSupervisor::start(AbstractClient *_client, ServerInfo_User *userInfo)
tabServer = new TabServer(client, userInfo);
connect(tabServer, SIGNAL(roomJoined(ServerInfo_Room *, bool)), this, SLOT(addRoomTab(ServerInfo_Room *, bool)));
connect(tabServer, SIGNAL(openMessageDialog(const QString &, bool)), this, SLOT(addMessageTab(const QString &, bool)));
connect(tabServer, SIGNAL(userJoined(const QString &)), this, SLOT(processUserJoined(const QString &)));
connect(tabServer, SIGNAL(userLeft(const QString &)), this, SLOT(processUserLeft(const QString &)));
myAddTab(tabServer);
updatePingTime(0, -1);
@ -128,6 +129,11 @@ void TabSupervisor::stop()
while (gameIterator.hasNext())
gameIterator.next().value()->deleteLater();
gameTabs.clear();
QMapIterator<QString, TabMessage *> messageIterator(messageTabs);
while (messageIterator.hasNext())
messageIterator.next().value()->deleteLater();
messageTabs.clear();
}
void TabSupervisor::updatePingTime(int value, int max)
@ -178,6 +184,7 @@ void TabSupervisor::addRoomTab(ServerInfo_Room *info, bool setCurrent)
{
TabRoom *tab = new TabRoom(client, userName, info);
connect(tab, SIGNAL(roomClosing(TabRoom *)), this, SLOT(roomLeft(TabRoom *)));
connect(tab, SIGNAL(openMessageDialog(const QString &, bool)), this, SLOT(addMessageTab(const QString &, bool)));
myAddTab(tab);
roomTabs.insert(info->getRoomId(), tab);
if (setCurrent)
@ -197,7 +204,7 @@ TabMessage *TabSupervisor::addMessageTab(const QString &receiverName, bool focus
if (receiverName == userName)
return 0;
TabMessage *tab = new TabMessage(client, receiverName);
TabMessage *tab = new TabMessage(client, userName, receiverName);
connect(tab, SIGNAL(talkClosing(TabMessage *)), this, SLOT(talkLeft(TabMessage *)));
myAddTab(tab);
messageTabs.insert(receiverName, tab);
@ -257,7 +264,14 @@ void TabSupervisor::processUserLeft(const QString &userName)
{
TabMessage *tab = messageTabs.value(userName);
if (tab)
tab->processUserLeft(userName);
tab->processUserLeft();
}
void TabSupervisor::processUserJoined(const QString &userName)
{
TabMessage *tab = messageTabs.value(userName);
if (tab)
tab->processUserJoined();
}
void TabSupervisor::updateCurrent(int index)

View file

@ -55,6 +55,7 @@ private slots:
void roomLeft(TabRoom *tab);
TabMessage *addMessageTab(const QString &userName, bool focus);
void processUserLeft(const QString &userName);
void processUserJoined(const QString &userName);
void talkLeft(TabMessage *tab);
void tabUserEvent();
void processRoomEvent(RoomEvent *event);

View file

@ -140,7 +140,7 @@ void TableZone::reorganizeCards()
qreal actualX = x + numberAttachedCards * CARD_WIDTH / 3.0;
qreal actualY = y;
if (numberAttachedCards)
actualY += 5;
actualY += 15;
cards[i]->setPos(actualX, actualY);
cards[i]->setRealZValue((actualY + CARD_HEIGHT) * 100000 + (actualX + 1) * 100);
@ -151,7 +151,7 @@ void TableZone::reorganizeCards()
++j;
CardItem *attachedCard = attachedCardIterator.next();
qreal childX = actualX - j * CARD_WIDTH / 3.0;
qreal childY = y - 5;
qreal childY = y + 5;
attachedCard->setPos(childX, childY);
attachedCard->setRealZValue((childY + CARD_HEIGHT) * 100000 + (childX + 1) * 100);

View file

@ -154,9 +154,9 @@ bool Server_CardZone::isColumnEmpty(int x, int y) const
void Server_CardZone::moveCard(CommandContainer *cont, QMap<int, Server_Card *> &coordMap, Server_Card *card, int x, int y)
{
coordMap.remove(card->getX());
player->moveCard(cont, this, QList<int>() << card->getId(), this, x, y, card->getFaceDown(), false);
coordMap.insert(x, card);
coordMap.remove(card->getY() * 10000 + card->getX());
player->moveCard(cont, this, QList<int>() << card->getId(), this, x, y, card->getFaceDown(), false, false);
coordMap.insert(y * 10000 + x, card);
}
void Server_CardZone::fixFreeSpaces(CommandContainer *cont)

View file

@ -233,7 +233,7 @@ public:
}
};
ResponseCode Server_Player::moveCard(CommandContainer *cont, Server_CardZone *startzone, const QList<int> &_cardIds, Server_CardZone *targetzone, int x, int y, bool faceDown, bool tapped)
ResponseCode Server_Player::moveCard(CommandContainer *cont, Server_CardZone *startzone, const QList<int> &_cardIds, Server_CardZone *targetzone, int x, int y, bool faceDown, bool tapped, bool fixFreeSpaces)
{
// Disallow controller change to other zones than the table.
if (((targetzone->getType() != PublicZone) || !targetzone->hasCoords()) && (startzone->getPlayer() != targetzone->getPlayer()))
@ -302,7 +302,7 @@ ResponseCode Server_Player::moveCard(CommandContainer *cont, Server_CardZone *st
}
}
if (card->getDestroyOnZoneChange() && (startzone != targetzone)) {
if (card->getDestroyOnZoneChange() && (startzone->getName() != targetzone->getName())) {
cont->enqueueGameEventPrivate(new Event_DestroyCard(getPlayerId(), startzone->getName(), card->getId()), game->getGameId());
cont->enqueueGameEventPublic(new Event_DestroyCard(getPlayerId(), startzone->getName(), card->getId()), game->getGameId());
card->deleteLater();
@ -369,7 +369,7 @@ ResponseCode Server_Player::moveCard(CommandContainer *cont, Server_CardZone *st
setCardAttrHelper(cont, targetzone->getName(), card->getId(), "tapped", "1");
}
}
if (startzone->hasCoords())
if (startzone->hasCoords() && fixFreeSpaces)
startzone->fixFreeSpaces(cont);
return RespOk;
@ -383,7 +383,7 @@ void Server_Player::unattachCard(CommandContainer *cont, Server_Card *card)
cont->enqueueGameEventPrivate(new Event_AttachCard(getPlayerId(), zone->getName(), card->getId(), -1, QString(), -1), game->getGameId());
cont->enqueueGameEventPublic(new Event_AttachCard(getPlayerId(), zone->getName(), card->getId(), -1, QString(), -1), game->getGameId());
moveCard(cont, zone, QList<int>() << card->getId(), zone, -1, card->getY(), card->getFaceDown(), card->getTapped());
moveCard(cont, zone, QList<int>() << card->getId(), zone, -1, card->getY(), card->getFaceDown(), false);
}
ResponseCode Server_Player::setCardAttrHelper(CommandContainer *cont, const QString &zoneName, int cardId, const QString &attrName, const QString &attrValue)

View file

@ -76,7 +76,7 @@ public:
void setupZones();
ResponseCode moveCard(CommandContainer *cont, const QString &_startZone, const QList<int> &_cardId, int _targetPlayer, const QString &_targetZone, int _x, int _y, bool _faceDown, bool _tapped);
ResponseCode moveCard(CommandContainer *cont, Server_CardZone *startzone, const QList<int> &_cardId, Server_CardZone *targetzone, int x, int y, bool faceDown, bool tapped);
ResponseCode moveCard(CommandContainer *cont, Server_CardZone *startzone, const QList<int> &_cardId, Server_CardZone *targetzone, int x, int y, bool faceDown, bool tapped, bool fixFreeSpaces = true);
void unattachCard(CommandContainer *cont, Server_Card *card);
ResponseCode setCardAttrHelper(CommandContainer *cont, const QString &zone, int cardId, const QString &attrName, const QString &attrValue);

View file

@ -129,7 +129,6 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm
default: return RespInvalidCommand;
}
}
qDebug() << "received generic Command";
switch (command->getItemId()) {
case ItemId_Command_Ping: return cmdPing(static_cast<Command_Ping *>(command), cont);
case ItemId_Command_Login: return cmdLogin(static_cast<Command_Login *>(command), cont);
@ -659,7 +658,8 @@ ResponseCode Server_ProtocolHandler::cmdAttachCard(Command_AttachCard *cmd, Comm
if (targetCard) {
// Unattach all cards attached to the card being attached.
const QList<Server_Card *> &attachedList = card->getAttachedCards();
// Make a copy of the list because its contents change during the loop otherwise.
QList<Server_Card *> attachedList = card->getAttachedCards();
for (int i = 0; i < attachedList.size(); ++i)
player->unattachCard(cont, attachedList[i]);
@ -670,6 +670,7 @@ ResponseCode Server_ProtocolHandler::cmdAttachCard(Command_AttachCard *cmd, Comm
card->setCoords(-1, card->getY());
cont->enqueueGameEventPrivate(new Event_AttachCard(player->getPlayerId(), startzone->getName(), card->getId(), targetPlayer->getPlayerId(), targetzone->getName(), targetCard->getId()), game->getGameId());
cont->enqueueGameEventPublic(new Event_AttachCard(player->getPlayerId(), startzone->getName(), card->getId(), targetPlayer->getPlayerId(), targetzone->getName(), targetCard->getId()), game->getGameId());
startzone->fixFreeSpaces(cont);
} else
player->unattachCard(cont, card);

View file

@ -225,4 +225,4 @@ void Servatrice::statusUpdate()
execSqlQuery(query);
}
const QString Servatrice::versionString = "Servatrice 0.20110114";
const QString Servatrice::versionString = "Servatrice 0.20110124";