Merge branch 'translation' of git://cockatrice.git.sourceforge.net/gitroot/cockatrice/cockatrice into translation

This commit is contained in:
Milton Goncalves 2011-07-12 00:27:45 +01:00
commit b38f5b6bb9
169 changed files with 38294 additions and 8847 deletions

View file

@ -26,6 +26,7 @@ AbstractCardItem::AbstractCardItem(const QString &_name, Player *_owner, QGraphi
AbstractCardItem::~AbstractCardItem()
{
qDebug() << "AbstractCardItem destructor:" << name;
emit deleteCardInfoPopup(name);
}
QRectF AbstractCardItem::boundingRect() const
@ -157,6 +158,10 @@ void AbstractCardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *
void AbstractCardItem::setName(const QString &_name)
{
if (name == _name)
return;
emit deleteCardInfoPopup(name);
disconnect(info, 0, this, 0);
name = _name;
info = db->getCard(name);
@ -212,6 +217,9 @@ void AbstractCardItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
void AbstractCardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::MidButton)
emit deleteCardInfoPopup(name);
// This function ensures the parent function doesn't mess around with our selection.
event->accept();
}

View file

@ -30,7 +30,7 @@ private slots:
signals:
void hovered(AbstractCardItem *card);
void showCardInfoPopup(QPoint pos, QString cardName);
void deleteCardInfoPopup();
void deleteCardInfoPopup(QString cardName);
public:
enum { Type = typeCard };
int type() const { return Type; }
@ -50,6 +50,7 @@ public:
bool getTapped() const { return tapped; }
void setTapped(bool _tapped, bool canAnimate = false);
void processHoverEvent();
void deleteCardInfoPopup() { emit deleteCardInfoPopup(name); }
protected:
QSizeF getTranslatedSize(QPainter *painter) const;
void transformPainter(QPainter *painter, const QSizeF &translatedSize, int angle);

View file

@ -32,15 +32,16 @@ void AbstractClient::processProtocolItem(ProtocolItem *item)
GenericEvent *genericEvent = qobject_cast<GenericEvent *>(item);
if (genericEvent) {
switch (genericEvent->getItemId()) {
case ItemId_Event_ConnectionClosed: emit connectionClosedEventReceived(qobject_cast<Event_ConnectionClosed *>(item)); break;
case ItemId_Event_AddToList: emit addToListEventReceived(qobject_cast<Event_AddToList *>(item)); break;
case ItemId_Event_RemoveFromList: emit removeFromListEventReceived(qobject_cast<Event_RemoveFromList *>(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_ListRooms: emit listRoomsEventReceived(qobject_cast<Event_ListRooms *>(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;
case ItemId_Event_ConnectionClosed: emit connectionClosedEventReceived(static_cast<Event_ConnectionClosed *>(item)); break;
case ItemId_Event_ServerShutdown: emit serverShutdownEventReceived(static_cast<Event_ServerShutdown *>(item)); break;
case ItemId_Event_AddToList: emit addToListEventReceived(static_cast<Event_AddToList *>(item)); break;
case ItemId_Event_RemoveFromList: emit removeFromListEventReceived(static_cast<Event_RemoveFromList *>(item)); break;
case ItemId_Event_UserJoined: emit userJoinedEventReceived(static_cast<Event_UserJoined *>(item)); break;
case ItemId_Event_UserLeft: emit userLeftEventReceived(static_cast<Event_UserLeft *>(item)); break;
case ItemId_Event_ServerMessage: emit serverMessageEventReceived(static_cast<Event_ServerMessage *>(item)); break;
case ItemId_Event_ListRooms: emit listRoomsEventReceived(static_cast<Event_ListRooms *>(item)); break;
case ItemId_Event_GameJoined: emit gameJoinedEventReceived(static_cast<Event_GameJoined *>(item)); break;
case ItemId_Event_Message: emit messageEventReceived(static_cast<Event_Message *>(item)); break;
}
if (genericEvent->getReceiverMayDelete())
delete genericEvent;

View file

@ -21,6 +21,7 @@ class Event_ListRooms;
class Event_GameJoined;
class Event_Message;
class Event_ConnectionClosed;
class Event_ServerShutdown;
enum ClientStatus {
StatusDisconnected,
@ -43,6 +44,7 @@ signals:
void gameEventContainerReceived(GameEventContainer *event);
// Generic events
void connectionClosedEventReceived(Event_ConnectionClosed *event);
void serverShutdownEventReceived(Event_ServerShutdown *event);
void addToListEventReceived(Event_AddToList *event);
void removeFromListEventReceived(Event_RemoveFromList *event);
void userJoinedEventReceived(Event_UserJoined *event);

View file

@ -298,8 +298,8 @@ QString CardInfo::getMainCardType() const
QString CardInfo::getCorrectedName() const
{
QString result = name;
// Fire // Ice, Circle of Protection: Red
return result.remove(" // ").remove(":");
// Fire // Ice, Circle of Protection: Red, "Ach! Hans, Run!", Who/What/When/Where/Why, Question Elemental?
return result.remove(" // ").remove(':').remove('"').remove('?').replace('/', ' ');
}
void CardInfo::addToSet(CardSet *set)

View file

@ -31,11 +31,11 @@ private:
QSet<QString> cardTypes, cardColors;
public:
CardDatabaseDisplayModel(QObject *parent = 0);
void setCardNameBeginning(const QString &_beginning) { cardNameBeginning = _beginning; invalidateFilter(); }
void setCardName(const QString &_cardName) { cardName = _cardName; invalidateFilter(); }
void setCardText(const QString &_cardText) { cardText = _cardText; invalidateFilter(); }
void setCardTypes(const QSet<QString> &_cardTypes) { cardTypes = _cardTypes; invalidateFilter(); }
void setCardColors(const QSet<QString> &_cardColors) { cardColors = _cardColors; invalidateFilter(); }
void setCardNameBeginning(const QString &_beginning) { cardNameBeginning = _beginning; invalidate(); }
void setCardName(const QString &_cardName) { cardName = _cardName; invalidate(); }
void setCardText(const QString &_cardText) { cardText = _cardText; invalidate(); }
void setCardTypes(const QSet<QString> &_cardTypes) { cardTypes = _cardTypes; invalidate(); }
void setCardColors(const QSet<QString> &_cardColors) { cardColors = _cardColors; invalidate(); }
void clearSearch();
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;

View file

@ -11,13 +11,24 @@
#include "settingscache.h"
CardInfoWidget::CardInfoWidget(ResizeMode _mode, QWidget *parent, Qt::WindowFlags flags)
: QFrame(parent, flags), pixmapWidth(160), aspectRatio((qreal) CARD_HEIGHT / (qreal) CARD_WIDTH), minimized(false), mode(_mode), minimizeButton(0), info(0)
: QFrame(parent, flags)
, pixmapWidth(160)
, aspectRatio((qreal) CARD_HEIGHT / (qreal) CARD_WIDTH)
, minimized(settingsCache->getCardInfoMinimized()) // Initialize the cardinfo view status from cache.
, mode(_mode)
, info(0)
{
if (mode == ModeGameTab) {
minimizeButton = new QPushButton(QIcon(style()->standardIcon(QStyle::SP_ArrowUp)), QString());
connect(minimizeButton, SIGNAL(clicked()), this, SLOT(minimizeClicked()));
// Create indexed list of status views for card.
const QStringList cardInfoStatus = QStringList() << tr("Hide card info") << tr("Show card only") << tr("Show text only") << tr("Show full info");
// Create droplist for cardinfo view selection, and set right current index.
dropList = new QComboBox();
dropList->addItems(cardInfoStatus);
dropList->setCurrentIndex(minimized);
connect(dropList, SIGNAL(currentIndexChanged(int)), this, SLOT(minimizeClicked(int)));
}
cardPicture = new QLabel;
cardPicture->setAlignment(Qt::AlignCenter);
@ -39,7 +50,7 @@ CardInfoWidget::CardInfoWidget(ResizeMode _mode, QWidget *parent, Qt::WindowFlag
QGridLayout *grid = new QGridLayout(this);
int row = 0;
if (mode == ModeGameTab)
grid->addWidget(minimizeButton, row++, 1, 1, 1, Qt::AlignRight);
grid->addWidget(dropList, row++, 1, 1, 1, Qt::AlignRight);
grid->addWidget(cardPicture, row++, 0, 1, 2);
grid->addWidget(nameLabel1, row, 0);
grid->addWidget(nameLabel2, row++, 1);
@ -70,30 +81,38 @@ CardInfoWidget::CardInfoWidget(ResizeMode _mode, QWidget *parent, Qt::WindowFlag
setFixedHeight(sizeHint().height());
}
void CardInfoWidget::minimizeClicked()
void CardInfoWidget::minimizeClicked(int newMinimized)
{
setMinimized(!minimized);
settingsCache->setCardInfoMinimized(minimized);
// Set new status, and store it in the settings cache.
setMinimized(newMinimized);
settingsCache->setCardInfoMinimized(newMinimized);
}
void CardInfoWidget::setMinimized(bool _minimized)
void CardInfoWidget::setMinimized(int _minimized)
{
minimized = _minimized;
cardPicture->setVisible(!minimized);
nameLabel2->setVisible(!minimized);
nameLabel1->setVisible(!minimized);
manacostLabel1->setVisible(!minimized);
manacostLabel2->setVisible(!minimized);
cardtypeLabel1->setVisible(!minimized);
cardtypeLabel2->setVisible(!minimized);
powtoughLabel1->setVisible(!minimized);
powtoughLabel2->setVisible(!minimized);
textLabel->setVisible(!minimized);
if (minimizeButton)
minimizeButton->setIcon(style()->standardIcon(minimized ? QStyle::SP_ArrowDown : QStyle::SP_ArrowUp));
// Set the picture to be shown only at "card only" (1) and "full info" (3)
if (minimized == 1 || minimized == 3) {
cardPicture->setVisible(true);
} else {
cardPicture->setVisible(false);
}
// Set the rest of the fields to be shown only at "full info" (3) and "oracle only" (2)
bool showAll = (minimized == 2 || minimized == 3) ? true : false;
// Toggle oracle fields as according to selected view.
nameLabel2->setVisible(showAll);
nameLabel1->setVisible(showAll);
manacostLabel1->setVisible(showAll);
manacostLabel2->setVisible(showAll);
cardtypeLabel1->setVisible(showAll);
cardtypeLabel2->setVisible(showAll);
powtoughLabel1->setVisible(showAll);
powtoughLabel2->setVisible(showAll);
textLabel->setVisible(showAll);
setFixedHeight(sizeHint().height());
}
@ -153,8 +172,7 @@ void CardInfoWidget::resizeEvent(QResizeEvent * /*event*/)
}
}
void CardInfoWidget::mouseReleaseEvent(QMouseEvent *event)
QString CardInfoWidget::getCardName() const
{
if ((event->button() == Qt::MidButton) && (mode == ModePopUp))
emit mouseReleased();
}
return nameLabel2->text();
}

View file

@ -2,6 +2,8 @@
#define CARDINFOWIDGET_H
#include <QFrame>
#include <QStringList>
#include <QComboBox>
class QLabel;
class QTextEdit;
@ -13,40 +15,44 @@ class QMouseEvent;
class CardInfoWidget : public QFrame {
Q_OBJECT
public:
enum ResizeMode { ModeDeckEditor, ModeGameTab, ModePopUp };
private:
int pixmapWidth;
qreal aspectRatio;
bool minimized;
int minimized; // 0 - minimized, 1 - card, 2 - oracle only, 3 - full
ResizeMode mode;
QPushButton *minimizeButton;
QComboBox *dropList;
QLabel *cardPicture;
QLabel *nameLabel1, *nameLabel2;
QLabel *manacostLabel1, *manacostLabel2;
QLabel *cardtypeLabel1, *cardtypeLabel2;
QLabel *powtoughLabel1, *powtoughLabel2;
QTextEdit *textLabel;
CardInfo *info;
void setMinimized(bool _minimized);
void setMinimized(int _minimized);
public:
CardInfoWidget(ResizeMode _mode, QWidget *parent = 0, Qt::WindowFlags f = 0);
void retranslateUi();
QString getCardName() const;
public slots:
void setCard(CardInfo *card);
void setCard(const QString &cardName);
void setCard(AbstractCardItem *card);
private slots:
void clear();
void updatePixmap();
void minimizeClicked();
signals:
void mouseReleased();
void minimizeClicked(int newMinimized);
protected:
void resizeEvent(QResizeEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
};
#endif

View file

@ -34,6 +34,8 @@ CardItem::CardItem(Player *_owner, const QString &_name, int _cardid, bool _reve
connect(aAttach, SIGNAL(triggered()), this, SLOT(actAttach()));
aUnattach = new QAction(this);
connect(aUnattach, SIGNAL(triggered()), this, SLOT(actUnattach()));
aDrawArrow = new QAction(this);
connect(aDrawArrow, SIGNAL(triggered()), this, SLOT(actDrawArrow()));
aIncP = new QAction(this);
connect(aIncP, SIGNAL(triggered()), this, SLOT(actIncP()));
aDecP = new QAction(this);
@ -172,6 +174,7 @@ void CardItem::updateCardMenu()
cardMenu->addAction(aAttach);
if (attachedTo)
cardMenu->addAction(aUnattach);
cardMenu->addAction(aDrawArrow);
cardMenu->addSeparator();
cardMenu->addMenu(ptMenu);
cardMenu->addAction(aSetAnnotation);
@ -186,6 +189,9 @@ void CardItem::updateCardMenu()
cardMenu->addAction(aSetCounter[i]);
}
cardMenu->addSeparator();
} else if (zone->getName() == "stack") {
cardMenu->addAction(aDrawArrow);
cardMenu->addMenu(moveMenu);
} else {
cardMenu->addAction(aPlay);
cardMenu->addMenu(moveMenu);
@ -209,6 +215,7 @@ void CardItem::retranslateUi()
aAttach->setText(tr("&Attach to card..."));
aAttach->setShortcut(tr("Ctrl+A"));
aUnattach->setText(tr("Unattac&h"));
aDrawArrow->setText(tr("&Draw arrow..."));
ptMenu->setTitle(tr("&Power / toughness"));
aIncP->setText(tr("&Increase power"));
aIncP->setShortcut(tr("Ctrl++"));
@ -360,7 +367,7 @@ void CardItem::resetState()
annotation.clear();
attachedTo = 0;
attachedCards.clear();
setTapped(false);
setTapped(false, false);
setDoesntUntap(false);
update();
}
@ -380,6 +387,7 @@ void CardItem::processCardInfo(ServerInfo_Card *info)
setColor(info->getColor());
setTapped(info->getTapped());
setDestroyOnZoneChange(info->getDestroyOnZoneChange());
setDoesntUntap(info->getDoesntUntap());
}
CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown)
@ -398,13 +406,35 @@ void CardItem::deleteDragItem()
dragItem = NULL;
}
void CardItem::drawArrow(const QColor &arrowColor)
{
if (static_cast<TabGame *>(owner->parent())->getSpectator())
return;
Player *arrowOwner = static_cast<TabGame *>(owner->parent())->getActiveLocalPlayer();
ArrowDragItem *arrow = new ArrowDragItem(arrowOwner, this, arrowColor);
scene()->addItem(arrow);
arrow->grabMouse();
QListIterator<QGraphicsItem *> itemIterator(scene()->selectedItems());
while (itemIterator.hasNext()) {
CardItem *c = qgraphicsitem_cast<CardItem *>(itemIterator.next());
if (!c || (c == this))
continue;
if (c->getZone() != zone)
continue;
ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, c, arrowColor);
scene()->addItem(childArrow);
arrow->addChildArrow(childArrow);
}
}
void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (event->buttons().testFlag(Qt::RightButton)) {
if ((event->screenPos() - event->buttonDownScreenPos(Qt::RightButton)).manhattanLength() < 2 * QApplication::startDragDistance())
return;
if (static_cast<TabGame *>(owner->parent())->getSpectator())
return;
QColor arrowColor = Qt::red;
if (event->modifiers().testFlag(Qt::ControlModifier))
@ -414,23 +444,7 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
else if (event->modifiers().testFlag(Qt::ShiftModifier))
arrowColor = Qt::green;
Player *arrowOwner = static_cast<TabGame *>(owner->parent())->getActiveLocalPlayer();
ArrowDragItem *arrow = new ArrowDragItem(arrowOwner, this, arrowColor);
scene()->addItem(arrow);
arrow->grabMouse();
QListIterator<QGraphicsItem *> itemIterator(scene()->selectedItems());
while (itemIterator.hasNext()) {
CardItem *c = qgraphicsitem_cast<CardItem *>(itemIterator.next());
if (!c || (c == this))
continue;
if (c->getZone() != zone)
continue;
ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, c, arrowColor);
scene()->addItem(childArrow);
arrow->addChildArrow(childArrow);
}
drawArrow(arrowColor);
} else if (event->buttons().testFlag(Qt::LeftButton)) {
if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < 2 * QApplication::startDragDistance())
return;
@ -546,6 +560,11 @@ void CardItem::actUnattach()
owner->actUnattach(static_cast<QAction *>(sender()));
}
void CardItem::actDrawArrow()
{
drawArrow(Qt::red);
}
void CardItem::actIncP()
{
owner->actIncPT(1, 0);

View file

@ -9,6 +9,7 @@ class CardZone;
class ServerInfo_Card;
class Player;
class QAction;
class QColor;
const int MAX_COUNTERS_ON_CARD = 999;
@ -33,17 +34,19 @@ private:
QList<QAction *> aAddCounter, aSetCounter, aRemoveCounter;
QAction *aPlay,
*aHide,
*aTap, *aUntap, *aDoesntUntap, *aAttach, *aUnattach, *aSetPT, *aIncP, *aDecP, *aIncT, *aDecT, *aIncPT, *aDecPT, *aSetAnnotation, *aFlip, *aClone,
*aTap, *aUntap, *aDoesntUntap, *aAttach, *aUnattach, *aDrawArrow, *aSetPT, *aIncP, *aDecP, *aIncT, *aDecT, *aIncPT, *aDecPT, *aSetAnnotation, *aFlip, *aClone,
*aMoveToTopLibrary, *aMoveToBottomLibrary, *aMoveToGraveyard, *aMoveToExile;
QMenu *cardMenu, *ptMenu, *moveMenu;
void playCard(bool faceDown);
void drawArrow(const QColor &arrowColor);
void prepareDelete();
private slots:
void cardMenuAction();
void actCardCounterTrigger();
void actAttach();
void actUnattach();
void actDrawArrow();
void actSetPT();
void actIncP();
void actDecP();

View file

@ -46,35 +46,36 @@ void CardZone::clearContents()
QString CardZone::getTranslatedName(bool hisOwn, GrammaticalCase gc) const
{
QString ownerName = player->getName();
bool female = player->getUserInfo()->getGender() == ServerInfo_User::Female;
if (name == "hand")
switch (gc) {
case CaseNominative: return hisOwn ? tr("his hand", "nominative") : tr("%1's hand", "nominative").arg(ownerName);
case CaseGenitive: return hisOwn ? tr("of his hand", "genitive") : tr("of %1's hand", "genitive").arg(ownerName);
case CaseAccusative: return hisOwn ? tr("his hand", "accusative") : tr("%1's hand", "accusative").arg(ownerName);
case CaseNominative: return female ? (hisOwn ? tr("her hand", "nominative, female owner") : tr("%1's hand", "nominative, female owner").arg(ownerName)) : (hisOwn ? tr("his hand", "nominative, male owner") : tr("%1's hand", "nominative, male owner").arg(ownerName));
case CaseGenitive: return female ? (hisOwn ? tr("of her hand", "genitive, female owner") : tr("of %1's hand", "genitive, female owner").arg(ownerName)) : (hisOwn ? tr("of his hand", "genitive, male owner") : tr("of %1's hand", "genitive, male owner").arg(ownerName));
case CaseAccusative: return female ? (hisOwn ? tr("her hand", "accusative, female owner") : tr("%1's hand", "accusative, female owner").arg(ownerName)) : (hisOwn ? tr("his hand", "accusative, male owner") : tr("%1's hand", "accusative, male owner").arg(ownerName));
}
else if (name == "deck")
switch (gc) {
case CaseNominative: return hisOwn ? tr("his library", "nominative") : tr("%1's library", "nominative").arg(ownerName);
case CaseGenitive: return hisOwn ? tr("of his library", "genitive") : tr("of %1's library", "genitive").arg(ownerName);
case CaseAccusative: return hisOwn ? tr("his library", "accusative") : tr("%1's library", "accusative").arg(ownerName);
case CaseNominative: return female ? (hisOwn ? tr("her library", "nominative, female owner") : tr("%1's library", "nominative, female owner").arg(ownerName)) : (hisOwn ? tr("his library", "nominative, male owner") : tr("%1's library", "nominative, male owner").arg(ownerName));
case CaseGenitive: return female ? (hisOwn ? tr("of her library", "genitive, female owner") : tr("of %1's library", "genitive, female owner").arg(ownerName)) : (hisOwn ? tr("of his library", "genitive, male owner") : tr("of %1's library", "genitive, male owner").arg(ownerName));
case CaseAccusative: return female ? (hisOwn ? tr("her library", "accusative, female owner") : tr("%1's library", "accusative, female owner").arg(ownerName)) : (hisOwn ? tr("his library", "accusative, male owner") : tr("%1's library", "accusative, male owner").arg(ownerName));
}
else if (name == "grave")
switch (gc) {
case CaseNominative: return hisOwn ? tr("his graveyard", "nominative") : tr("%1's graveyard", "nominative").arg(ownerName);
case CaseGenitive: return hisOwn ? tr("of his graveyard", "genitive") : tr("of %1's graveyard", "genitive").arg(ownerName);
case CaseAccusative: return hisOwn ? tr("his graveyard", "accusative") : tr("%1's graveyard", "accusative").arg(ownerName);
case CaseNominative: return female ? (hisOwn ? tr("her graveyard", "nominative, female owner") : tr("%1's graveyard", "nominative, female owner").arg(ownerName)) : (hisOwn ? tr("his graveyard", "nominative, male owner") : tr("%1's graveyard", "nominative, male owner").arg(ownerName));
case CaseGenitive: return female ? (hisOwn ? tr("of her graveyard", "genitive, female owner") : tr("of %1's graveyard", "genitive, female owner").arg(ownerName)) : (hisOwn ? tr("of his graveyard", "genitive, male owner") : tr("of %1's graveyard", "genitive, male owner").arg(ownerName));
case CaseAccusative: return female ? (hisOwn ? tr("her graveyard", "accusative, female owner") : tr("%1's graveyard", "accusative, female owner").arg(ownerName)) : (hisOwn ? tr("his graveyard", "accusative, male owner") : tr("%1's graveyard", "accusative, male owner").arg(ownerName));
}
else if (name == "rfg")
switch (gc) {
case CaseNominative: return hisOwn ? tr("his exile", "nominative") : tr("%1's exile", "nominative").arg(ownerName);
case CaseGenitive: return hisOwn ? tr("of his exile", "genitive") : tr("of %1's exile", "genitive").arg(ownerName);
case CaseAccusative: return hisOwn ? tr("his exile", "accusative") : tr("%1's exile", "accusative").arg(ownerName);
case CaseNominative: return female ? (hisOwn ? tr("her exile", "nominative, female owner") : tr("%1's exile", "nominative, female owner").arg(ownerName)) : (hisOwn ? tr("his exile", "nominative, male owner") : tr("%1's exile", "nominative, male owner").arg(ownerName));
case CaseGenitive: return female ? (hisOwn ? tr("of her exile", "genitive, female owner") : tr("of %1's exile", "genitive, female owner").arg(ownerName)) : (hisOwn ? tr("of his exile", "genitive, male owner") : tr("of %1's exile", "genitive, male owner").arg(ownerName));
case CaseAccusative: return female ? (hisOwn ? tr("her exile", "accusative, female owner") : tr("%1's exile", "accusative, female owner").arg(ownerName)) : (hisOwn ? tr("his exile", "accusative, male owner") : tr("%1's exile", "accusative, male owner").arg(ownerName));
}
else if (name == "sb")
switch (gc) {
case CaseNominative: return hisOwn ? tr("his sideboard", "nominative") : tr("%1's sideboard", "nominative").arg(ownerName);
case CaseGenitive: return hisOwn ? tr("of his sideboard", "genitive") : tr("of %1's sideboard", "genitive").arg(ownerName);
case CaseAccusative: return hisOwn ? tr("his sideboard", "accusative") : tr("%1's sideboard", "accusative").arg(ownerName);
case CaseNominative: return female ? (hisOwn ? tr("her sideboard", "nominative, female owner") : tr("%1's sideboard", "nominative, female owner").arg(ownerName)) : (hisOwn ? tr("his sideboard", "nominative, male owner") : tr("%1's sideboard", "nominative, male owner").arg(ownerName));
case CaseGenitive: return female ? (hisOwn ? tr("of her sideboard", "genitive, female owner") : tr("of %1's sideboard", "genitive, female owner").arg(ownerName)) : (hisOwn ? tr("of his sideboard", "genitive, male owner") : tr("of %1's sideboard", "genitive, male owner").arg(ownerName));
case CaseAccusative: return female ? (hisOwn ? tr("her sideboard", "accusative, female owner") : tr("%1's sideboard", "accusative, female owner").arg(ownerName)) : (hisOwn ? tr("his sideboard", "accusative, male owner") : tr("%1's sideboard", "accusative, male owner").arg(ownerName));
}
return QString();
}

View file

@ -1,45 +1,198 @@
#include <QTextEdit>
#include <QDateTime>
#include <QTextTable>
#include <QScrollBar>
#include <QMouseEvent>
#include <QDesktopServices>
#include "chatview.h"
ChatView::ChatView(const QString &_ownName, QWidget *parent)
: QTextEdit(parent), ownName(_ownName)
ChatView::ChatView(const QString &_ownName, bool _showTimestamps, QWidget *parent)
: QTextBrowser(parent), evenNumber(true), ownName(_ownName), showTimestamps(_showTimestamps)
{
setTextInteractionFlags(Qt::TextSelectableByMouse);
setReadOnly(true);
setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
setOpenLinks(false);
connect(this, SIGNAL(anchorClicked(const QUrl &)), this, SLOT(openLink(const QUrl &)));
}
void ChatView::appendMessage(QString sender, const QString &message)
QTextCursor ChatView::prepareBlock(bool same)
{
lastSender.clear();
QTextCursor cursor(document()->lastBlock());
cursor.movePosition(QTextCursor::End);
if (!same) {
QTextBlockFormat blockFormat;
if ((evenNumber = !evenNumber))
blockFormat.setBackground(palette().alternateBase());
blockFormat.setBottomMargin(2);
cursor.insertBlock(blockFormat);
} else
cursor.insertHtml("<br>");
QTextBlockFormat blockFormat;
blockFormat.setBottomMargin(3);
cursor.insertBlock(blockFormat);
return cursor;
}
void ChatView::appendHtml(const QString &html)
{
prepareBlock().insertHtml(html);
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
}
void ChatView::appendMessage(QString sender, QString message, QColor playerColor, bool playerBold)
{
bool sameSender = (sender == lastSender) && !lastSender.isEmpty();
QTextCursor cursor = prepareBlock(sameSender);
lastSender = sender;
QTextCharFormat timeFormat;
timeFormat.setForeground(Qt::black);
cursor.setCharFormat(timeFormat);
cursor.insertText(QDateTime::currentDateTime().toString("[hh:mm] "));
if (showTimestamps) {
QTextCharFormat timeFormat;
if (sameSender)
timeFormat.setForeground(Qt::transparent);
else
timeFormat.setForeground(Qt::black);
cursor.setCharFormat(timeFormat);
cursor.insertText(QDateTime::currentDateTime().toString("[hh:mm] "));
}
QTextCharFormat senderFormat;
if (sender == ownName) {
senderFormat.setFontWeight(QFont::Bold);
senderFormat.setForeground(Qt::red);
} else
senderFormat.setForeground(Qt::blue);
} else {
if (playerColor == QColor())
senderFormat.setForeground(QColor(0, 0, 254));
else
senderFormat.setForeground(playerColor);
if (playerBold)
senderFormat.setFontWeight(QFont::Bold);
}
if (sameSender)
senderFormat.setForeground(Qt::transparent);
cursor.setCharFormat(senderFormat);
if (!sender.isEmpty())
sender.append(" ");
sender.append(": ");
cursor.insertText(sender);
QTextCharFormat messageFormat;
if (sender.isEmpty())
messageFormat.setForeground(Qt::darkGreen);
cursor.setCharFormat(messageFormat);
cursor.insertText(message);
int from = 0, index = 0;
while ((index = message.indexOf('[', from)) != -1) {
cursor.insertText(message.left(index));
message = message.mid(index);
if (message.isEmpty())
break;
if (message.startsWith("[card]")) {
message = message.mid(6);
QTextCharFormat tempFormat = messageFormat;
tempFormat.setForeground(Qt::blue);
cursor.setCharFormat(tempFormat);
int closeTagIndex = message.indexOf("[/card]");
cursor.insertText(message.left(closeTagIndex));
cursor.setCharFormat(messageFormat);
if (closeTagIndex == -1)
message.clear();
else
message = message.mid(closeTagIndex + 7);
} else if (message.startsWith("[url]")) {
message = message.mid(5);
int closeTagIndex = message.indexOf("[/url]");
QString url = message.left(closeTagIndex);
if (!url.startsWith("http://"))
url.prepend("http://");
QTextCharFormat tempFormat = messageFormat;
tempFormat.setForeground(QColor(0, 0, 254));
tempFormat.setAnchor(true);
tempFormat.setAnchorHref(url);
cursor.setCharFormat(tempFormat);
cursor.insertText(url);
cursor.setCharFormat(messageFormat);
if (closeTagIndex == -1)
message.clear();
else
message = message.mid(closeTagIndex + 6);
} else
from = 1;
}
if (!message.isEmpty())
cursor.insertText(message);
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
}
void ChatView::enterEvent(QEvent * /*event*/)
{
setMouseTracking(true);
}
void ChatView::leaveEvent(QEvent * /*event*/)
{
setMouseTracking(false);
}
QTextFragment ChatView::getFragmentUnderMouse(const QPoint &pos) const
{
QTextCursor cursor(cursorForPosition(pos));
QTextBlock block(cursor.block());
QTextBlock::iterator it;
for (it = block.begin(); !(it.atEnd()); ++it) {
QTextFragment frag = it.fragment();
if (frag.contains(cursor.position()))
return frag;
}
return QTextFragment();
}
QString ChatView::getCardNameUnderMouse(QTextFragment frag) const
{
if (frag.charFormat().foreground().color() == Qt::blue)
return frag.text();
return QString();
}
QString ChatView::getCardNameUnderMouse(const QPoint &pos) const
{
return getCardNameUnderMouse(getFragmentUnderMouse(pos));
}
void ChatView::mouseMoveEvent(QMouseEvent *event)
{
QTextFragment frag = getFragmentUnderMouse(event->pos());
QString cardName = getCardNameUnderMouse(frag);
if (!cardName.isEmpty()) {
viewport()->setCursor(Qt::PointingHandCursor);
emit cardNameHovered(cardName);
} else if (frag.charFormat().isAnchor())
viewport()->setCursor(Qt::PointingHandCursor);
else
viewport()->setCursor(Qt::IBeamCursor);
QTextBrowser::mouseMoveEvent(event);
}
void ChatView::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::MidButton) {
QString cardName = getCardNameUnderMouse(event->pos());
if (!cardName.isEmpty())
emit showCardInfoPopup(event->globalPos(), cardName);
}
QTextBrowser::mousePressEvent(event);
}
void ChatView::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::MidButton)
emit deleteCardInfoPopup(QString("_"));
QTextBrowser::mouseReleaseEvent(event);
}
void ChatView::openLink(const QUrl &link)
{
QDesktopServices::openUrl(link);
}

View file

@ -1,18 +1,41 @@
#ifndef CHATVIEW_H
#define CHATVIEW_H
#include <QTextEdit>
#include <QTextBrowser>
#include <QTextFragment>
#include <QTextCursor>
#include <QColor>
class QTextTable;
class QMouseEvent;
class ChatView : public QTextEdit {
class ChatView : public QTextBrowser {
Q_OBJECT;
private:
QTextTable *table;
QString lastSender;
bool evenNumber;
QString ownName;
bool showTimestamps;
QTextFragment getFragmentUnderMouse(const QPoint &pos) const;
QString getCardNameUnderMouse(QTextFragment frag) const;
QString getCardNameUnderMouse(const QPoint &pos) const;
QTextCursor prepareBlock(bool same = false);
private slots:
void openLink(const QUrl &link);
public:
ChatView(const QString &_ownName, QWidget *parent = 0);
void appendMessage(QString sender, const QString &message);
ChatView(const QString &_ownName, bool _showTimestamps, QWidget *parent = 0);
void appendHtml(const QString &html);
void appendMessage(QString sender, QString message, QColor playerColor = QColor(), bool playerBold = false);
protected:
void enterEvent(QEvent *event);
void leaveEvent(QEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
signals:
void cardNameHovered(QString cardName);
void showCardInfoPopup(QPoint pos, QString cardName);
void deleteCardInfoPopup(QString cardName);
};
#endif

View file

@ -10,6 +10,7 @@
#include "main.h"
#include "decklistmodel.h"
#include "carddatabase.h"
#include "settingscache.h"
DeckListModel::DeckListModel(QObject *parent)
: QAbstractItemModel(parent)
@ -65,12 +66,20 @@ int DeckListModel::rowCount(const QModelIndex &parent) const
return 0;
}
int DeckListModel::columnCount(const QModelIndex &/*parent*/) const
{
if (settingsCache->getPriceTagFeature())
return 3;
else
return 2;
}
QVariant DeckListModel::data(const QModelIndex &index, int role) const
{
// debugIndexInfo("data", index);
if (!index.isValid())
return QVariant();
if (index.column() >= 2)
if (index.column() >= columnCount())
return QVariant();
AbstractDecklistNode *temp = static_cast<AbstractDecklistNode *>(index.internalPointer());
@ -86,8 +95,9 @@ QVariant DeckListModel::data(const QModelIndex &index, int role) const
case Qt::DisplayRole:
case Qt::EditRole:
switch (index.column()) {
case 0: return node->recursiveCount(true);
case 1: return node->getVisibleName();
case 0: return node->recursiveCount(true);
case 1: return node->getVisibleName();
case 2: return QString().sprintf("$%.2f", node->recursivePrice(true));
default: return QVariant();
}
case Qt::BackgroundRole: {
@ -101,8 +111,9 @@ QVariant DeckListModel::data(const QModelIndex &index, int role) const
case Qt::DisplayRole:
case Qt::EditRole: {
switch (index.column()) {
case 0: return card->getNumber();
case 1: return card->getName();
case 0: return card->getNumber();
case 1: return card->getName();
case 2: return QString().sprintf("$%.2f", card->getTotalPrice());
default: return QVariant();
}
}
@ -119,9 +130,12 @@ QVariant DeckListModel::headerData(int section, Qt::Orientation orientation, int
{
if ((role != Qt::DisplayRole) || (orientation != Qt::Horizontal))
return QVariant();
if (section >= columnCount())
return QVariant();
switch (section) {
case 0: return tr("Number");
case 1: return tr("Card");
case 0: return tr("Number");
case 1: return tr("Card");
case 2: return tr("Price");
default: return QVariant();
}
}
@ -174,8 +188,9 @@ bool DeckListModel::setData(const QModelIndex &index, const QVariant &value, int
return false;
switch (index.column()) {
case 0: node->setNumber(value.toInt()); break;
case 1: node->setName(value.toString()); break;
case 0: node->setNumber(value.toInt()); break;
case 1: node->setName(value.toString()); break;
case 2: node->setPrice(value.toFloat()); break;
default: return false;
}
emitRecursiveUpdates(index);
@ -300,7 +315,7 @@ void DeckListModel::setDeckList(DeckList *_deck)
void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *node)
{
static const int totalColumns = 3;
const int totalColumns = settingsCache->getPriceTagFeature() ? 3 : 2;
if (node->height() == 1) {
QTextBlockFormat blockFormat;
@ -308,13 +323,16 @@ void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *no
charFormat.setFontPointSize(11);
charFormat.setFontWeight(QFont::Bold);
cursor->insertBlock(blockFormat, charFormat);
cursor->insertText(QString("%1: %2").arg(node->getVisibleName()).arg(node->recursiveCount(true)));
QString priceStr;
if (settingsCache->getPriceTagFeature())
priceStr = QString().sprintf(": $%.2f", node->recursivePrice(true));
cursor->insertText(QString("%1: %2").arg(node->getVisibleName()).arg(node->recursiveCount(true)).append(priceStr));
QTextTableFormat tableFormat;
tableFormat.setCellPadding(0);
tableFormat.setCellSpacing(0);
tableFormat.setBorder(0);
QTextTable *table = cursor->insertTable(node->size() + 1, 2, tableFormat);
QTextTable *table = cursor->insertTable(node->size() + 1, totalColumns, tableFormat);
for (int i = 0; i < node->size(); i++) {
AbstractDecklistCardNode *card = dynamic_cast<AbstractDecklistCardNode *>(node->at(i));
@ -330,6 +348,13 @@ void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *no
cell.setFormat(cellCharFormat);
cellCursor = cell.firstCursorPosition();
cellCursor.insertText(card->getName());
if (settingsCache->getPriceTagFeature()) {
cell = table->cellAt(i, 2);
cell.setFormat(cellCharFormat);
cellCursor = cell.firstCursorPosition();
cellCursor.insertText(QString().sprintf("$%.2f ", card->getTotalPrice()));
}
}
} else if (node->height() == 2) {
QTextBlockFormat blockFormat;
@ -338,7 +363,10 @@ void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *no
charFormat.setFontWeight(QFont::Bold);
cursor->insertBlock(blockFormat, charFormat);
cursor->insertText(QString("%1: %2").arg(node->getVisibleName()).arg(node->recursiveCount(true)));
QString priceStr;
if (settingsCache->getPriceTagFeature())
priceStr = QString().sprintf(": $%.2f", node->recursivePrice(true));
cursor->insertText(QString("%1: %2").arg(node->getVisibleName()).arg(node->recursiveCount(true)).append(priceStr));
QTextTableFormat tableFormat;
tableFormat.setCellPadding(10);
@ -391,3 +419,14 @@ void DeckListModel::printDeckList(QPrinter *printer)
doc.print(printer);
}
void DeckListModel::pricesUpdated(InnerDecklistNode *node)
{
if (!node)
node = root;
if (node->isEmpty())
return;
emit dataChanged(createIndex(0, 2, node->at(0)), createIndex(node->size() - 1, 2, node->last()));
}

View file

@ -17,6 +17,8 @@ public:
DecklistModelCardNode(DecklistCardNode *_dataNode, InnerDecklistNode *_parent) : AbstractDecklistCardNode(_parent), dataNode(_dataNode) { }
int getNumber() const { return dataNode->getNumber(); }
void setNumber(int _number) { dataNode->setNumber(_number); }
float getPrice() const { return dataNode->getPrice(); }
void setPrice(float _price) { dataNode->setPrice(_price); }
QString getName() const { return dataNode->getName(); }
void setName(const QString &_name) { dataNode->setName(_name); }
DecklistCardNode *getDataNode() const { return dataNode; }
@ -32,7 +34,7 @@ public:
DeckListModel(QObject *parent = 0);
~DeckListModel();
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const { return 2; }
int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
@ -45,6 +47,7 @@ public:
void cleanList();
DeckList *getDeckList() const { return deckList; }
void setDeckList(DeckList *_deck);
void pricesUpdated(InnerDecklistNode *node = 0);
private:
DeckList *deckList;
InnerDecklistNode *root;

View file

@ -17,6 +17,7 @@ DlgCreateGame::DlgCreateGame(AbstractClient *_client, int _roomId, const QMap<in
descriptionLabel = new QLabel(tr("&Description:"));
descriptionEdit = new QLineEdit;
descriptionLabel->setBuddy(descriptionEdit);
descriptionEdit->setMaxLength(60);
maxPlayersLabel = new QLabel(tr("P&layers:"));
maxPlayersEdit = new QSpinBox();

View file

@ -16,6 +16,7 @@
#include <QSettings>
#include <QApplication>
#include <QInputDialog>
#include <QSpinBox>
#include "carddatabase.h"
#include "dlg_settings.h"
#include "main.h"
@ -242,8 +243,17 @@ AppearanceSettingsPage::AppearanceSettingsPage()
invertVerticalCoordinateCheckBox->setChecked(settingsCache->getInvertVerticalCoordinate());
connect(invertVerticalCoordinateCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setInvertVerticalCoordinate(int)));
minPlayersForMultiColumnLayoutLabel = new QLabel;
minPlayersForMultiColumnLayoutEdit = new QSpinBox;
minPlayersForMultiColumnLayoutEdit->setMinimum(2);
minPlayersForMultiColumnLayoutEdit->setValue(settingsCache->getMinPlayersForMultiColumnLayout());
connect(minPlayersForMultiColumnLayoutEdit, SIGNAL(valueChanged(int)), settingsCache, SLOT(setMinPlayersForMultiColumnLayout(int)));
minPlayersForMultiColumnLayoutLabel->setBuddy(minPlayersForMultiColumnLayoutEdit);
QGridLayout *tableGrid = new QGridLayout;
tableGrid->addWidget(invertVerticalCoordinateCheckBox, 0, 0, 1, 2);
tableGrid->addWidget(minPlayersForMultiColumnLayoutLabel, 1, 0, 1, 1);
tableGrid->addWidget(minPlayersForMultiColumnLayoutEdit, 1, 1, 1, 1);
tableGroupBox = new QGroupBox;
tableGroupBox->setLayout(tableGrid);
@ -289,6 +299,7 @@ void AppearanceSettingsPage::retranslateUi()
tableGroupBox->setTitle(tr("Table grid layout"));
invertVerticalCoordinateCheckBox->setText(tr("Invert vertical coordinate"));
minPlayersForMultiColumnLayoutLabel->setText(tr("Minimum player count for multi-column layout:"));
zoneViewGroupBox->setTitle(tr("Zone view layout"));
zoneViewSortByNameCheckBox->setText(tr("Sort by name"));
@ -377,6 +388,8 @@ void AppearanceSettingsPage::cardBackPicturePathButtonClicked()
UserInterfaceSettingsPage::UserInterfaceSettingsPage()
{
QIcon deleteIcon(":/resources/icon_delete.svg");
doubleClickToPlayCheckBox = new QCheckBox;
doubleClickToPlayCheckBox->setChecked(settingsCache->getDoubleClickToPlay());
connect(doubleClickToPlayCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setDoubleClickToPlay(int)));
@ -391,6 +404,28 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage()
tapAnimationCheckBox->setChecked(settingsCache->getTapAnimation());
connect(tapAnimationCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setTapAnimation(int)));
soundEnabledCheckBox = new QCheckBox;
soundEnabledCheckBox->setChecked(settingsCache->getSoundEnabled());
connect(soundEnabledCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setSoundEnabled(int)));
soundPathLabel = new QLabel;
soundPathEdit = new QLineEdit(settingsCache->getSoundPath());
soundPathEdit->setReadOnly(true);
QPushButton *soundPathClearButton = new QPushButton(deleteIcon, QString());
connect(soundPathClearButton, SIGNAL(clicked()), this, SLOT(soundPathClearButtonClicked()));
QPushButton *soundPathButton = new QPushButton("...");
connect(soundPathButton, SIGNAL(clicked()), this, SLOT(soundPathButtonClicked()));
QGridLayout *soundGrid = new QGridLayout;
soundGrid->addWidget(soundEnabledCheckBox, 0, 0, 1, 4);
soundGrid->addWidget(soundPathLabel, 1, 0);
soundGrid->addWidget(soundPathEdit, 1, 1);
soundGrid->addWidget(soundPathClearButton, 1, 2);
soundGrid->addWidget(soundPathButton, 1, 3);
soundGroupBox = new QGroupBox;
soundGroupBox->setLayout(soundGrid);
QGridLayout *animationGrid = new QGridLayout;
animationGrid->addWidget(tapAnimationCheckBox, 0, 0);
@ -400,6 +435,7 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage()
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(generalGroupBox);
mainLayout->addWidget(animationGroupBox);
mainLayout->addWidget(soundGroupBox);
setLayout(mainLayout);
}
@ -410,6 +446,48 @@ void UserInterfaceSettingsPage::retranslateUi()
doubleClickToPlayCheckBox->setText(tr("&Double-click cards to play them (instead of single-click)"));
animationGroupBox->setTitle(tr("Animation settings"));
tapAnimationCheckBox->setText(tr("&Tap/untap animation"));
soundEnabledCheckBox->setText(tr("Enable &sounds"));
soundPathLabel->setText(tr("Path to sounds directory:"));
}
void UserInterfaceSettingsPage::soundPathClearButtonClicked()
{
soundPathEdit->setText(QString());
settingsCache->setSoundPath(QString());
}
void UserInterfaceSettingsPage::soundPathButtonClicked()
{
QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"));
if (path.isEmpty())
return;
soundPathEdit->setText(path);
settingsCache->setSoundPath(path);
}
DeckEditorSettingsPage::DeckEditorSettingsPage()
{
priceTagsCheckBox = new QCheckBox;
priceTagsCheckBox->setChecked(settingsCache->getPriceTagFeature());
connect(priceTagsCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPriceTagFeature(int)));
QGridLayout *generalGrid = new QGridLayout;
generalGrid->addWidget(priceTagsCheckBox, 0, 0);
generalGroupBox = new QGroupBox;
generalGroupBox->setLayout(generalGrid);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(generalGroupBox);
setLayout(mainLayout);
}
void DeckEditorSettingsPage::retranslateUi()
{
priceTagsCheckBox->setText(tr("Enable &price tag feature (using data from blacklotusproject.com)"));
generalGroupBox->setTitle(tr("General"));
}
MessagesSettingsPage::MessagesSettingsPage()
@ -490,6 +568,7 @@ DlgSettings::DlgSettings(QWidget *parent)
pagesWidget->addWidget(new GeneralSettingsPage);
pagesWidget->addWidget(new AppearanceSettingsPage);
pagesWidget->addWidget(new UserInterfaceSettingsPage);
pagesWidget->addWidget(new DeckEditorSettingsPage);
pagesWidget->addWidget(new MessagesSettingsPage);
closeButton = new QPushButton;
@ -534,6 +613,11 @@ void DlgSettings::createIcons()
userInterfaceButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
userInterfaceButton->setIcon(QIcon(":/resources/icon_config_interface.svg"));
deckEditorButton = new QListWidgetItem(contentsWidget);
deckEditorButton->setTextAlignment(Qt::AlignHCenter);
deckEditorButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
deckEditorButton->setIcon(QIcon(":/resources/icon_config_deckeditor.svg"));
messagesButton = new QListWidgetItem(contentsWidget);
messagesButton->setTextAlignment(Qt::AlignHCenter);
messagesButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
@ -590,6 +674,7 @@ void DlgSettings::retranslateUi()
generalButton->setText(tr("General"));
appearanceButton->setText(tr("Appearance"));
userInterfaceButton->setText(tr("User interface"));
deckEditorButton->setText(tr("Deck editor"));
messagesButton->setText(tr("Messages"));
closeButton->setText(tr("&Close"));

View file

@ -14,6 +14,7 @@ class QGroupBox;
class QCheckBox;
class QLabel;
class QCloseEvent;
class QSpinBox;
class AbstractSettingsPage : public QWidget {
public:
@ -65,10 +66,11 @@ signals:
void playerAreaBgChanged(const QString &path);
void cardBackPicturePathChanged(const QString &path);
private:
QLabel *handBgLabel, *stackBgLabel, *tableBgLabel, *playerAreaBgLabel, *cardBackPicturePathLabel;
QLabel *handBgLabel, *stackBgLabel, *tableBgLabel, *playerAreaBgLabel, *cardBackPicturePathLabel, *minPlayersForMultiColumnLayoutLabel;
QLineEdit *handBgEdit, *stackBgEdit, *tableBgEdit, *playerAreaBgEdit, *cardBackPicturePathEdit;
QCheckBox *displayCardNamesCheckBox, *horizontalHandCheckBox, *invertVerticalCoordinateCheckBox, *zoneViewSortByNameCheckBox, *zoneViewSortByTypeCheckBox;
QGroupBox *zoneBgGroupBox, *cardsGroupBox, *handGroupBox, *tableGroupBox, *zoneViewGroupBox;
QSpinBox *minPlayersForMultiColumnLayoutEdit;
public:
AppearanceSettingsPage();
void retranslateUi();
@ -76,15 +78,33 @@ public:
class UserInterfaceSettingsPage : public AbstractSettingsPage {
Q_OBJECT
private slots:
void soundPathClearButtonClicked();
void soundPathButtonClicked();
signals:
void soundPathChanged();
private:
QCheckBox *doubleClickToPlayCheckBox;
QCheckBox *tapAnimationCheckBox;
QGroupBox *generalGroupBox, *animationGroupBox;
QCheckBox *soundEnabledCheckBox;
QLabel *soundPathLabel;
QLineEdit *soundPathEdit;
QGroupBox *generalGroupBox, *animationGroupBox, *soundGroupBox;
public:
UserInterfaceSettingsPage();
void retranslateUi();
};
class DeckEditorSettingsPage : public AbstractSettingsPage {
Q_OBJECT
public:
DeckEditorSettingsPage();
void retranslateUi();
private:
QCheckBox *priceTagsCheckBox;
QGroupBox *generalGroupBox;
};
class MessagesSettingsPage : public AbstractSettingsPage {
Q_OBJECT
public:
@ -110,7 +130,7 @@ private slots:
private:
QListWidget *contentsWidget;
QStackedWidget *pagesWidget;
QListWidgetItem *generalButton, *appearanceButton, *userInterfaceButton, *messagesButton;
QListWidgetItem *generalButton, *appearanceButton, *userInterfaceButton, *deckEditorButton, *messagesButton;
QPushButton *closeButton;
void createIcons();
void retranslateUi();

View file

@ -3,6 +3,8 @@
#include "zoneviewwidget.h"
#include "zoneviewzone.h"
#include "phasestoolbar.h"
#include "settingscache.h"
#include <math.h>
#include <QAction>
#include <QGraphicsSceneMouseEvent>
#include <QSet>
@ -13,6 +15,7 @@ GameScene::GameScene(PhasesToolbar *_phasesToolbar, QObject *parent)
{
animationTimer = new QBasicTimer;
addItem(phasesToolbar);
connect(settingsCache, SIGNAL(minPlayersForMultiColumnLayoutChanged()), this, SLOT(rearrange()));
}
GameScene::~GameScene()
@ -31,7 +34,6 @@ void GameScene::addPlayer(Player *player)
qDebug("GameScene::addPlayer");
players << player;
addItem(player);
rearrange();
connect(player, SIGNAL(sizeChanged()), this, SLOT(rearrange()));
connect(player, SIGNAL(gameConceded()), this, SLOT(rearrange()));
}
@ -46,44 +48,63 @@ void GameScene::removePlayer(Player *player)
void GameScene::rearrange()
{
struct PlayerProcessor {
static void processPlayer(Player *p, qreal &w, QPointF &b, bool singlePlayer)
{
if (p->getConceded())
return;
const QRectF br = p->boundingRect();
if (br.width() > w)
w = br.width();
p->setPos(b);
p->setMirrored((b.y() < playerAreaSpacing) && !singlePlayer);
b += QPointF(0, br.height() + playerAreaSpacing);
}
};
qreal sceneHeight = -playerAreaSpacing;
playersByColumn.clear();
QList<Player *> playersPlaying;
int firstPlayer = -1;
for (int i = 0; i < players.size(); ++i)
if (!players[i]->getConceded())
sceneHeight += players[i]->boundingRect().height() + playerAreaSpacing;
if (!players[i]->getConceded()) {
playersPlaying.append(players[i]);
if ((firstPlayer == -1) && (players[i]->getLocal()))
firstPlayer = playersPlaying.size() - 1;
}
if (firstPlayer == -1)
firstPlayer = 0;
const int playersCount = playersPlaying.size();
const int columns = playersCount < settingsCache->getMinPlayersForMultiColumnLayout() ? 1 : 2;
const int rows = ceil((qreal) playersCount / columns);
qreal sceneHeight = 0, sceneWidth = -playerAreaSpacing;
QList<int> columnWidth;
int firstPlayerOfColumn = firstPlayer;
for (int col = 0; col < columns; ++col) {
playersByColumn.append(QList<Player *>());
columnWidth.append(0);
qreal thisColumnHeight = -playerAreaSpacing;
const int rowsInColumn = rows - (playersCount % columns);
for (int j = 0; j < rowsInColumn; ++j) {
Player *player = playersPlaying[(firstPlayerOfColumn + j) % playersCount];
if (col == 0)
playersByColumn[col].prepend(player);
else
playersByColumn[col].append(player);
thisColumnHeight += player->boundingRect().height() + playerAreaSpacing;
if (player->boundingRect().width() > columnWidth[col])
columnWidth[col] = player->boundingRect().width();
}
if (thisColumnHeight > sceneHeight)
sceneHeight = thisColumnHeight;
sceneWidth += columnWidth[col] + playerAreaSpacing;
firstPlayerOfColumn += rowsInColumn;
}
phasesToolbar->setHeight(sceneHeight);
qreal phasesWidth = phasesToolbar->getWidth();
QPointF base(phasesWidth, 0);
qreal sceneWidth;
QList<Player *> localPlayers;
for (int i = 0; i < players.size(); ++i)
if (!players[i]->getLocal())
PlayerProcessor::processPlayer(players[i], sceneWidth, base, players.size() == 1);
else
localPlayers.append(players[i]);
for (int i = 0; i < localPlayers.size(); ++i)
PlayerProcessor::processPlayer(localPlayers[i], sceneWidth, base, players.size() == 1);
sceneWidth += phasesWidth;
playersRect = QRectF(0, 0, sceneWidth, sceneHeight);
qreal x = phasesWidth;
for (int col = 0; col < columns; ++col) {
qreal y = 0;
for (int row = 0; row < playersByColumn[col].size(); ++row) {
Player *player = playersByColumn[col][row];
player->setPos(x, y);
player->setMirrored(row != rows - 1);
y += player->boundingRect().height() + playerAreaSpacing;
}
x += columnWidth[col] + playerAreaSpacing;
}
setSceneRect(sceneRect().x(), sceneRect().y(), sceneWidth, sceneHeight);
processViewSizeChange(viewSize);
}
@ -139,24 +160,33 @@ void GameScene::processViewSizeChange(const QSize &newSize)
qreal newRatio = ((qreal) newSize.width()) / newSize.height();
qreal minWidth = 0;
for (int i = 0; i < players.size(); ++i) {
qreal w = players[i]->getMinimumWidth();
if (w > minWidth)
minWidth = w;
QList<qreal> minWidthByColumn;
for (int col = 0; col < playersByColumn.size(); ++col) {
minWidthByColumn.append(0);
for (int row = 0; row < playersByColumn[col].size(); ++row) {
qreal w = playersByColumn[col][row]->getMinimumWidth();
if (w > minWidthByColumn[col])
minWidthByColumn[col] = w;
}
minWidth += minWidthByColumn[col];
}
minWidth += phasesToolbar->getWidth();
qreal minRatio = minWidth / sceneRect().height();
qreal newWidth;
if (minRatio > newRatio) {
// Aspect ratio is dominated by table width.
setSceneRect(0, 0, minWidth, sceneRect().height());
newWidth = minWidth;
} else {
// Aspect ratio is dominated by window dimensions.
setSceneRect(0, 0, newRatio * sceneRect().height(), sceneRect().height());
newWidth = newRatio * sceneRect().height();
}
for (int i = 0; i < players.size(); ++i)
players[i]->processSceneSizeChange(sceneRect().size() - QSizeF(phasesToolbar->getWidth(), 0));
setSceneRect(0, 0, newWidth, sceneRect().height());
qreal extraWidthPerColumn = (newWidth - minWidth) / playersByColumn.size();
for (int col = 0; col < playersByColumn.size(); ++col)
for (int row = 0; row < playersByColumn[col].size(); ++row)
playersByColumn[col][row]->processSceneSizeChange(minWidthByColumn[col] + extraWidthPerColumn);
}
void GameScene::updateHover(const QPointF &scenePos)

View file

@ -22,7 +22,7 @@ private:
PhasesToolbar *phasesToolbar;
QList<Player *> players;
QRectF playersRect;
QList<QList<Player *> > playersByColumn;
QList<ZoneViewWidget *> views;
QSize viewSize;
QPointer<CardItem> hoveredCard;
@ -33,7 +33,6 @@ public:
GameScene(PhasesToolbar *_phasesToolbar, QObject *parent = 0);
~GameScene();
void retranslateUi();
const QRectF &getPlayersRect() const { return playersRect; }
void processViewSizeChange(const QSize &newSize);
void startRubberBand(const QPointF &selectionOrigin);

View file

@ -0,0 +1,150 @@
#include <QTreeView>
#include <QCheckBox>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QHeaderView>
#include <QInputDialog>
#include "dlg_creategame.h"
#include "abstractclient.h"
#include "protocol_items.h"
#include "gameselector.h"
#include "gamesmodel.h"
GameSelector::GameSelector(AbstractClient *_client, TabRoom *_room, const QMap<int, QString> &_rooms, const QMap<int, GameTypeMap> &_gameTypes, QWidget *parent)
: QGroupBox(parent), client(_client), room(_room)
{
gameListView = new QTreeView;
gameListModel = new GamesModel(_rooms, _gameTypes, this);
gameListProxyModel = new GamesProxyModel(this);
gameListProxyModel->setSourceModel(gameListModel);
gameListProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
gameListView->setModel(gameListProxyModel);
gameListView->setSortingEnabled(true);
gameListView->setAlternatingRowColors(true);
if (_room)
gameListView->header()->hideSection(0);
gameListView->header()->setResizeMode(1, QHeaderView::ResizeToContents);
showFullGamesCheckBox = new QCheckBox;
showRunningGamesCheckBox = new QCheckBox;
QVBoxLayout *filterLayout = new QVBoxLayout;
filterLayout->addWidget(showFullGamesCheckBox);
filterLayout->addWidget(showRunningGamesCheckBox);
if (room)
createButton = new QPushButton;
else
createButton = 0;
joinButton = new QPushButton;
spectateButton = new QPushButton;
QHBoxLayout *buttonLayout = new QHBoxLayout;
if (room)
buttonLayout->addWidget(createButton);
buttonLayout->addWidget(joinButton);
buttonLayout->addWidget(spectateButton);
buttonLayout->setAlignment(Qt::AlignTop);
QHBoxLayout *hbox = new QHBoxLayout;
hbox->addLayout(filterLayout);
hbox->addStretch();
hbox->addLayout(buttonLayout);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(gameListView);
mainLayout->addLayout(hbox);
retranslateUi();
setLayout(mainLayout);
setMinimumWidth((qreal) (gameListView->columnWidth(0) * gameListModel->columnCount()) / 1.5);
setMinimumHeight(200);
connect(showFullGamesCheckBox, SIGNAL(stateChanged(int)), this, SLOT(showFullGamesChanged(int)));
connect(showRunningGamesCheckBox, SIGNAL(stateChanged(int)), this, SLOT(showRunningGamesChanged(int)));
connect(createButton, SIGNAL(clicked()), this, SLOT(actCreate()));
connect(joinButton, SIGNAL(clicked()), this, SLOT(actJoin()));
connect(spectateButton, SIGNAL(clicked()), this, SLOT(actJoin()));
}
void GameSelector::showFullGamesChanged(int state)
{
gameListProxyModel->setFullGamesVisible(state);
}
void GameSelector::showRunningGamesChanged(int state)
{
gameListProxyModel->setRunningGamesVisible(state);
}
void GameSelector::actCreate()
{
DlgCreateGame dlg(client, room->getRoomId(), room->getGameTypes(), this);
dlg.exec();
}
void GameSelector::checkResponse(ResponseCode response)
{
if (createButton)
createButton->setEnabled(true);
joinButton->setEnabled(true);
spectateButton->setEnabled(true);
switch (response) {
case RespNotInRoom: QMessageBox::critical(this, tr("Error"), tr("Please join the appropriate room first.")); break;
case RespWrongPassword: QMessageBox::critical(this, tr("Error"), tr("Wrong password.")); break;
case RespSpectatorsNotAllowed: QMessageBox::critical(this, tr("Error"), tr("Spectators are not allowed in this game.")); break;
case RespGameFull: QMessageBox::critical(this, tr("Error"), tr("The game is already full.")); break;
case RespNameNotFound: QMessageBox::critical(this, tr("Error"), tr("The game does not exist any more.")); break;
case RespUserLevelTooLow: QMessageBox::critical(this, tr("Error"), tr("This game is only open to registered users.")); break;
case RespOnlyBuddies: QMessageBox::critical(this, tr("Error"), tr("This game is only open to its creator's buddies.")); break;
case RespInIgnoreList: QMessageBox::critical(this, tr("Error"), tr("You are being ignored by the creator of this game.")); break;
default: ;
}
}
void GameSelector::actJoin()
{
bool spectator = sender() == spectateButton;
QModelIndex ind = gameListView->currentIndex();
if (!ind.isValid())
return;
ServerInfo_Game *game = gameListModel->getGame(ind.data(Qt::UserRole).toInt());
QString password;
if (game->getHasPassword() && !(spectator && !game->getSpectatorsNeedPassword())) {
bool ok;
password = QInputDialog::getText(this, tr("Join game"), tr("Password:"), QLineEdit::Password, QString(), &ok);
if (!ok)
return;
}
Command_JoinGame *commandJoinGame = new Command_JoinGame(game->getRoomId(), game->getGameId(), password, spectator);
connect(commandJoinGame, SIGNAL(finished(ResponseCode)), this, SLOT(checkResponse(ResponseCode)));
client->sendCommand(commandJoinGame);
if (createButton)
createButton->setEnabled(false);
joinButton->setEnabled(false);
spectateButton->setEnabled(false);
}
void GameSelector::retranslateUi()
{
setTitle(tr("Games"));
showFullGamesCheckBox->setText(tr("Show &full games"));
showRunningGamesCheckBox->setText(tr("Show &running games"));
if (createButton)
createButton->setText(tr("C&reate"));
joinButton->setText(tr("&Join"));
spectateButton->setText(tr("J&oin as spectator"));
}
void GameSelector::processGameInfo(ServerInfo_Game *info)
{
gameListModel->updateGameList(info);
}

View file

@ -0,0 +1,42 @@
#ifndef GAMESELECTOR_H
#define GAMESELECTOR_H
#include <QGroupBox>
#include "protocol_datastructures.h"
#include "tab_room.h"
#include "gametypemap.h"
class QTreeView;
class GamesModel;
class GamesProxyModel;
class QPushButton;
class QCheckBox;
class AbstractClient;
class TabRoom;
class GameSelector : public QGroupBox {
Q_OBJECT
private slots:
void showFullGamesChanged(int state);
void showRunningGamesChanged(int state);
void actCreate();
void actJoin();
void checkResponse(ResponseCode response);
signals:
void gameJoined(int gameId);
private:
AbstractClient *client;
TabRoom *room;
QTreeView *gameListView;
GamesModel *gameListModel;
GamesProxyModel *gameListProxyModel;
QPushButton *createButton, *joinButton, *spectateButton;
QCheckBox *showFullGamesCheckBox, *showRunningGamesCheckBox;
public:
GameSelector(AbstractClient *_client, TabRoom *_room, const QMap<int, QString> &_rooms, const QMap<int, GameTypeMap> &_gameTypes, QWidget *parent = 0);
void retranslateUi();
void processGameInfo(ServerInfo_Game *info);
};
#endif

View file

@ -1,8 +1,8 @@
#include "gamesmodel.h"
#include "protocol_datastructures.h"
GamesModel::GamesModel(const QMap<int, QString> &_gameTypes, QObject *parent)
: QAbstractTableModel(parent), gameTypes(_gameTypes)
GamesModel::GamesModel(const QMap<int, QString> &_rooms, const QMap<int, GameTypeMap> &_gameTypes, QObject *parent)
: QAbstractTableModel(parent), rooms(_rooms), gameTypes(_gameTypes)
{
}
@ -30,17 +30,19 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const
ServerInfo_Game *g = gameList[index.row()];
switch (index.column()) {
case 0: return g->getDescription();
case 1: return g->getCreatorInfo()->getName();
case 2: {
case 0: return rooms.value(g->getRoomId());
case 1: return g->getDescription();
case 2: return g->getCreatorInfo()->getName();
case 3: {
QStringList result;
QList<GameTypeId *> gameTypeList = g->getGameTypes();
GameTypeMap gameTypeMap = gameTypes.value(g->getRoomId());
for (int i = 0; i < gameTypeList.size(); ++i)
result.append(gameTypes.value(gameTypeList[i]->getData()));
result.append(gameTypeMap.value(gameTypeList[i]->getData()));
return result.join(", ");
}
case 3: return g->getHasPassword() ? (g->getSpectatorsNeedPassword() ? tr("yes") : tr("yes, free for spectators")) : tr("no");
case 4: {
case 4: return g->getHasPassword() ? (g->getSpectatorsNeedPassword() ? tr("yes") : tr("yes, free for spectators")) : tr("no");
case 5: {
QStringList result;
if (g->getOnlyBuddies())
result.append(tr("buddies only"));
@ -48,8 +50,8 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const
result.append(tr("reg. users only"));
return result.join(", ");
}
case 5: return QString("%1/%2").arg(g->getPlayerCount()).arg(g->getMaxPlayers());
case 6: return g->getSpectatorsAllowed() ? QVariant(g->getSpectatorCount()) : QVariant(tr("not allowed"));
case 6: return QString("%1/%2").arg(g->getPlayerCount()).arg(g->getMaxPlayers());
case 7: return g->getSpectatorsAllowed() ? QVariant(g->getSpectatorCount()) : QVariant(tr("not allowed"));
default: return QVariant();
}
}
@ -59,13 +61,14 @@ QVariant GamesModel::headerData(int section, Qt::Orientation orientation, int ro
if ((role != Qt::DisplayRole) || (orientation != Qt::Horizontal))
return QVariant();
switch (section) {
case 0: return tr("Description");
case 1: return tr("Creator");
case 2: return tr("Game type");
case 3: return tr("Password");
case 4: return tr("Restrictions");
case 5: return tr("Players");
case 6: return tr("Spectators");
case 0: return tr("Room");
case 1: return tr("Description");
case 2: return tr("Creator");
case 3: return tr("Game type");
case 4: return tr("Password");
case 5: return tr("Restrictions");
case 6: return tr("Players");
case 7: return tr("Spectators");
default: return QVariant();
}
}
@ -82,7 +85,7 @@ void GamesModel::updateGameList(ServerInfo_Game *_game)
for (int i = 0; i < oldGameTypeList.size(); ++i)
gameTypeList.append(new GameTypeId(oldGameTypeList[i]->getData()));
ServerInfo_Game *game = new ServerInfo_Game(_game->getGameId(), _game->getDescription(), _game->getHasPassword(), _game->getPlayerCount(), _game->getMaxPlayers(), gameTypeList, new ServerInfo_User(_game->getCreatorInfo()), _game->getOnlyBuddies(), _game->getOnlyRegistered(), _game->getSpectatorsAllowed(), _game->getSpectatorsNeedPassword(), _game->getSpectatorCount());
ServerInfo_Game *game = new ServerInfo_Game(_game->getRoomId(), _game->getGameId(), _game->getDescription(), _game->getHasPassword(), _game->getPlayerCount(), _game->getMaxPlayers(), _game->getStarted(), gameTypeList, new ServerInfo_User(_game->getCreatorInfo()), _game->getOnlyBuddies(), _game->getOnlyRegistered(), _game->getSpectatorsAllowed(), _game->getSpectatorsNeedPassword(), _game->getSpectatorCount());
for (int i = 0; i < gameList.size(); i++)
if (gameList[i]->getGameId() == game->getGameId()) {
if (game->getPlayerCount() == 0) {
@ -92,7 +95,7 @@ void GamesModel::updateGameList(ServerInfo_Game *_game)
} else {
delete gameList[i];
gameList[i] = game;
emit dataChanged(index(i, 0), index(i, 4));
emit dataChanged(index(i, 0), index(i, 7));
}
return;
}
@ -115,17 +118,22 @@ void GamesProxyModel::setFullGamesVisible(bool _fullGamesVisible)
invalidateFilter();
}
void GamesProxyModel::setRunningGamesVisible(bool _runningGamesVisible)
{
runningGamesVisible = _runningGamesVisible;
invalidateFilter();
}
bool GamesProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &/*sourceParent*/) const
{
if (fullGamesVisible)
return true;
GamesModel *model = qobject_cast<GamesModel *>(sourceModel());
if (!model)
return false;
ServerInfo_Game *game = model->getGame(sourceRow);
if (game->getPlayerCount() == game->getMaxPlayers())
if ((game->getPlayerCount() == game->getMaxPlayers()) && !fullGamesVisible)
return false;
if (game->getStarted() && !runningGamesVisible)
return false;
return true;

View file

@ -4,6 +4,7 @@
#include <QAbstractTableModel>
#include <QSortFilterProxyModel>
#include <QList>
#include "gametypemap.h"
class ServerInfo_Game;
@ -11,12 +12,13 @@ class GamesModel : public QAbstractTableModel {
Q_OBJECT
private:
QList<ServerInfo_Game *> gameList;
QMap<int, QString> gameTypes;
QMap<int, QString> rooms;
QMap<int, GameTypeMap> gameTypes;
public:
GamesModel(const QMap<int, QString> &_gameTypes, QObject *parent = 0);
GamesModel(const QMap<int, QString> &_rooms, const QMap<int, GameTypeMap> &_gameTypes, QObject *parent = 0);
~GamesModel();
int rowCount(const QModelIndex &parent = QModelIndex()) const { return parent.isValid() ? 0 : gameList.size(); }
int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const { return 7; }
int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const { return 8; }
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
@ -28,9 +30,11 @@ class GamesProxyModel : public QSortFilterProxyModel {
Q_OBJECT
private:
bool fullGamesVisible;
bool runningGamesVisible;
public:
GamesProxyModel(QObject *parent = 0);
void setFullGamesVisible(bool _fullGamesVisible);
void setRunningGamesVisible(bool _runningGamesVisible);
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
};

View file

@ -0,0 +1,8 @@
#ifndef GAMETYPEMAP_H
#define GAMETYPEMAP_H
#include <QMap>
typedef QMap<int, QString> GameTypeMap;
#endif

View file

@ -10,6 +10,7 @@ LocalServer::LocalServer(QObject *parent)
LocalServer::~LocalServer()
{
prepareDestroy();
}
LocalServerInterface *LocalServer::newConnection()

View file

@ -11,11 +11,12 @@ class LocalServer : public Server
public:
LocalServer(QObject *parent = 0);
~LocalServer();
AuthenticationResult checkUserPassword(const QString & /*user*/, const QString & /*password*/) { return UnknownUser; }
AuthenticationResult checkUserPassword(Server_ProtocolHandler * /*handler*/, const QString & /*user*/, const QString & /*password*/) { return UnknownUser; }
QString getLoginMessage() const { return QString(); }
bool getGameShouldPing() const { return false; }
int getMaxGameInactivityTime() const { return 9999999; }
int getMaxPlayerInactivityTime() const { return 9999999; }
bool getThreaded() const { return false; }
LocalServerInterface *newConnection();
protected:

View file

@ -9,6 +9,7 @@ LocalServerInterface::LocalServerInterface(LocalServer *_server)
LocalServerInterface::~LocalServerInterface()
{
prepareDestroy();
}
void LocalServerInterface::sendProtocolItem(ProtocolItem *item, bool deleteItem)

View file

@ -18,14 +18,16 @@ private:
ResponseCode cmdDeckDel(Command_DeckDel * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; }
ResponseCode cmdDeckUpload(Command_DeckUpload * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; }
ResponseCode cmdDeckDownload(Command_DeckDownload * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; }
ResponseCode cmdUpdateServerMessage(Command_UpdateServerMessage * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; }
ResponseCode cmdBanFromServer(Command_BanFromServer * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; }
ResponseCode cmdShutdownServer(Command_ShutdownServer * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; }
ResponseCode cmdUpdateServerMessage(Command_UpdateServerMessage * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; }
protected:
bool getCompressionSupport() const { return false; }
public:
LocalServerInterface(LocalServer *_server);
~LocalServerInterface();
void sendProtocolItem(ProtocolItem *item, bool deleteItem = true);
signals:
void itemToClient(ProtocolItem *item);
public slots:

View file

@ -36,6 +36,7 @@
#include "settingscache.h"
#include "pixmapgenerator.h"
#include "rng_sfmt.h"
#include "soundengine.h"
//Q_IMPORT_PLUGIN(qjpeg)
@ -43,6 +44,7 @@ CardDatabase *db;
QTranslator *translator, *qtTranslator;
SettingsCache *settingsCache;
RNG_Abstract *rng;
SoundEngine *soundEngine;
void myMessageOutput(QtMsgType /*type*/, const char *msg)
{
@ -114,6 +116,8 @@ int main(int argc, char *argv[])
}
if (startMainProgram) {
soundEngine = new SoundEngine;
MainWindow ui;
qDebug("main(): MainWindow constructor finished");

View file

@ -3,12 +3,13 @@
class CardDatabase;
class QTranslator;
class SoundEngine;
extern CardDatabase *db;
extern QTranslator *translator;
const QString translationPrefix = "cockatrice";
const QString versionString = "0.20110303";
const QString versionString = "0.20110625";
void installNewTranslator();

View file

@ -1,11 +1,9 @@
#include "messagelogwidget.h"
#include "player.h"
#include "cardzone.h"
#include "cardinfowidget.h"
#include "protocol_items.h"
#include <QDebug>
#include <QMouseEvent>
#include <QTextBlock>
#include "soundengine.h"
#include <QScrollBar>
QString MessageLogWidget::sanitizeHtml(QString dirty) const
{
@ -15,133 +13,158 @@ QString MessageLogWidget::sanitizeHtml(QString dirty) const
.replace(">", "&gt;");
}
void MessageLogWidget::logConnecting(QString hostname)
bool MessageLogWidget::isFemale(Player *player) const
{
append(tr("Connecting to %1...").arg(sanitizeHtml(hostname)));
}
void MessageLogWidget::logConnected()
{
append(tr("Connected."));
}
void MessageLogWidget::logDisconnected()
{
append(tr("Disconnected from server."));
}
void MessageLogWidget::logSocketError(const QString &errorString)
{
append(sanitizeHtml(errorString));
}
void MessageLogWidget::logServerError(ResponseCode response)
{
switch (response) {
case RespWrongPassword: append(tr("Invalid password.")); break;
default: ;
}
}
void MessageLogWidget::logProtocolVersionMismatch(int clientVersion, int serverVersion)
{
append(tr("Protocol version mismatch. Client: %1, Server: %2").arg(clientVersion).arg(serverVersion));
}
void MessageLogWidget::logProtocolError()
{
append(tr("Protocol error."));
return player->getUserInfo()->getGender() == ServerInfo_User::Female;
}
void MessageLogWidget::logGameJoined(int gameId)
{
append(tr("You have joined game #%1.").arg(gameId));
if (female)
appendHtml(tr("You have joined game #%1.", "female").arg(gameId));
else
appendHtml(tr("You have joined game #%1.", "male").arg(gameId));
}
void MessageLogWidget::logJoin(Player *player)
{
append(tr("%1 has joined the game.").arg(sanitizeHtml(player->getName())));
soundEngine->cuckoo();
if (isFemale(player))
appendHtml(tr("%1 has joined the game.", "female").arg(sanitizeHtml(player->getName())));
else
appendHtml(tr("%1 has joined the game.", "male").arg(sanitizeHtml(player->getName())));
}
void MessageLogWidget::logLeave(Player *player)
{
append(tr("%1 has left the game.").arg(sanitizeHtml(player->getName())));
if (isFemale(player))
appendHtml(tr("%1 has left the game.", "female").arg(sanitizeHtml(player->getName())));
else
appendHtml(tr("%1 has left the game.", "male").arg(sanitizeHtml(player->getName())));
}
void MessageLogWidget::logGameClosed()
{
append(tr("The game has been closed."));
appendHtml(tr("The game has been closed."));
}
void MessageLogWidget::logJoinSpectator(QString name)
{
append(tr("%1 is now watching the game.").arg(sanitizeHtml(name)));
appendHtml(tr("%1 is now watching the game.").arg(sanitizeHtml(name)));
}
void MessageLogWidget::logLeaveSpectator(QString name)
{
append(tr("%1 is not watching the game any more.").arg(sanitizeHtml(name)));
appendHtml(tr("%1 is not watching the game any more.").arg(sanitizeHtml(name)));
}
void MessageLogWidget::logDeckSelect(Player *player, int deckId)
{
if (deckId == -1)
append(tr("%1 has loaded a local deck.").arg(sanitizeHtml(player->getName())));
else
append(tr("%1 has loaded deck #%2.").arg(sanitizeHtml(player->getName())).arg(deckId));
if (deckId == -1) {
if (isFemale(player))
appendHtml(tr("%1 has loaded a local deck.", "female").arg(sanitizeHtml(player->getName())));
else
appendHtml(tr("%1 has loaded a local deck.", "male").arg(sanitizeHtml(player->getName())));
} else {
if (isFemale(player))
appendHtml(tr("%1 has loaded deck #%2.", "female").arg(sanitizeHtml(player->getName())).arg(deckId));
else
appendHtml(tr("%1 has loaded deck #%2.", "male").arg(sanitizeHtml(player->getName())).arg(deckId));
}
}
void MessageLogWidget::logReadyStart(Player *player)
{
append(tr("%1 is ready to start the game.").arg(sanitizeHtml(player->getName())));
if (isFemale(player))
appendHtml(tr("%1 is ready to start the game.", "female").arg(sanitizeHtml(player->getName())));
else
appendHtml(tr("%1 is ready to start the game.", "male").arg(sanitizeHtml(player->getName())));
}
void MessageLogWidget::logNotReadyStart(Player *player)
{
append(tr("%1 is not ready to start the game any more.").arg(sanitizeHtml(player->getName())));
if (isFemale(player))
appendHtml(tr("%1 is not ready to start the game any more.", "female").arg(sanitizeHtml(player->getName())));
else
appendHtml(tr("%1 is not ready to start the game any more.", "male").arg(sanitizeHtml(player->getName())));
}
void MessageLogWidget::logConcede(Player *player)
{
append(tr("%1 has conceded the game.").arg(sanitizeHtml(player->getName())));
if (isFemale(player))
appendHtml(tr("%1 has conceded the game.", "female").arg(sanitizeHtml(player->getName())));
else
appendHtml(tr("%1 has conceded the game.", "male").arg(sanitizeHtml(player->getName())));
}
void MessageLogWidget::logGameStart()
{
append(tr("The game has started."));
appendHtml(tr("The game has started."));
}
void MessageLogWidget::logConnectionStateChanged(Player *player, bool connectionState)
{
if (connectionState) {
if (isFemale(player))
appendHtml(tr("%1 has restored connection to the game.", "female").arg(sanitizeHtml(player->getName())));
else
appendHtml(tr("%1 has restored connection to the game.", "male").arg(sanitizeHtml(player->getName())));
} else {
if (isFemale(player))
appendHtml(tr("%1 has lost connection to the game.", "female").arg(sanitizeHtml(player->getName())));
else
appendHtml(tr("%1 has lost connection to the game.", "male").arg(sanitizeHtml(player->getName())));
}
}
void MessageLogWidget::logSay(Player *player, QString message)
{
append(QString("<b><font color=\"") + (player->getLocal() ? "red" : "#0000fe") + QString("\">%1:</font></b> %2").arg(sanitizeHtml(player->getName())).arg(sanitizeHtml(message)));
appendMessage(player->getName(), message, QColor(), true);
}
void MessageLogWidget::logSpectatorSay(QString spectatorName, QString message)
{
append(QString("<font color=\"red\">%1:</font> %2").arg(sanitizeHtml(spectatorName)).arg(sanitizeHtml(message)));
appendMessage(spectatorName, message, QColor(), false);
}
void MessageLogWidget::logShuffle(Player *player)
void MessageLogWidget::logShuffle(Player *player, CardZone *zone)
{
append(tr("%1 shuffles his library.").arg(sanitizeHtml(player->getName())));
soundEngine->shuffle();
if (currentContext != MessageContext_Mulligan) {
if (isFemale(player))
appendHtml(tr("%1 shuffles %2.", "female").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative)));
else
appendHtml(tr("%1 shuffles %2.", "male").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative)));
}
}
void MessageLogWidget::logRollDie(Player *player, int sides, int roll)
{
append(tr("%1 rolls a %2 with a %3-sided die.").arg(sanitizeHtml(player->getName())).arg(roll).arg(sides));
if (isFemale(player))
appendHtml(tr("%1 rolls a %2 with a %3-sided die.", "female").arg(sanitizeHtml(player->getName())).arg(roll).arg(sides));
else
appendHtml(tr("%1 rolls a %2 with a %3-sided die.", "male").arg(sanitizeHtml(player->getName())).arg(roll).arg(sides));
}
void MessageLogWidget::logDrawCards(Player *player, int number)
{
append(tr("%1 draws %n card(s).", "", number).arg(sanitizeHtml(player->getName())));
if (currentContext == MessageContext_Mulligan)
mulliganPlayer = player;
else {
soundEngine->draw();
if (isFemale(player))
appendHtml(tr("%1 draws %n card(s).", "female", number).arg(sanitizeHtml(player->getName())));
else
appendHtml(tr("%1 draws %n card(s).", "male", number).arg(sanitizeHtml(player->getName())));
}
}
void MessageLogWidget::logUndoDraw(Player *player, QString cardName)
{
if (cardName.isEmpty())
append(tr("%1 undoes his last draw.").arg(sanitizeHtml(player->getName())));
appendHtml((isFemale(player) ? tr("%1 undoes her last draw.") : tr("%1 undoes his last draw.")).arg(sanitizeHtml(player->getName())));
else
append(tr("%1 undoes his last draw (%2).").arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName))));
appendHtml((isFemale(player) ? tr("%1 undoes her last draw (%2).") : tr("%1 undoes his last draw (%2).")).arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName))));
}
QPair<QString, QString> MessageLogWidget::getFromStr(CardZone *zone, QString cardName, int position) const
@ -161,16 +184,16 @@ QPair<QString, QString> MessageLogWidget::getFromStr(CardZone *zone, QString car
else if (startName == "deck") {
if (position == zone->getCards().size() - 1) {
if (cardName.isEmpty()) {
cardName = tr("the bottom card of his library");
cardName = isFemale(zone->getPlayer()) ? tr("the bottom card of her library") : tr("the bottom card of his library");
cardNameContainsStartZone = true;
} else
fromStr = tr(" from the bottom of his library");
fromStr = isFemale(zone->getPlayer()) ? tr(" from the bottom of her library") : tr(" from the bottom of his library");
} else if (position == 0) {
if (cardName.isEmpty()) {
cardName = tr("the top card of his library");
cardName = isFemale(zone->getPlayer()) ? tr("the top card of her library") : tr("the top card of his library");
cardNameContainsStartZone = true;
} else
fromStr = tr(" from the top of his library");
fromStr = isFemale(zone->getPlayer()) ? tr(" from the top of her library") : tr(" from the top of his library");
} else
fromStr = tr(" from library");
} else if (startName == "sb")
@ -206,12 +229,13 @@ void MessageLogWidget::doMoveCard(LogMoveCard &attributes)
cardStr = QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName));
if (attributes.startZone->getPlayer() != attributes.targetZone->getPlayer()) {
append(tr("%1 gives %2 control over %3.").arg(sanitizeHtml(attributes.player->getName())).arg(sanitizeHtml(attributes.targetZone->getPlayer()->getName())).arg(cardStr));
appendHtml(tr("%1 gives %2 control over %3.").arg(sanitizeHtml(attributes.player->getName())).arg(sanitizeHtml(attributes.targetZone->getPlayer()->getName())).arg(cardStr));
return;
}
QString finalStr;
if (targetName == "table") {
soundEngine->playCard();
if (moveCardTapped.value(attributes.card))
finalStr = tr("%1 puts %2 into play tapped%3.");
else
@ -224,19 +248,21 @@ void MessageLogWidget::doMoveCard(LogMoveCard &attributes)
finalStr = tr("%1 moves %2%3 to hand.");
else if (targetName == "deck") {
if (attributes.newX == -1)
finalStr = tr("%1 puts %2%3 into his library.");
finalStr = isFemale(attributes.targetZone->getPlayer()) ? tr("%1 puts %2%3 into her library.") : tr("%1 puts %2%3 into his library.");
else if (attributes.newX == attributes.targetZone->getCards().size() - 1)
finalStr = tr("%1 puts %2%3 on bottom of his library.");
finalStr = isFemale(attributes.targetZone->getPlayer()) ? tr("%1 puts %2%3 on bottom of her library.") : tr("%1 puts %2%3 on bottom of his library.");
else if (attributes.newX == 0)
finalStr = tr("%1 puts %2%3 on top of his library.");
finalStr = isFemale(attributes.targetZone->getPlayer()) ? tr("%1 puts %2%3 on top of her library.") : tr("%1 puts %2%3 on top of his library.");
else
finalStr = tr("%1 puts %2%3 into his library at position %4.");
finalStr = isFemale(attributes.targetZone->getPlayer()) ? tr("%1 puts %2%3 into her library at position %4.") : tr("%1 puts %2%3 into his library at position %4.");
} else if (targetName == "sb")
finalStr = tr("%1 moves %2%3 to sideboard.");
else if (targetName == "stack")
else if (targetName == "stack") {
soundEngine->playCard();
finalStr = tr("%1 plays %2%3.");
}
append(finalStr.arg(sanitizeHtml(attributes.player->getName())).arg(cardStr).arg(fromStr).arg(attributes.newX));
appendHtml(finalStr.arg(sanitizeHtml(attributes.player->getName())).arg(cardStr).arg(fromStr).arg(attributes.newX));
}
void MessageLogWidget::logMoveCard(Player *player, CardItem *card, CardZone *startZone, int oldX, CardZone *targetZone, int newX)
@ -244,55 +270,211 @@ void MessageLogWidget::logMoveCard(Player *player, CardItem *card, CardZone *sta
LogMoveCard attributes = {player, card, card->getName(), startZone, oldX, targetZone, newX};
if (currentContext == MessageContext_MoveCard)
moveCardQueue.append(attributes);
else if (currentContext == MessageContext_Mulligan)
mulliganPlayer = player;
else
doMoveCard(attributes);
}
void MessageLogWidget::logMulligan(Player *player, int number)
{
if (!player)
return;
if (number > -1) {
if (isFemale(player))
appendHtml(tr("%1 takes a mulligan to %n.", "female", number).arg(sanitizeHtml(player->getName())));
else
appendHtml(tr("%1 takes a mulligan to %n.", "male", number).arg(sanitizeHtml(player->getName())));
} else
appendHtml((isFemale(player) ? tr("%1 draws her initial hand.") : tr("%1 draws his initial hand.")).arg(sanitizeHtml(player->getName())));
}
void MessageLogWidget::logFlipCard(Player *player, QString cardName, bool faceDown)
{
if (faceDown)
append(tr("%1 flips %2 face-down.").arg(sanitizeHtml(player->getName())).arg(cardName));
else
append(tr("%1 flips %2 face-up.").arg(sanitizeHtml(player->getName())).arg(cardName));
if (faceDown) {
if (isFemale(player))
appendHtml(tr("%1 flips %2 face-down.", "female").arg(sanitizeHtml(player->getName())).arg(cardName));
else
appendHtml(tr("%1 flips %2 face-down.", "male").arg(sanitizeHtml(player->getName())).arg(cardName));
} else {
if (isFemale(player))
appendHtml(tr("%1 flips %2 face-up.", "female").arg(sanitizeHtml(player->getName())).arg(cardName));
else
appendHtml(tr("%1 flips %2 face-up.", "male").arg(sanitizeHtml(player->getName())).arg(cardName));
}
}
void MessageLogWidget::logDestroyCard(Player *player, QString cardName)
{
append(tr("%1 destroys %2.").arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName))));
if (isFemale(player))
appendHtml(tr("%1 destroys %2.", "female").arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName))));
else
appendHtml(tr("%1 destroys %2.", "male").arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName))));
}
void MessageLogWidget::logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName)
{
append(tr("%1 attaches %2 to %3's %4.").arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName))).arg(sanitizeHtml(targetPlayer->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(targetCardName))));
QString str;
if (isFemale(player)) {
if (isFemale(targetPlayer))
str = tr("%1 attaches %2 to %3's %4.", "p1 female, p2 female");
else
str = tr("%1 attaches %2 to %3's %4.", "p1 female, p2 male");
} else {
if (isFemale(targetPlayer))
str = tr("%1 attaches %2 to %3's %4.", "p1 male, p2 female");
else
str = tr("%1 attaches %2 to %3's %4.", "p1 male, p2 male");
}
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName))).arg(sanitizeHtml(targetPlayer->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(targetCardName))));
}
void MessageLogWidget::logUnattachCard(Player *player, QString cardName)
{
append(tr("%1 unattaches %2.").arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName))));
if (isFemale(player))
appendHtml(tr("%1 unattaches %2.", "female").arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName))));
else
appendHtml(tr("%1 unattaches %2.", "male").arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName))));
}
void MessageLogWidget::logCreateToken(Player *player, QString cardName, QString pt)
{
append(tr("%1 creates token: %2%3.").arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\"><a name=\"foo\">%1</a></font>").arg(sanitizeHtml(cardName))).arg(pt.isEmpty() ? QString() : QString(" (%1)").arg(sanitizeHtml(pt))));
if (isFemale(player))
appendHtml(tr("%1 creates token: %2%3.", "female").arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName))).arg(pt.isEmpty() ? QString() : QString(" (%1)").arg(sanitizeHtml(pt))));
else
appendHtml(tr("%1 creates token: %2%3.", "male").arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName))).arg(pt.isEmpty() ? QString() : QString(" (%1)").arg(sanitizeHtml(pt))));
}
void MessageLogWidget::logCreateArrow(Player *player, Player *startPlayer, QString startCard, Player *targetPlayer, QString targetCard, bool playerTarget)
{
if (playerTarget)
append(tr("%1 points from %2's %3 to %4.")
.arg(sanitizeHtml(player->getName()))
.arg(sanitizeHtml(startPlayer->getName()))
.arg(sanitizeHtml(startCard))
.arg(sanitizeHtml(targetPlayer->getName()))
);
else
append(tr("%1 points from %2's %3 to %4's %5.")
.arg(sanitizeHtml(player->getName()))
.arg(sanitizeHtml(startPlayer->getName()))
.arg(sanitizeHtml(startCard))
.arg(sanitizeHtml(targetPlayer->getName()))
.arg(sanitizeHtml(targetCard))
);
startCard = QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(startCard));
targetCard = QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(targetCard));
QString str;
if (playerTarget) {
if ((player == startPlayer) && (player == targetPlayer)) {
if (isFemale(player))
str = tr("%1 points from her %2 to herself.", "female");
else
str = tr("%1 points from his %2 to himself.", "male");
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(startCard));
} else if (player == startPlayer) {
if (isFemale(player)) {
if (isFemale(targetPlayer))
str = tr("%1 points from her %2 to %3.", "p1 female, p2 female");
else
str = tr("%1 points from her %2 to %3.", "p1 female, p2 male");
} else {
if (isFemale(targetPlayer))
str = tr("%1 points from his %2 to %3.", "p1 male, p2 female");
else
str = tr("%1 points from his %2 to %3.", "p1 male, p2 male");
}
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(startCard).arg(sanitizeHtml(targetPlayer->getName())));
} else if (player == targetPlayer) {
if (isFemale(player)) {
if (isFemale(startPlayer))
str = tr("%1 points from %2's %3 to herself.", "card owner female, target female");
else
str = tr("%1 points from %2's %3 to herself.", "card owner male, target female");
} else {
if (isFemale(startPlayer))
str = tr("%1 points from %2's %3 to himself.", "card owner female, target male");
else
str = tr("%1 points from %2's %3 to himself.", "card owner male, target male");
}
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(sanitizeHtml(startPlayer->getName())).arg(startCard));
} else {
if (isFemale(player)) {
if (isFemale(startPlayer)) {
if (isFemale(targetPlayer))
str = tr("%1 points from %2's %3 to %4.", "p1 female, p2 female, p3 female");
else
str = tr("%1 points from %2's %3 to %4.", "p1 female, p2 female, p3 male");
} else {
if (isFemale(targetPlayer))
str = tr("%1 points from %2's %3 to %4.", "p1 female, p2 male, p3 female");
else
str = tr("%1 points from %2's %3 to %4.", "p1 female, p2 male, p3 male");
}
} else {
if (isFemale(startPlayer)) {
if (isFemale(targetPlayer))
str = tr("%1 points from %2's %3 to %4.", "p1 male, p2 female, p3 female");
else
str = tr("%1 points from %2's %3 to %4.", "p1 male, p2 female, p3 male");
} else {
if (isFemale(targetPlayer))
str = tr("%1 points from %2's %3 to %4.", "p1 male, p2 male, p3 female");
else
str = tr("%1 points from %2's %3 to %4.", "p1 male, p2 male, p3 male");
}
}
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(sanitizeHtml(startPlayer->getName())).arg(startCard).arg(sanitizeHtml(targetPlayer->getName())));
}
} else {
if ((player == startPlayer) && (player == targetPlayer)) {
if (isFemale(player))
str = tr("%1 points from her %2 to her %3.", "female");
else
str = tr("%1 points from his %2 to his %3.", "male");
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(startCard).arg(targetCard));
} else if (player == startPlayer) {
if (isFemale(player)) {
if (isFemale(targetPlayer))
str = tr("%1 points from her %2 to %3's %4.", "p1 female, p2 female");
else
str = tr("%1 points from her %2 to %3's %4.", "p1 female, p2 male");
} else {
if (isFemale(targetPlayer))
str = tr("%1 points from his %2 to %3's %4.", "p1 male, p2 female");
else
str = tr("%1 points from his %2 to %3's %4.", "p1 male, p2 male");
}
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(startCard).arg(sanitizeHtml(targetPlayer->getName())).arg(targetCard));
} else if (player == targetPlayer) {
if (isFemale(player)) {
if (isFemale(startPlayer))
str = tr("%1 points from %2's %3 to her own %4.", "card owner female, target female");
else
str = tr("%1 points from %2's %3 to her own %4.", "card owner male, target female");
} else {
if (isFemale(startPlayer))
str = tr("%1 points from %2's %3 to his own %4.", "card owner female, target male");
else
str = tr("%1 points from %2's %3 to his own %4.", "card owner male, target male");
}
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(sanitizeHtml(startPlayer->getName())).arg(startCard).arg(targetCard));
} else {
if (isFemale(player)) {
if (isFemale(startPlayer)) {
if (isFemale(targetPlayer))
str = tr("%1 points from %2's %3 to %4's %5.", "p1 female, p2 female, p3 female");
else
str = tr("%1 points from %2's %3 to %4's %5.", "p1 female, p2 female, p3 male");
} else {
if (isFemale(targetPlayer))
str = tr("%1 points from %2's %3 to %4's %5.", "p1 female, p2 male, p3 female");
else
str = tr("%1 points from %2's %3 to %4's %5.", "p1 female, p2 male, p3 male");
}
} else {
if (isFemale(startPlayer)) {
if (isFemale(targetPlayer))
str = tr("%1 points from %2's %3 to %4's %5.", "p1 male, p2 female, p3 female");
else
str = tr("%1 points from %2's %3 to %4's %5.", "p1 male, p2 female, p3 male");
} else {
if (isFemale(targetPlayer))
str = tr("%1 points from %2's %3 to %4's %5.", "p1 male, p2 male, p3 female");
else
str = tr("%1 points from %2's %3 to %4's %5.", "p1 male, p2 male, p3 male");
}
}
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(sanitizeHtml(startPlayer->getName())).arg(startCard).arg(sanitizeHtml(targetPlayer->getName())).arg(targetCard));
}
}
}
void MessageLogWidget::logSetCardCounter(Player *player, QString cardName, int counterId, int value, int oldValue)
@ -300,10 +482,17 @@ void MessageLogWidget::logSetCardCounter(Player *player, QString cardName, int c
QString finalStr, colorStr;
int delta = abs(oldValue - value);
if (value > oldValue)
finalStr = tr("%1 places %n %2 counter(s) on %3 (now %4).", "", delta);
else
finalStr = tr("%1 removes %n %2 counter(s) from %3 (now %4).", "", delta);
if (value > oldValue) {
if (isFemale(player))
finalStr = tr("%1 places %n %2 counter(s) on %3 (now %4).", "female", delta);
else
finalStr = tr("%1 places %n %2 counter(s) on %3 (now %4).", "male", delta);
} else {
if (isFemale(player))
finalStr = tr("%1 removes %n %2 counter(s) from %3 (now %4).", "female", delta);
else
finalStr = tr("%1 removes %n %2 counter(s) from %3 (now %4).", "male", delta);
}
switch (counterId) {
case 0: colorStr = tr("red", "", delta); break;
@ -312,63 +501,124 @@ void MessageLogWidget::logSetCardCounter(Player *player, QString cardName, int c
default: ;
}
append(finalStr.arg(sanitizeHtml(player->getName())).arg(colorStr).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName))).arg(value));
appendHtml(finalStr.arg(sanitizeHtml(player->getName())).arg(colorStr).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName))).arg(value));
}
void MessageLogWidget::logSetTapped(Player *player, CardItem *card, bool tapped)
{
if (tapped)
soundEngine->tap();
else
soundEngine->untap();
if (currentContext == MessageContext_MoveCard)
moveCardTapped.insert(card, tapped);
else {
QString cardStr;
if (!card)
cardStr = tr("his permanents");
else
cardStr = QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(card->getName()));
append(tr("%1 %2 %3.").arg(sanitizeHtml(player->getName())).arg(tapped ? tr("taps") : tr("untaps")).arg(cardStr));
QString str;
if (!card) {
if (isFemale(player)) {
if (tapped)
str = tr("%1 taps her permanents.", "female");
else
str = tr("%1 untaps her permanents.", "female");
} else {
if (tapped)
str = tr("%1 taps his permanents.", "male");
else
str = tr("%1 untaps his permanents.", "male");
}
appendHtml(str.arg(sanitizeHtml(player->getName())));
} else {
if (isFemale(player)) {
if (tapped)
str = tr("%1 taps %2.", "female");
else
str = tr("%1 untaps %2.", "female");
} else {
if (tapped)
str = tr("%1 taps %2.", "male");
else
str = tr("%1 untaps %2.", "male");
}
QString cardStr = QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(card->getName()));
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(cardStr));
}
}
}
void MessageLogWidget::logSetCounter(Player *player, QString counterName, int value, int oldValue)
{
append(tr("%1 sets counter %2 to %3 (%4%5).").arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(counterName))).arg(QString("<font color=\"blue\">%1</font>").arg(value)).arg(value > oldValue ? "+" : "").arg(value - oldValue));
QString str;
if (isFemale(player))
str = tr("%1 sets counter %2 to %3 (%4%5).", "female");
else
str = tr("%1 sets counter %2 to %3 (%4%5).", "male");
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(counterName))).arg(QString("<font color=\"blue\">%1</font>").arg(value)).arg(value > oldValue ? "+" : "").arg(value - oldValue));
}
void MessageLogWidget::logSetDoesntUntap(Player *player, CardItem *card, bool doesntUntap)
{
QString finalStr;
if (doesntUntap)
finalStr = tr("%1 sets %2 to not untap normally.");
else
finalStr = tr("%1 sets %2 to untap normally.");
append(finalStr.arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(card->getName()))));
QString str;
if (doesntUntap) {
if (isFemale(player))
str = tr("%1 sets %2 to not untap normally.", "female");
else
str = tr("%1 sets %2 to not untap normally.", "male");
} else {
if (isFemale(player))
str = tr("%1 sets %2 to untap normally.", "female");
else
str = tr("%1 sets %2 to untap normally.", "male");
}
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(card->getName()))));
}
void MessageLogWidget::logSetPT(Player *player, CardItem *card, QString newPT)
{
if (currentContext == MessageContext_MoveCard)
moveCardPT.insert(card, newPT);
else
append(tr("%1 sets PT of %2 to %3.").arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(card->getName()))).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(newPT))));
else {
QString str;
if (isFemale(player))
str = tr("%1 sets PT of %2 to %3.", "female");
else
str = tr("%1 sets PT of %2 to %3.", "male");
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(card->getName()))).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(newPT))));
}
}
void MessageLogWidget::logSetAnnotation(Player *player, CardItem *card, QString newAnnotation)
{
append(tr("%1 sets annotation of %2 to %3.").arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(card->getName()))).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(newAnnotation))));
QString str;
if (isFemale(player))
str = tr("%1 sets annotation of %2 to %3.", "female");
else
str = tr("%1 sets annotation of %2 to %3.", "male");
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(card->getName()))).arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(newAnnotation))));
}
void MessageLogWidget::logDumpZone(Player *player, CardZone *zone, int numberCards)
{
if (numberCards != -1)
append(tr("%1 is looking at the top %2 cards %3.").arg(sanitizeHtml(player->getName())).arg(numberCards).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseGenitive)));
else
append(tr("%1 is looking at %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseAccusative)));
if (numberCards != -1) {
if (isFemale(player))
appendHtml(tr("%1 is looking at the top %2 cards %3.", "female").arg(sanitizeHtml(player->getName())).arg(numberCards).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseGenitive)));
else
appendHtml(tr("%1 is looking at the top %2 cards %3.", "male").arg(sanitizeHtml(player->getName())).arg(numberCards).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseGenitive)));
} else {
if (isFemale(player))
appendHtml(tr("%1 is looking at %2.", "female").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseAccusative)));
else
appendHtml(tr("%1 is looking at %2.", "male").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseAccusative)));
}
}
void MessageLogWidget::logStopDumpZone(Player *player, CardZone *zone)
{
QString zoneName = zone->getTranslatedName(zone->getPlayer() == player, CaseAccusative);
append(tr("%1 stops looking at %2.").arg(sanitizeHtml(player->getName())).arg(zoneName));
if (isFemale(player))
appendHtml(tr("%1 stops looking at %2.", "female").arg(sanitizeHtml(player->getName())).arg(zoneName));
else
appendHtml(tr("%1 stops looking at %2.", "male").arg(sanitizeHtml(player->getName())).arg(zoneName));
}
void MessageLogWidget::logRevealCards(Player *player, CardZone *zone, int cardId, QString cardName, Player *otherPlayer)
@ -389,33 +639,85 @@ void MessageLogWidget::logRevealCards(Player *player, CardZone *zone, int cardId
else
cardStr = QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(cardName));
QString str;
if (cardId == -1) {
if (otherPlayer)
append(tr("%1 reveals %2 to %3.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative)).arg(sanitizeHtml(otherPlayer->getName())));
else
append(tr("%1 reveals %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative)));
if (otherPlayer) {
if (isFemale(player)) {
if (isFemale(otherPlayer))
str = tr("%1 reveals %2 to %3.", "p1 female, p2 female");
else
str = tr("%1 reveals %2 to %3.", "p1 female, p2 male");
} else {
if (isFemale(otherPlayer))
str = tr("%1 reveals %2 to %3.", "p1 male, p2 female");
else
str = tr("%1 reveals %2 to %3.", "p1 male, p2 male");
}
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative)).arg(sanitizeHtml(otherPlayer->getName())));
} else {
if (isFemale(player))
appendHtml(tr("%1 reveals %2.", "female").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative)));
else
appendHtml(tr("%1 reveals %2.", "male").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative)));
}
} else if (cardId == -2) {
if (otherPlayer)
append(tr("%1 randomly reveals %2%3 to %4.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName())));
else
append(tr("%1 randomly reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr));
if (otherPlayer) {
if (isFemale(player)) {
if (isFemale(otherPlayer))
str = tr("%1 randomly reveals %2%3 to %4.", "p1 female, p2 female");
else
str = tr("%1 randomly reveals %2%3 to %4.", "p1 female, p2 male");
} else {
if (isFemale(otherPlayer))
str = tr("%1 randomly reveals %2%3 to %4.", "p1 male, p2 female");
else
str = tr("%1 randomly reveals %2%3 to %4.", "p1 male, p2 male");
}
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName())));
} else {
if (isFemale(player))
appendHtml(tr("%1 randomly reveals %2%3.", "female").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative)));
else
appendHtml(tr("%1 randomly reveals %2%3.", "male").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr));
}
} else {
if (otherPlayer)
append(tr("%1 reveals %2%3 to %4.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName())));
else
append(tr("%1 reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr));
if (otherPlayer) {
if (isFemale(player)) {
if (isFemale(otherPlayer))
str = tr("%1 reveals %2%3 to %4.", "p1 female, p2 female");
else
str = tr("%1 reveals %2%3 to %4.", "p1 female, p2 male");
} else {
if (isFemale(otherPlayer))
str = tr("%1 reveals %2%3 to %4.", "p1 male, p2 female");
else
str = tr("%1 reveals %2%3 to %4.", "p1 male, p2 male");
}
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName())));
} else {
if (isFemale(player))
appendHtml(tr("%1 reveals %2%3.", "female").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative)));
else
appendHtml(tr("%1 reveals %2%3.", "male").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr));
}
}
}
void MessageLogWidget::logSetActivePlayer(Player *player)
{
append(QString());
append("<font color=\"green\"><b>" + tr("It is now %1's turn.").arg(player->getName()) + "</b></font>");
append(QString());
soundEngine->notification();
QString str;
if (isFemale(player))
str = tr("It is now %1's turn.", "female");
else
str = tr("It is now %1's turn.", "male");
appendHtml("<br><font color=\"green\"><b>" + str.arg(player->getName()) + "</b></font><br>");
}
void MessageLogWidget::logSetActivePhase(int phase)
{
soundEngine->notification();
QString phaseName;
switch (phase) {
case 0: phaseName = tr("untap step"); break;
@ -430,13 +732,18 @@ void MessageLogWidget::logSetActivePhase(int phase)
case 9: phaseName = tr("second main phase"); break;
case 10: phaseName = tr("ending phase"); break;
}
append("<font color=\"green\"><b>" + tr("It is now the %1.").arg(phaseName) + "</b></font>");
appendHtml("<font color=\"green\"><b>" + tr("It is now the %1.").arg(phaseName) + "</b></font>");
}
void MessageLogWidget::containerProcessingStarted(GameEventContext *_context)
{
if (qobject_cast<Context_MoveCard *>(_context))
currentContext = MessageContext_MoveCard;
else if (qobject_cast<Context_Mulligan *>(_context)) {
currentContext = MessageContext_Mulligan;
mulliganPlayer = 0;
mulliganNumber = static_cast<Context_Mulligan *>(_context)->getNumber();
}
}
void MessageLogWidget::containerProcessingDone()
@ -447,6 +754,10 @@ void MessageLogWidget::containerProcessingDone()
moveCardQueue.clear();
moveCardPT.clear();
moveCardTapped.clear();
} else if (currentContext == MessageContext_Mulligan) {
logMulligan(mulliganPlayer, mulliganNumber);
mulliganPlayer = 0;
mulliganNumber = 0;
}
currentContext = MessageContext_None;
@ -454,8 +765,9 @@ void MessageLogWidget::containerProcessingDone()
void MessageLogWidget::connectToPlayer(Player *player)
{
connect(player, SIGNAL(logConnectionStateChanged(Player *, bool)), this, SLOT(logConnectionStateChanged(Player *, bool)));
connect(player, SIGNAL(logSay(Player *, QString)), this, SLOT(logSay(Player *, QString)));
connect(player, SIGNAL(logShuffle(Player *)), this, SLOT(logShuffle(Player *)));
connect(player, SIGNAL(logShuffle(Player *, CardZone *)), this, SLOT(logShuffle(Player *, CardZone *)));
connect(player, SIGNAL(logRollDie(Player *, int, int)), this, SLOT(logRollDie(Player *, int, int)));
connect(player, SIGNAL(logCreateArrow(Player *, Player *, QString, Player *, QString, bool)), this, SLOT(logCreateArrow(Player *, Player *, QString, Player *, QString, bool)));
connect(player, SIGNAL(logCreateToken(Player *, QString, QString)), this, SLOT(logCreateToken(Player *, QString, QString)));
@ -477,66 +789,7 @@ void MessageLogWidget::connectToPlayer(Player *player)
connect(player, SIGNAL(logRevealCards(Player *, CardZone *, int, QString, Player *)), this, SLOT(logRevealCards(Player *, CardZone *, int, QString, Player *)));
}
MessageLogWidget::MessageLogWidget(QWidget *parent)
: QTextEdit(parent)
MessageLogWidget::MessageLogWidget(const QString &_ownName, bool _female, QWidget *parent)
: ChatView(_ownName, false, parent), female(_female)
{
setReadOnly(true);
}
void MessageLogWidget::enterEvent(QEvent * /*event*/)
{
setMouseTracking(true);
}
void MessageLogWidget::leaveEvent(QEvent * /*event*/)
{
setMouseTracking(false);
}
QString MessageLogWidget::getCardNameUnderMouse(const QPoint &pos) const
{
QTextCursor cursor(cursorForPosition(pos));
QTextBlock block(cursor.block());
QTextBlock::iterator it;
for (it = block.begin(); !(it.atEnd()); ++it) {
QTextFragment frag = it.fragment();
if (!frag.contains(cursor.position()))
continue;
if (frag.charFormat().foreground().color() == Qt::blue)
return frag.text();
break;
}
return QString();
}
void MessageLogWidget::mouseMoveEvent(QMouseEvent *event)
{
QString cardName = getCardNameUnderMouse(event->pos());
if (!cardName.isEmpty()) {
viewport()->setCursor(Qt::PointingHandCursor);
emit cardNameHovered(cardName);
} else
viewport()->setCursor(Qt::IBeamCursor);
QTextEdit::mouseMoveEvent(event);
}
void MessageLogWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::MidButton) {
QString cardName = getCardNameUnderMouse(event->pos());
if (!cardName.isEmpty())
emit showCardInfoPopup(event->globalPos(), cardName);
}
QTextEdit::mousePressEvent(event);
}
void MessageLogWidget::mouseReleaseEvent(QMouseEvent *event)
{
emit deleteCardInfoPopup();
QTextEdit::mouseReleaseEvent(event);
}

View file

@ -1,15 +1,13 @@
#ifndef MESSAGELOGWIDGET_H
#define MESSAGELOGWIDGET_H
#include <QTextEdit>
#include "chatview.h"
#include <QAbstractSocket>
#include "translation.h"
#include "protocol_datastructures.h"
class Player;
class CardZone;
class QMouseEvent;
class QEvent;
class CardInfoWidget;
class GameEventContext;
class CardItem;
@ -24,31 +22,24 @@ struct LogMoveCard {
int newX;
};
class MessageLogWidget : public QTextEdit {
class MessageLogWidget : public ChatView {
Q_OBJECT
private:
enum MessageContext { MessageContext_None, MessageContext_MoveCard };
enum MessageContext { MessageContext_None, MessageContext_MoveCard, MessageContext_Mulligan };
CardInfoWidget *infoWidget;
QString sanitizeHtml(QString dirty) const;
bool isFemale(Player *player) const;
QPair<QString, QString> getFromStr(CardZone *zone, QString cardName, int position) const;
QString getCardNameUnderMouse(const QPoint &pos) const;
MessageContext currentContext;
bool female;
QList<LogMoveCard> moveCardQueue;
QMap<CardItem *, QString> moveCardPT;
QMap<CardItem *, bool> moveCardTapped;
signals:
void cardNameHovered(QString cardName);
void showCardInfoPopup(QPoint pos, QString cardName);
void deleteCardInfoPopup();
Player *mulliganPlayer;
int mulliganNumber;
public slots:
void logConnecting(QString hostname);
void logConnected();
void logDisconnected();
void logSocketError(const QString &errorString);
void logServerError(ResponseCode response);
void logProtocolVersionMismatch(int clientVersion, int serverVersion);
void logProtocolError();
void logGameJoined(int gameId);
void logJoin(Player *player);
void logLeave(Player *player);
@ -60,14 +51,16 @@ public slots:
void logNotReadyStart(Player *player);
void logConcede(Player *player);
void logGameStart();
void logConnectionStateChanged(Player *player, bool connectionState);
void logSay(Player *player, QString message);
void logSpectatorSay(QString spectatorName, QString message);
void logShuffle(Player *player);
void logShuffle(Player *player, CardZone *zone);
void logRollDie(Player *player, int sides, int roll);
void logDrawCards(Player *player, int number);
void logUndoDraw(Player *player, QString cardName);
void doMoveCard(LogMoveCard &attributes);
void logMoveCard(Player *player, CardItem *card, CardZone *startZone, int oldX, CardZone *targetZone, int newX);
void logMulligan(Player *player, int number);
void logFlipCard(Player *player, QString cardName, bool faceDown);
void logDestroyCard(Player *player, QString cardName);
void logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName);
@ -89,13 +82,7 @@ public slots:
void containerProcessingDone();
public:
void connectToPlayer(Player *player);
MessageLogWidget(QWidget *parent = 0);
protected:
void enterEvent(QEvent *event);
void leaveEvent(QEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
MessageLogWidget(const QString &_ownName, bool _female, QWidget *parent = 0);
};
#endif

View file

@ -78,6 +78,36 @@ QPixmap PingPixmapGenerator::generatePixmap(int size, int value, int max)
QMap<int, QPixmap> PingPixmapGenerator::pmCache;
QPixmap GenderPixmapGenerator::generatePixmap(int height, int _gender)
{
ServerInfo_User::Gender gender = static_cast<ServerInfo_User::Gender>(_gender);
if ((gender != ServerInfo_User::Male) && (gender != ServerInfo_User::Female))
gender = ServerInfo_User::GenderUnknown;
int key = gender * 100000 + height;
if (pmCache.contains(key))
return pmCache.value(key);
QString genderStr;
switch (gender) {
case ServerInfo_User::Male: genderStr = "male"; break;
case ServerInfo_User::Female: genderStr = "female"; break;
default: genderStr = "unknown";
};
QSvgRenderer svg(QString(":/resources/genders/" + genderStr + ".svg"));
int width = (int) round(height * (double) svg.defaultSize().width() / (double) svg.defaultSize().height());
QPixmap pixmap(width, height);
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
svg.render(&painter, QRectF(0, 0, width, height));
pmCache.insert(key, pixmap);
return pixmap;
}
QMap<int, QPixmap> GenderPixmapGenerator::pmCache;
QPixmap CountryPixmapGenerator::generatePixmap(int height, const QString &countryCode)
{
if (countryCode.size() != 2)
@ -110,8 +140,8 @@ QPixmap UserLevelPixmapGenerator::generatePixmap(int height, int userLevel)
QString levelString;
if (userLevel & ServerInfo_User::IsAdmin)
levelString = "admin";
else if (userLevel & ServerInfo_User::IsJudge)
levelString = "judge";
else if (userLevel & ServerInfo_User::IsModerator)
levelString = "moderator";
else if (userLevel &ServerInfo_User::IsRegistered)
levelString = "registered";
else

View file

@ -28,6 +28,14 @@ public:
static void clear() { pmCache.clear(); }
};
class GenderPixmapGenerator {
private:
static QMap<int, QPixmap> pmCache;
public:
static QPixmap generatePixmap(int height, int gender);
static void clear() { pmCache.clear(); }
};
class CountryPixmapGenerator {
private:
static QMap<QString, QPixmap> pmCache;

View file

@ -706,6 +706,11 @@ void Player::setCardAttrHelper(GameEventContext *context, CardItem *card, const
}
}
void Player::eventConnectionStateChanged(Event_ConnectionStateChanged *event)
{
emit logConnectionStateChanged(this, event->getConnected());
}
void Player::eventSay(Event_Say *event)
{
emit logSay(this, event->getMessage());
@ -713,7 +718,7 @@ void Player::eventSay(Event_Say *event)
void Player::eventShuffle(Event_Shuffle * /*event*/)
{
emit logShuffle(this);
emit logShuffle(this, zones.value("deck"));
}
void Player::eventRollDie(Event_RollDie *event)
@ -862,6 +867,8 @@ void Player::eventMoveCard(Event_MoveCard *event, GameEventContext *context)
CardItem *card = startZone->takeCard(position, event->getCardId(), startZone != targetZone);
if (!card)
return;
if (startZone != targetZone)
card->deleteCardInfoPopup();
card->setName(event->getCardName());
if (card->getAttachedTo() && (startZone != targetZone)) {
@ -891,8 +898,7 @@ void Player::eventMoveCard(Event_MoveCard *event, GameEventContext *context)
if (context)
switch (context->getItemId()) {
case ItemId_Context_UndoDraw: emit logUndoDraw(this, card->getName()); break;
case ItemId_Context_MoveCard: emit logMoveCard(this, card, startZone, logPosition, targetZone, logX);
default: ;
default: emit logMoveCard(this, card, startZone, logPosition, targetZone, logX);
}
else
emit logMoveCard(this, card, startZone, logPosition, targetZone, logX);
@ -1008,7 +1014,6 @@ void Player::eventDrawCards(Event_DrawCards *event)
hand->reorganizeCards();
deck->reorganizeCards();
emit logDrawCards(this, event->getNumberCards());
}
@ -1038,6 +1043,7 @@ void Player::processGameEvent(GameEvent *event, GameEventContext *context)
{
qDebug() << "player event: id=" << event->getItemId();
switch (event->getItemId()) {
case ItemId_Event_ConnectionStateChanged: eventConnectionStateChanged(static_cast<Event_ConnectionStateChanged *>(event)); break;
case ItemId_Event_Say: eventSay(static_cast<Event_Say *>(event)); break;
case ItemId_Event_Shuffle: eventShuffle(static_cast<Event_Shuffle *>(event)); break;
case ItemId_Event_RollDie: eventRollDie(static_cast<Event_RollDie *>(event)); break;
@ -1546,12 +1552,9 @@ void Player::setMirrored(bool _mirrored)
}
}
void Player::processSceneSizeChange(const QSizeF &newSize)
void Player::processSceneSizeChange(int newPlayerWidth)
{
// This will need to be changed if player areas are displayed side by side (e.g. 2x2 for a 4-player game)
qreal fullPlayerWidth = newSize.width();
qreal tableWidth = fullPlayerWidth - CARD_HEIGHT - 15 - counterAreaWidth - stack->boundingRect().width();
qreal tableWidth = newPlayerWidth - CARD_HEIGHT - 15 - counterAreaWidth - stack->boundingRect().width();
if (!settingsCache->getHorizontalHand())
tableWidth -= hand->boundingRect().width();

View file

@ -26,6 +26,7 @@ class CommandContainer;
class GameCommand;
class GameEvent;
class GameEventContext;
class Event_ConnectionStateChanged;
class Event_Say;
class Event_Shuffle;
class Event_RollDie;
@ -69,8 +70,9 @@ class Player : public QObject, public QGraphicsItem {
signals:
void newCardAdded(AbstractCardItem *card);
// Log events
void logConnectionStateChanged(Player *player, bool connectionState);
void logSay(Player *player, QString message);
void logShuffle(Player *player);
void logShuffle(Player *player, CardZone *zone);
void logRollDie(Player *player, int sides, int roll);
void logCreateArrow(Player *player, Player *startPlayer, QString startCard, Player *targetPlayer, QString targetCard, bool _playerTarget);
void logCreateToken(Player *player, QString cardName, QString pt);
@ -176,6 +178,7 @@ private:
void initSayMenu();
void eventConnectionStateChanged(Event_ConnectionStateChanged *event);
void eventSay(Event_Say *event);
void eventShuffle(Event_Shuffle *event);
void eventRollDie(Event_RollDie *event);
@ -245,7 +248,7 @@ public:
qreal getMinimumWidth() const;
void setMirrored(bool _mirrored);
void processSceneSizeChange(const QSizeF &newSize);
void processSceneSizeChange(int newPlayerWidth);
void processPlayerInfo(ServerInfo_Player *info);
void processCardAttachment(ServerInfo_Player *info);

View file

@ -0,0 +1,81 @@
/**
* @author Marcio Ribeiro <mmr@b1n.org>
* @version 1.0
*/
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QScriptEngine>
#include <QScriptValueIterator>
#include "priceupdater.h"
/**
* Constructor.
*
* @param _deck deck.
*/
PriceUpdater::PriceUpdater(const DeckList *_deck)
{
nam = new QNetworkAccessManager(this);
deck = _deck;
}
/**
* Update the prices of the cards in deckList.
*/
void PriceUpdater::updatePrices()
{
QString q = "http://blacklotusproject.com/json/?cards=";
QStringList cards = deck->getCardList();
for (int i = 0; i < cards.size(); ++i) {
q += cards[i] + "|";
}
QUrl url(q.replace(' ', '+'));
QNetworkReply *reply = nam->get(QNetworkRequest(url));
connect(reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
}
/**
* Called when the download of the json file with the prices is finished.
*/
void PriceUpdater::downloadFinished()
{
QMap<QString, DecklistCardNode *> cmap;
InnerDecklistNode *listRoot = deck->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
if (!currentCard)
continue;
cmap.insert(currentCard->getName().toLower(), currentCard);
currentCard->setPrice(0);
}
}
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
QByteArray result = reply->readAll();
QScriptValue sc;
QScriptEngine engine;
sc = engine.evaluate("value = " + result);
if (sc.property("cards").isArray()) {
QScriptValueIterator it(sc.property("cards"));
while (it.hasNext()) {
it.next();
QString name = it.value().property("name").toString().toLower();
float price = it.value().property("average").toString().toFloat();
DecklistCardNode *c = cmap[name];
if (!c)
continue;
if (c->getPrice() == 0 || c->getPrice() > price) {
c->setPrice(price);
}
}
}
reply->deleteLater();
deleteLater();
emit finishedUpdate();
}

View file

@ -0,0 +1,28 @@
#ifndef PRICEUPDATER_H
#define PRICEUPDATER_H
#include <QNetworkReply>
#include "decklist.h"
class QNetworkAccessManager;
/**
* Price Updater.
*
* @author Marcio Ribeiro <mmr@b1n.org>
*/
class PriceUpdater : public QObject
{
Q_OBJECT
private:
const DeckList *deck;
QNetworkAccessManager *nam;
signals:
void finishedUpdate();
private slots:
void downloadFinished();
public:
PriceUpdater(const DeckList *deck);
void updatePrices();
};
#endif

View file

@ -1,6 +1,7 @@
#include <QTimer>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QCryptographicHash>
#include "remoteclient.h"
#include "protocol.h"
#include "protocol_items.h"
@ -82,12 +83,13 @@ void RemoteClient::readData()
xmlWriter->writeStartDocument();
xmlWriter->writeStartElement("cockatrice_client_stream");
xmlWriter->writeAttribute("version", QString::number(ProtocolItem::protocolVersion));
xmlWriter->writeAttribute("comp", "1");
topLevelItem = new TopLevelProtocolItem;
connect(topLevelItem, SIGNAL(protocolItemReceived(ProtocolItem *)), this, SLOT(processProtocolItem(ProtocolItem *)));
setStatus(StatusLoggingIn);
Command_Login *cmdLogin = new Command_Login(userName, password);
Command_Login *cmdLogin = new Command_Login(userName, QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha1).toBase64());
connect(cmdLogin, SIGNAL(finished(ProtocolResponse *)), this, SLOT(loginResponse(ProtocolResponse *)));
sendCommand(cmdLogin);
}

View file

@ -19,14 +19,21 @@ SettingsCache::SettingsCache()
picDownload = settings->value("personal/picturedownload", true).toBool();
doubleClickToPlay = settings->value("interface/doubleclicktoplay", true).toBool();
cardInfoMinimized = settings->value("interface/cardinfominimized", false).toBool();
cardInfoMinimized = settings->value("interface/cardinfominimized", 0).toInt();
tabGameSplitterSizes = settings->value("interface/tabgame_splittersizes").toByteArray();
displayCardNames = settings->value("cards/displaycardnames", true).toBool();
horizontalHand = settings->value("hand/horizontal", true).toBool();
invertVerticalCoordinate = settings->value("table/invert_vertical", false).toBool();
minPlayersForMultiColumnLayout = settings->value("interface/min_players_multicolumn", 5).toInt();
tapAnimation = settings->value("cards/tapanimation", true).toBool();
zoneViewSortByName = settings->value("zoneview/sortbyname", true).toBool();
zoneViewSortByType = settings->value("zoneview/sortbytype", true).toBool();
soundEnabled = settings->value("sound/enabled", false).toBool();
soundPath = settings->value("sound/path").toString();
priceTagFeature = settings->value("deckeditor/pricetags", false).toBool();
}
void SettingsCache::setLang(const QString &_lang)
@ -104,12 +111,18 @@ void SettingsCache::setDoubleClickToPlay(int _doubleClickToPlay)
settings->setValue("interface/doubleclicktoplay", doubleClickToPlay);
}
void SettingsCache::setCardInfoMinimized(bool _cardInfoMinimized)
void SettingsCache::setCardInfoMinimized(int _cardInfoMinimized)
{
cardInfoMinimized = _cardInfoMinimized;
cardInfoMinimized = _cardInfoMinimized;
settings->setValue("interface/cardinfominimized", cardInfoMinimized);
}
void SettingsCache::setTabGameSplitterSizes(const QByteArray &_tabGameSplitterSizes)
{
tabGameSplitterSizes = _tabGameSplitterSizes;
settings->setValue("interface/tabgame_splittersizes", tabGameSplitterSizes);
}
void SettingsCache::setDisplayCardNames(int _displayCardNames)
{
displayCardNames = _displayCardNames;
@ -131,6 +144,13 @@ void SettingsCache::setInvertVerticalCoordinate(int _invertVerticalCoordinate)
emit invertVerticalCoordinateChanged();
}
void SettingsCache::setMinPlayersForMultiColumnLayout(int _minPlayersForMultiColumnLayout)
{
minPlayersForMultiColumnLayout = _minPlayersForMultiColumnLayout;
settings->setValue("interface/min_players_multicolumn", minPlayersForMultiColumnLayout);
emit minPlayersForMultiColumnLayoutChanged();
}
void SettingsCache::setTapAnimation(int _tapAnimation)
{
tapAnimation = _tapAnimation;
@ -148,3 +168,22 @@ void SettingsCache::setZoneViewSortByType(int _zoneViewSortByType)
zoneViewSortByType = _zoneViewSortByType;
settings->setValue("zoneview/sortbytype", zoneViewSortByType);
}
void SettingsCache::setSoundEnabled(int _soundEnabled)
{
soundEnabled = _soundEnabled;
settings->setValue("sound/enabled", soundEnabled);
}
void SettingsCache::setSoundPath(const QString &_soundPath)
{
soundPath = _soundPath;
settings->setValue("sound/path", soundPath);
emit soundPathChanged();
}
void SettingsCache::setPriceTagFeature(int _priceTagFeature)
{
priceTagFeature = _priceTagFeature;
settings->setValue("deckeditor/pricetags", priceTagFeature);
}

View file

@ -20,6 +20,8 @@ signals:
void displayCardNamesChanged();
void horizontalHandChanged();
void invertVerticalCoordinateChanged();
void minPlayersForMultiColumnLayoutChanged();
void soundPathChanged();
private:
QSettings *settings;
@ -28,12 +30,17 @@ private:
QString handBgPath, stackBgPath, tableBgPath, playerBgPath, cardBackPicturePath;
bool picDownload;
bool doubleClickToPlay;
bool cardInfoMinimized;
int cardInfoMinimized;
QByteArray tabGameSplitterSizes;
bool displayCardNames;
bool horizontalHand;
bool invertVerticalCoordinate;
int minPlayersForMultiColumnLayout;
bool tapAnimation;
bool zoneViewSortByName, zoneViewSortByType;
bool soundEnabled;
QString soundPath;
bool priceTagFeature;
public:
SettingsCache();
QString getLang() const { return lang; }
@ -47,13 +54,18 @@ public:
QString getCardBackPicturePath() const { return cardBackPicturePath; }
bool getPicDownload() const { return picDownload; }
bool getDoubleClickToPlay() const { return doubleClickToPlay; }
bool getCardInfoMinimized() const { return cardInfoMinimized; }
int getCardInfoMinimized() const { return cardInfoMinimized; }
QByteArray getTabGameSplitterSizes() const { return tabGameSplitterSizes; }
bool getDisplayCardNames() const { return displayCardNames; }
bool getHorizontalHand() const { return horizontalHand; }
bool getInvertVerticalCoordinate() const { return invertVerticalCoordinate; }
int getMinPlayersForMultiColumnLayout() const { return minPlayersForMultiColumnLayout; }
bool getTapAnimation() const { return tapAnimation; }
bool getZoneViewSortByName() const { return zoneViewSortByName; }
bool getZoneViewSortByType() const { return zoneViewSortByType; }
bool getSoundEnabled() const { return soundEnabled; }
QString getSoundPath() const { return soundPath; }
bool getPriceTagFeature() const { return priceTagFeature; }
public slots:
void setLang(const QString &_lang);
void setDeckPath(const QString &_deckPath);
@ -66,13 +78,18 @@ public slots:
void setCardBackPicturePath(const QString &_cardBackPicturePath);
void setPicDownload(int _picDownload);
void setDoubleClickToPlay(int _doubleClickToPlay);
void setCardInfoMinimized(bool _cardInfoMinimized);
void setCardInfoMinimized(int _cardInfoMinimized);
void setTabGameSplitterSizes(const QByteArray &_tabGameSplitterSizes);
void setDisplayCardNames(int _displayCardNames);
void setHorizontalHand(int _horizontalHand);
void setInvertVerticalCoordinate(int _invertVerticalCoordinate);
void setMinPlayersForMultiColumnLayout(int _minPlayersForMultiColumnLayout);
void setTapAnimation(int _tapAnimation);
void setZoneViewSortByName(int _zoneViewSortByName);
void setZoneViewSortByType(int _zoneViewSortByType);
void setSoundEnabled(int _soundEnabled);
void setSoundPath(const QString &_soundPath);
void setPriceTagFeature(int _priceTagFeature);
};
extern SettingsCache *settingsCache;

View file

@ -0,0 +1,82 @@
#include "soundengine.h"
#include "settingscache.h"
#include <QAudioOutput>
#include <QAudioFormat>
#include <QFile>
#include <QBuffer>
SoundEngine::SoundEngine(QObject *parent)
: QObject(parent)
{
inputBuffer = new QBuffer;
QAudioFormat format;
format.setFrequency(44100);
format.setChannels(1);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
audio = new QAudioOutput(format, this);
connect(settingsCache, SIGNAL(soundPathChanged()), this, SLOT(cacheData()));
cacheData();
}
void SoundEngine::cacheData()
{
static const QStringList fileNames = QStringList()
<< "notification" << "draw" << "playcard" << "shuffle" << "tap" << "untap" << "cuckoo";
for (int i = 0; i < fileNames.size(); ++i) {
QFile file(settingsCache->getSoundPath() + "/" + fileNames[i] + ".raw");
file.open(QIODevice::ReadOnly);
audioData.insert(fileNames[i], file.readAll());
file.close();
}
}
void SoundEngine::playSound(const QString &fileName)
{
if (!settingsCache->getSoundEnabled())
return;
audio->stop();
inputBuffer->close();
inputBuffer->setData(audioData[fileName]);
inputBuffer->open(QIODevice::ReadOnly);
audio->start(inputBuffer);
}
void SoundEngine::notification()
{
playSound("notification");
}
void SoundEngine::draw()
{
playSound("draw");
}
void SoundEngine::playCard()
{
playSound("playcard");
}
void SoundEngine::shuffle()
{
playSound("shuffle");
}
void SoundEngine::tap()
{
playSound("tap");
}
void SoundEngine::untap()
{
playSound("untap");
}
void SoundEngine::cuckoo()
{
playSound("cuckoo");
}

View file

@ -0,0 +1,33 @@
#ifndef SOUNDENGINE_H
#define SOUNDENGINE_H
#include <QObject>
#include <QMap>
class QAudioOutput;
class QBuffer;
class SoundEngine : public QObject {
Q_OBJECT
private:
void playSound(const QString &fileName);
QMap<QString, QByteArray> audioData;
QBuffer *inputBuffer;
QAudioOutput *audio;
private slots:
void cacheData();
public:
SoundEngine(QObject *parent = 0);
public slots:
void notification();
void draw();
void playCard();
void shuffle();
void tap();
void untap();
void cuckoo();
};
extern SoundEngine *soundEngine;
#endif

32
cockatrice/src/tab.cpp Normal file
View file

@ -0,0 +1,32 @@
#include "tab.h"
#include "cardinfowidget.h"
#include <QDesktopWidget>
#include <QApplication>
Tab::Tab(TabSupervisor *_tabSupervisor, QWidget *parent)
: QWidget(parent), tabMenu(0), tabSupervisor(_tabSupervisor), contentsChanged(false), infoPopup(0)
{
}
void Tab::showCardInfoPopup(const QPoint &pos, const QString &cardName)
{
infoPopup = new CardInfoWidget(CardInfoWidget::ModePopUp, 0, Qt::Widget | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint);
infoPopup->setAttribute(Qt::WA_TransparentForMouseEvents);
infoPopup->setCard(cardName);
QRect screenRect = qApp->desktop()->screenGeometry(this);
infoPopup->move(
qMax(screenRect.left(), qMin(pos.x() - infoPopup->width() / 2, screenRect.left() + screenRect.width() - infoPopup->width())),
qMax(screenRect.top(), qMin(pos.y() - infoPopup->height() / 2, screenRect.top() + screenRect.height() - infoPopup->height()))
);
infoPopup->show();
}
void Tab::deleteCardInfoPopup(const QString &cardName)
{
if (infoPopup) {
if ((infoPopup->getCardName() == cardName) || (cardName == "_")) {
infoPopup->deleteLater();
infoPopup = 0;
}
}
}

View file

@ -5,24 +5,29 @@
class QMenu;
class TabSupervisor;
class CardInfoWidget;
class Tab : public QWidget {
Q_OBJECT
signals:
void userEvent();
void userEvent(bool globalEvent = true);
protected:
QMenu *tabMenu;
TabSupervisor *tabSupervisor;
protected slots:
void showCardInfoPopup(const QPoint &pos, const QString &cardName);
void deleteCardInfoPopup(const QString &cardName);
private:
bool contentsChanged;
CardInfoWidget *infoPopup;
public:
Tab(TabSupervisor *_tabSupervisor, QWidget *parent = 0)
: QWidget(parent), tabMenu(0), tabSupervisor(_tabSupervisor), contentsChanged(false) { }
Tab(TabSupervisor *_tabSupervisor, QWidget *parent = 0);
QMenu *getTabMenu() const { return tabMenu; }
bool getContentsChanged() const { return contentsChanged; }
void setContentsChanged(bool _contentsChanged) { contentsChanged = _contentsChanged; }
virtual QString getTabText() const = 0;
virtual void retranslateUi() = 0;
virtual void closeRequest() { }
};
#endif

View file

@ -1,19 +1,72 @@
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QPushButton>
#include <QGroupBox>
#include <QMessageBox>
#include <QSpinBox>
#include <QLabel>
#include <QLineEdit>
#include "tab_admin.h"
#include "abstractclient.h"
#include "protocol_items.h"
TabAdmin::TabAdmin(TabSupervisor *_tabSupervisor, AbstractClient *_client, QWidget *parent)
: Tab(_tabSupervisor, parent), locked(true), client(_client)
ShutdownDialog::ShutdownDialog(QWidget *parent)
: QDialog(parent)
{
QLabel *reasonLabel = new QLabel(tr("&Reason for shutdown:"));
reasonEdit = new QLineEdit;
reasonLabel->setBuddy(reasonEdit);
QLabel *minutesLabel = new QLabel(tr("&Time until shutdown (minutes):"));
minutesEdit = new QSpinBox;
minutesLabel->setBuddy(minutesEdit);
minutesEdit->setMinimum(0);
minutesEdit->setValue(5);
QPushButton *okButton = new QPushButton(tr("&OK"));
okButton->setAutoDefault(true);
okButton->setDefault(true);
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
QPushButton *cancelButton = new QPushButton(tr("&Cancel"));
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch();
buttonLayout->addWidget(okButton);
buttonLayout->addWidget(cancelButton);
QGridLayout *mainLayout = new QGridLayout;
mainLayout->addWidget(reasonLabel, 0, 0);
mainLayout->addWidget(reasonEdit, 0, 1);
mainLayout->addWidget(minutesLabel, 1, 0);
mainLayout->addWidget(minutesEdit, 1, 1);
mainLayout->addLayout(buttonLayout, 2, 0, 1, 2);
setLayout(mainLayout);
setWindowTitle(tr("Shut down server"));
}
QString ShutdownDialog::getReason() const
{
return reasonEdit->text();
}
int ShutdownDialog::getMinutes() const
{
return minutesEdit->value();
}
TabAdmin::TabAdmin(TabSupervisor *_tabSupervisor, AbstractClient *_client, bool _fullAdmin, QWidget *parent)
: Tab(_tabSupervisor, parent), locked(true), client(_client), fullAdmin(_fullAdmin)
{
updateServerMessageButton = new QPushButton;
connect(updateServerMessageButton, SIGNAL(clicked()), this, SLOT(actUpdateServerMessage()));
shutdownServerButton = new QPushButton;
connect(shutdownServerButton, SIGNAL(clicked()), this, SLOT(actShutdownServer()));
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(updateServerMessageButton);
vbox->addWidget(shutdownServerButton);
vbox->addStretch();
adminGroupBox = new QGroupBox;
@ -38,6 +91,7 @@ TabAdmin::TabAdmin(TabSupervisor *_tabSupervisor, AbstractClient *_client, QWidg
void TabAdmin::retranslateUi()
{
updateServerMessageButton->setText(tr("Update server &message"));
shutdownServerButton->setText(tr("&Shut down server"));
adminGroupBox->setTitle(tr("Server administration functions"));
unlockButton->setText(tr("&Unlock functions"));
@ -49,10 +103,18 @@ void TabAdmin::actUpdateServerMessage()
client->sendCommand(new Command_UpdateServerMessage());
}
void TabAdmin::actShutdownServer()
{
ShutdownDialog dlg;
if (dlg.exec())
client->sendCommand(new Command_ShutdownServer(dlg.getReason(), dlg.getMinutes()));
}
void TabAdmin::actUnlock()
{
if (QMessageBox::question(this, tr("Unlock administration functions"), tr("Do you really want to unlock the administration functions?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
adminGroupBox->setEnabled(true);
if (fullAdmin)
adminGroupBox->setEnabled(true);
lockButton->setEnabled(true);
unlockButton->setEnabled(false);
locked = false;
@ -61,7 +123,8 @@ void TabAdmin::actUnlock()
void TabAdmin::actLock()
{
adminGroupBox->setEnabled(false);
if (fullAdmin)
adminGroupBox->setEnabled(false);
lockButton->setEnabled(false);
unlockButton->setEnabled(true);
locked = true;

View file

@ -2,27 +2,43 @@
#define TAB_ADMIN_H
#include "tab.h"
#include <QDialog>
class AbstractClient;
class QGroupBox;
class QPushButton;
class QSpinBox;
class QLineEdit;
class ShutdownDialog : public QDialog {
Q_OBJECT
private:
QLineEdit *reasonEdit;
QSpinBox *minutesEdit;
public:
ShutdownDialog(QWidget *parent = 0);
QString getReason() const;
int getMinutes() const;
};
class TabAdmin : public Tab {
Q_OBJECT
private:
bool locked;
AbstractClient *client;
QPushButton *updateServerMessageButton;
bool fullAdmin;
QPushButton *updateServerMessageButton, *shutdownServerButton;
QGroupBox *adminGroupBox;
QPushButton *unlockButton, *lockButton;
private slots:
void actUpdateServerMessage();
void actShutdownServer();
void actUnlock();
void actLock();
public:
TabAdmin(TabSupervisor *_tabSupervisor, AbstractClient *_client, QWidget *parent = 0);
TabAdmin(TabSupervisor *_tabSupervisor, AbstractClient *_client, bool _fullAdmin, QWidget *parent = 0);
void retranslateUi();
QString getTabText() const { return tr("Administration"); }
bool getLocked() const { return locked; }

View file

@ -1,11 +1,10 @@
#include <QLabel>
#include <QHBoxLayout>
#include <QSplitter>
#include <QMenu>
#include <QAction>
#include <QMessageBox>
#include <QFileDialog>
#include <QApplication>
#include <QDesktopWidget>
#include "tab_game.h"
#include "cardinfowidget.h"
#include "playerlistwidget.h"
@ -159,8 +158,8 @@ void DeckViewContainer::setDeck(DeckList *deck)
readyStartButton->setEnabled(true);
}
TabGame::TabGame(TabSupervisor *_tabSupervisor, QList<AbstractClient *> &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming)
: Tab(_tabSupervisor), clients(_clients), gameId(_gameId), gameDescription(_gameDescription), localPlayerId(_localPlayerId), spectator(_spectator), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), started(false), resuming(_resuming), currentPhase(-1), infoPopup(0)
TabGame::TabGame(TabSupervisor *_tabSupervisor, QList<AbstractClient *> &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, ServerInfo_User *_userInfo, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming)
: Tab(_tabSupervisor), clients(_clients), gameId(_gameId), gameDescription(_gameDescription), localPlayerId(_localPlayerId), spectator(_spectator), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), started(false), resuming(_resuming), currentPhase(-1)
{
phasesToolbar = new PhasesToolbar;
phasesToolbar->hide();
@ -177,10 +176,10 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, QList<AbstractClient *> &_client
timeElapsedLabel = new QLabel;
timeElapsedLabel->setAlignment(Qt::AlignCenter);
messageLog = new MessageLogWidget;
messageLog = new MessageLogWidget(_userInfo->getName(), _userInfo->getGender() == ServerInfo_User::Female);
connect(messageLog, SIGNAL(cardNameHovered(QString)), cardInfo, SLOT(setCard(QString)));
connect(messageLog, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString)));
connect(messageLog, SIGNAL(deleteCardInfoPopup()), this, SLOT(deleteCardInfoPopup()));
connect(messageLog, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString)));
sayLabel = new QLabel;
sayEdit = new QLineEdit;
sayLabel->setBuddy(sayEdit);
@ -191,17 +190,23 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, QList<AbstractClient *> &_client
deckViewContainerLayout = new QVBoxLayout;
QVBoxLayout *verticalLayout = new QVBoxLayout;
verticalLayout->addWidget(cardInfo);
verticalLayout->addWidget(playerListWidget, 1);
verticalLayout->addWidget(timeElapsedLabel);
verticalLayout->addWidget(messageLog, 5);
verticalLayout->addLayout(hLayout);
QVBoxLayout *messageLogLayout = new QVBoxLayout;
messageLogLayout->addWidget(timeElapsedLabel);
messageLogLayout->addWidget(messageLog);
messageLogLayout->addLayout(hLayout);
QWidget *messageLogLayoutWidget = new QWidget;
messageLogLayoutWidget->setLayout(messageLogLayout);
splitter = new QSplitter(Qt::Vertical);
splitter->addWidget(cardInfo);
splitter->addWidget(playerListWidget);
splitter->addWidget(messageLogLayoutWidget);
mainLayout = new QHBoxLayout;
mainLayout->addWidget(gameView, 10);
mainLayout->addLayout(deckViewContainerLayout, 10);
mainLayout->addLayout(verticalLayout);
mainLayout->addWidget(splitter);
if (spectator && !spectatorsCanTalk) {
sayLabel->hide();
@ -253,12 +258,16 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, QList<AbstractClient *> &_client
retranslateUi();
setLayout(mainLayout);
splitter->restoreState(settingsCache->getTabGameSplitterSizes());
messageLog->logGameJoined(gameId);
}
TabGame::~TabGame()
{
settingsCache->setTabGameSplitterSizes(splitter->saveState());
QMapIterator<int, Player *> i(players);
while (i.hasNext())
delete i.next().value();
@ -285,6 +294,7 @@ void TabGame::retranslateUi()
aConcede->setText(tr("&Concede"));
aConcede->setShortcut(tr("F2"));
aLeaveGame->setText(tr("&Leave game"));
aLeaveGame->setShortcut(tr("Ctrl+Q"));
sayLabel->setText(tr("&Say:"));
cardInfo->retranslateUi();
@ -299,6 +309,11 @@ void TabGame::retranslateUi()
scene->retranslateUi();
}
void TabGame::closeRequest()
{
actLeaveGame();
}
void TabGame::actConcede()
{
if (QMessageBox::question(this, tr("Concede"), tr("Are you sure you want to concede this game?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes)
@ -309,8 +324,9 @@ void TabGame::actConcede()
void TabGame::actLeaveGame()
{
if (QMessageBox::question(this, tr("Leave game"), tr("Are you sure you want to leave this game?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes)
return;
if (!spectator)
if (QMessageBox::question(this, tr("Leave game"), tr("Are you sure you want to leave this game?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes)
return;
sendGameCommand(new Command_LeaveGame);
deleteLater();
@ -729,7 +745,7 @@ void TabGame::newCardAdded(AbstractCardItem *card)
{
connect(card, SIGNAL(hovered(AbstractCardItem *)), cardInfo, SLOT(setCard(AbstractCardItem *)));
connect(card, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString)));
connect(card, SIGNAL(deleteCardInfoPopup()), this, SLOT(deleteCardInfoPopup()));
connect(card, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString)));
}
CardItem *TabGame::getCard(int playerId, const QString &zoneName, int cardId) const
@ -761,25 +777,3 @@ Player *TabGame::getActiveLocalPlayer() const
return 0;
}
void TabGame::showCardInfoPopup(const QPoint &pos, const QString &cardName)
{
infoPopup = new CardInfoWidget(CardInfoWidget::ModePopUp, 0, Qt::Widget | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint);
connect(infoPopup, SIGNAL(mouseReleased()), this, SLOT(deleteCardInfoPopup()));
infoPopup->setCard(cardName);
QRect screenRect = qApp->desktop()->screenGeometry(this);
infoPopup->move(
qMax(screenRect.left(), qMin(pos.x() - infoPopup->width() / 2, screenRect.left() + screenRect.width() - infoPopup->width())),
qMax(screenRect.top(), qMin(pos.y() - infoPopup->height() / 2, screenRect.top() + screenRect.height() - infoPopup->height()))
);
infoPopup->show();
infoPopup->grabMouse();
}
void TabGame::deleteCardInfoPopup()
{
if (infoPopup) {
infoPopup->deleteLater();
infoPopup = 0;
}
}

View file

@ -12,6 +12,7 @@ class DeckView;
class GameScene;
class CardInfoWidget;
class MessageLogWidget;
class QSplitter;
class QLabel;
class QLineEdit;
class QPushButton;
@ -98,7 +99,7 @@ private:
int currentPhase;
int activePlayer;
CardInfoWidget *infoPopup;
QSplitter *splitter;
CardInfoWidget *cardInfo;
PlayerListWidget *playerListWidget;
QLabel *timeElapsedLabel;
@ -145,8 +146,6 @@ signals:
void openMessageDialog(const QString &userName, bool focus);
private slots:
void newCardAdded(AbstractCardItem *card);
void showCardInfoPopup(const QPoint &pos, const QString &cardName);
void deleteCardInfoPopup();
void actConcede();
void actLeaveGame();
@ -156,9 +155,10 @@ private slots:
void actNextPhase();
void actNextTurn();
public:
TabGame(TabSupervisor *_tabSupervisor, QList<AbstractClient *> &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming);
TabGame(TabSupervisor *_tabSupervisor, QList<AbstractClient *> &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, ServerInfo_User *_userInfo, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming);
~TabGame();
void retranslateUi();
void closeRequest();
const QMap<int, Player *> &getPlayers() const { return players; }
CardItem *getCard(int playerId, const QString &zoneName, int cardId) const;
int getGameId() const { return gameId; }

View file

@ -11,7 +11,9 @@
TabMessage::TabMessage(TabSupervisor *_tabSupervisor, AbstractClient *_client, const QString &_ownName, const QString &_userName)
: Tab(_tabSupervisor), client(_client), userName(_userName), userOnline(true)
{
chatView = new ChatView(_ownName);
chatView = new ChatView(_ownName, true);
connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString)));
connect(chatView, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString)));
sayEdit = new QLineEdit;
connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(sendMessage()));
@ -40,6 +42,11 @@ void TabMessage::retranslateUi()
aLeave->setText(tr("&Leave"));
}
void TabMessage::closeRequest()
{
actLeave();
}
void TabMessage::sendMessage()
{
if (sayEdit->text().isEmpty() || !userOnline)

View file

@ -30,6 +30,7 @@ public:
TabMessage(TabSupervisor *_tabSupervisor, AbstractClient *_client, const QString &_ownName, const QString &_userName);
~TabMessage();
void retranslateUi();
void closeRequest();
QString getUserName() const { return userName; }
QString getTabText() const { return tr("Talking to %1").arg(userName); }

View file

@ -4,126 +4,17 @@
#include <QMenu>
#include <QAction>
#include <QPushButton>
#include <QHeaderView>
#include <QMessageBox>
#include <QCheckBox>
#include <QInputDialog>
#include <QLabel>
#include "dlg_creategame.h"
#include <QSplitter>
#include "tab_supervisor.h"
#include "tab_room.h"
#include "userlist.h"
#include "abstractclient.h"
#include "protocol_items.h"
#include "gamesmodel.h"
#include "chatview.h"
GameSelector::GameSelector(AbstractClient *_client, TabRoom *_room, QWidget *parent)
: QGroupBox(parent), client(_client), room(_room)
{
gameListView = new QTreeView;
gameListModel = new GamesModel(room->getGameTypes(), this);
gameListProxyModel = new GamesProxyModel(this);
gameListProxyModel->setSourceModel(gameListModel);
gameListProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
gameListView->setModel(gameListProxyModel);
gameListView->header()->setResizeMode(0, QHeaderView::ResizeToContents);
gameListView->setSortingEnabled(true);
showFullGamesCheckBox = new QCheckBox;
createButton = new QPushButton;
joinButton = new QPushButton;
spectateButton = new QPushButton;
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addWidget(showFullGamesCheckBox);
buttonLayout->addStretch();
buttonLayout->addWidget(createButton);
buttonLayout->addWidget(joinButton);
buttonLayout->addWidget(spectateButton);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(gameListView);
mainLayout->addLayout(buttonLayout);
retranslateUi();
setLayout(mainLayout);
setMinimumWidth((qreal) (gameListView->columnWidth(0) * gameListModel->columnCount()) / 1.5);
setMinimumHeight(400);
connect(showFullGamesCheckBox, SIGNAL(stateChanged(int)), this, SLOT(showFullGamesChanged(int)));
connect(createButton, SIGNAL(clicked()), this, SLOT(actCreate()));
connect(joinButton, SIGNAL(clicked()), this, SLOT(actJoin()));
connect(spectateButton, SIGNAL(clicked()), this, SLOT(actJoin()));
}
void GameSelector::showFullGamesChanged(int state)
{
gameListProxyModel->setFullGamesVisible(state);
}
void GameSelector::actCreate()
{
DlgCreateGame dlg(client, room->getRoomId(), room->getGameTypes(), this);
dlg.exec();
}
void GameSelector::checkResponse(ResponseCode response)
{
createButton->setEnabled(true);
joinButton->setEnabled(true);
spectateButton->setEnabled(true);
switch (response) {
case RespWrongPassword: QMessageBox::critical(this, tr("Error"), tr("Wrong password.")); break;
case RespSpectatorsNotAllowed: QMessageBox::critical(this, tr("Error"), tr("Spectators are not allowed in this game.")); break;
case RespGameFull: QMessageBox::critical(this, tr("Error"), tr("The game is already full.")); break;
case RespNameNotFound: QMessageBox::critical(this, tr("Error"), tr("The game does not exist any more.")); break;
case RespUserLevelTooLow: QMessageBox::critical(this, tr("Error"), tr("This game is only open to registered users.")); break;
case RespOnlyBuddies: QMessageBox::critical(this, tr("Error"), tr("This game is only open to its creator's buddies.")); break;
case RespInIgnoreList: QMessageBox::critical(this, tr("Error"), tr("You are being ignored by the creator of this game.")); break;
default: ;
}
}
void GameSelector::actJoin()
{
bool spectator = sender() == spectateButton;
QModelIndex ind = gameListView->currentIndex();
if (!ind.isValid())
return;
ServerInfo_Game *game = gameListModel->getGame(ind.data(Qt::UserRole).toInt());
QString password;
if (game->getHasPassword() && !(spectator && !game->getSpectatorsNeedPassword())) {
bool ok;
password = QInputDialog::getText(this, tr("Join game"), tr("Password:"), QLineEdit::Password, QString(), &ok);
if (!ok)
return;
}
Command_JoinGame *commandJoinGame = new Command_JoinGame(room->getRoomId(), game->getGameId(), password, spectator);
connect(commandJoinGame, SIGNAL(finished(ResponseCode)), this, SLOT(checkResponse(ResponseCode)));
client->sendCommand(commandJoinGame);
createButton->setEnabled(false);
joinButton->setEnabled(false);
spectateButton->setEnabled(false);
}
void GameSelector::retranslateUi()
{
setTitle(tr("Games"));
showFullGamesCheckBox->setText(tr("Show &full games"));
createButton->setText(tr("C&reate"));
joinButton->setText(tr("&Join"));
spectateButton->setText(tr("J&oin as spectator"));
}
void GameSelector::processGameInfo(ServerInfo_Game *info)
{
gameListModel->updateGameList(info);
}
#include "gameselector.h"
TabRoom::TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, const QString &_ownName, ServerInfo_Room *info)
: Tab(_tabSupervisor), client(_client), roomId(info->getRoomId()), roomName(info->getName()), ownName(_ownName)
@ -132,11 +23,15 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, const Q
for (int i = 0; i < gameTypeList.size(); ++i)
gameTypes.insert(gameTypeList[i]->getGameTypeId(), gameTypeList[i]->getDescription());
gameSelector = new GameSelector(client, this);
QMap<int, GameTypeMap> tempMap;
tempMap.insert(info->getRoomId(), gameTypes);
gameSelector = new GameSelector(client, this, QMap<int, QString>(), tempMap);
userList = new UserList(tabSupervisor, client, UserList::RoomList);
connect(userList, SIGNAL(openMessageDialog(const QString &, bool)), this, SIGNAL(openMessageDialog(const QString &, bool)));
chatView = new ChatView(ownName);
chatView = new ChatView(ownName, true);
connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString)));
connect(chatView, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString)));
sayLabel = new QLabel;
sayEdit = new QLineEdit;
sayLabel->setBuddy(sayEdit);
@ -153,12 +48,12 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, const Q
chatGroupBox = new QGroupBox;
chatGroupBox->setLayout(chatVbox);
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(gameSelector);
vbox->addWidget(chatGroupBox);
QSplitter *splitter = new QSplitter(Qt::Vertical);
splitter->addWidget(gameSelector);
splitter->addWidget(chatGroupBox);
QHBoxLayout *hbox = new QHBoxLayout;
hbox->addLayout(vbox, 3);
hbox->addWidget(splitter, 3);
hbox->addWidget(userList, 1);
aLeaveRoom = new QAction(this);
@ -193,6 +88,11 @@ void TabRoom::retranslateUi()
aLeaveRoom->setText(tr("&Leave room"));
}
void TabRoom::closeRequest()
{
actLeaveRoom();
}
QString TabRoom::sanitizeHtml(QString dirty) const
{
return dirty
@ -256,5 +156,5 @@ void TabRoom::processLeaveRoomEvent(Event_LeaveRoom *event)
void TabRoom::processSayEvent(Event_RoomSay *event)
{
chatView->appendMessage(event->getPlayerName(), event->getMessage());
emit userEvent();
emit userEvent(false);
}

View file

@ -2,20 +2,16 @@
#define TAB_ROOM_H
#include "tab.h"
#include "protocol_datastructures.h"
#include <QGroupBox>
#include <QMap>
class AbstractClient;
class UserList;
class QLabel;
class ChatView;
class QLineEdit;
class QTreeView;
class QPushButton;
class QTextTable;
class QCheckBox;
class GamesModel;
class GamesProxyModel;
class RoomEvent;
class ServerInfo_Room;
class ServerInfo_Game;
@ -24,31 +20,7 @@ class Event_JoinRoom;
class Event_LeaveRoom;
class Event_RoomSay;
class ProtocolResponse;
class TabRoom;
class GameSelector : public QGroupBox {
Q_OBJECT
private slots:
void showFullGamesChanged(int state);
void actCreate();
void actJoin();
void checkResponse(ResponseCode response);
signals:
void gameJoined(int gameId);
private:
AbstractClient *client;
TabRoom *room;
QTreeView *gameListView;
GamesModel *gameListModel;
GamesProxyModel *gameListProxyModel;
QPushButton *createButton, *joinButton, *spectateButton;
QCheckBox *showFullGamesCheckBox;
public:
GameSelector(AbstractClient *_client, TabRoom *_room, QWidget *parent = 0);
void retranslateUi();
void processGameInfo(ServerInfo_Game *info);
};
class GameSelector;
class TabRoom : public Tab {
Q_OBJECT
@ -84,6 +56,7 @@ public:
TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, const QString &_ownName, ServerInfo_Room *info);
~TabRoom();
void retranslateUi();
void closeRequest();
void processRoomEvent(RoomEvent *event);
int getRoomId() const { return roomId; }
const QMap<int, QString> &getGameTypes() const { return gameTypes; }

View file

@ -11,8 +11,60 @@
#include "protocol_items.h"
#include "pixmapgenerator.h"
#include <QDebug>
#include <QPainter>
TabSupervisor:: TabSupervisor(QWidget *parent)
CloseButton::CloseButton(QWidget *parent)
: QAbstractButton(parent)
{
setFocusPolicy(Qt::NoFocus);
setCursor(Qt::ArrowCursor);
resize(sizeHint());
}
QSize CloseButton::sizeHint() const
{
ensurePolished();
int width = style()->pixelMetric(QStyle::PM_TabCloseIndicatorWidth, 0, this);
int height = style()->pixelMetric(QStyle::PM_TabCloseIndicatorHeight, 0, this);
return QSize(width, height);
}
void CloseButton::enterEvent(QEvent *event)
{
update();
QAbstractButton::enterEvent(event);
}
void CloseButton::leaveEvent(QEvent *event)
{
update();
QAbstractButton::leaveEvent(event);
}
void CloseButton::paintEvent(QPaintEvent * /*event*/)
{
QPainter p(this);
QStyleOption opt;
opt.init(this);
opt.state |= QStyle::State_AutoRaise;
if (isEnabled() && underMouse() && !isChecked() && !isDown())
opt.state |= QStyle::State_Raised;
if (isChecked())
opt.state |= QStyle::State_On;
if (isDown())
opt.state |= QStyle::State_Sunken;
if (const QTabBar *tb = qobject_cast<const QTabBar *>(parent())) {
int index = tb->currentIndex();
QTabBar::ButtonPosition position = (QTabBar::ButtonPosition) style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, 0, tb);
if (tb->tabButton(index, position) == this)
opt.state |= QStyle::State_Selected;
}
style()->drawPrimitive(QStyle::PE_IndicatorTabClose, &opt, &p, this);
}
TabSupervisor::TabSupervisor(QWidget *parent)
: QTabWidget(parent), client(0), tabServer(0), tabDeckStorage(0), tabAdmin(0)
{
tabChangedIcon = new QIcon(":/resources/icon_tab_changed.svg");
@ -47,17 +99,16 @@ void TabSupervisor::retranslateUi()
}
}
void TabSupervisor::myAddTab(Tab *tab)
int TabSupervisor::myAddTab(Tab *tab)
{
connect(tab, SIGNAL(userEvent()), this, SLOT(tabUserEvent()));
addTab(tab, tab->getTabText());
connect(tab, SIGNAL(userEvent(bool)), this, SLOT(tabUserEvent(bool)));
return addTab(tab, tab->getTabText());
}
void TabSupervisor::start(AbstractClient *_client, ServerInfo_User *userInfo)
void TabSupervisor::start(AbstractClient *_client, ServerInfo_User *_userInfo)
{
client = _client;
userName = userInfo->getName();
userLevel = userInfo->getUserLevel();
userInfo = new ServerInfo_User(_userInfo);
connect(client, SIGNAL(roomEventReceived(RoomEvent *)), this, SLOT(processRoomEvent(RoomEvent *)));
connect(client, SIGNAL(gameEventContainerReceived(GameEventContainer *)), this, SLOT(processGameEventContainer(GameEventContainer *)));
@ -83,8 +134,8 @@ void TabSupervisor::start(AbstractClient *_client, ServerInfo_User *userInfo)
} else
tabDeckStorage = 0;
if (userInfo->getUserLevel() & ServerInfo_User::IsAdmin) {
tabAdmin = new TabAdmin(this, client);
if (userInfo->getUserLevel() & ServerInfo_User::IsModerator) {
tabAdmin = new TabAdmin(this, client, (userInfo->getUserLevel() & ServerInfo_User::IsAdmin));
myAddTab(tabAdmin);
} else
tabAdmin = 0;
@ -94,6 +145,7 @@ void TabSupervisor::start(AbstractClient *_client, ServerInfo_User *userInfo)
void TabSupervisor::startLocal(const QList<AbstractClient *> &_clients)
{
userInfo = new ServerInfo_User;
localClients = _clients;
for (int i = 0; i < localClients.size(); ++i)
connect(localClients[i], SIGNAL(gameEventContainerReceived(GameEventContainer *)), this, SLOT(processGameEventContainer(GameEventContainer *)));
@ -140,6 +192,9 @@ void TabSupervisor::stop()
while (messageIterator.hasNext())
messageIterator.next().value()->deleteLater();
messageTabs.clear();
delete userInfo;
userInfo = 0;
}
void TabSupervisor::updatePingTime(int value, int max)
@ -152,21 +207,38 @@ void TabSupervisor::updatePingTime(int value, int max)
setTabIcon(0, QIcon(PingPixmapGenerator::generatePixmap(15, value, max)));
}
void TabSupervisor::closeButtonPressed()
{
Tab *tab = static_cast<Tab *>(static_cast<CloseButton *>(sender())->property("tab").value<QObject *>());
tab->closeRequest();
}
void TabSupervisor::addCloseButtonToTab(Tab *tab, int tabIndex)
{
QTabBar::ButtonPosition closeSide = (QTabBar::ButtonPosition) tabBar()->style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, 0, tabBar());
CloseButton *closeButton = new CloseButton;
connect(closeButton, SIGNAL(clicked()), this, SLOT(closeButtonPressed()));
closeButton->setProperty("tab", qVariantFromValue((QObject *) tab));
tabBar()->setTabButton(tabIndex, closeSide, closeButton);
}
void TabSupervisor::gameJoined(Event_GameJoined *event)
{
TabGame *tab = new TabGame(this, QList<AbstractClient *>() << client, event->getGameId(), event->getGameDescription(), event->getPlayerId(), event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming());
TabGame *tab = new TabGame(this, QList<AbstractClient *>() << client, event->getGameId(), event->getGameDescription(), event->getPlayerId(), userInfo, event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming());
connect(tab, SIGNAL(gameClosing(TabGame *)), this, SLOT(gameLeft(TabGame *)));
connect(tab, SIGNAL(openMessageDialog(const QString &, bool)), this, SLOT(addMessageTab(const QString &, bool)));
myAddTab(tab);
int tabIndex = myAddTab(tab);
addCloseButtonToTab(tab, tabIndex);
gameTabs.insert(event->getGameId(), tab);
setCurrentWidget(tab);
}
void TabSupervisor::localGameJoined(Event_GameJoined *event)
{
TabGame *tab = new TabGame(this, localClients, event->getGameId(), event->getGameDescription(), event->getPlayerId(), event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming());
TabGame *tab = new TabGame(this, localClients, event->getGameId(), event->getGameDescription(), event->getPlayerId(), userInfo, event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming());
connect(tab, SIGNAL(gameClosing(TabGame *)), this, SLOT(gameLeft(TabGame *)));
myAddTab(tab);
int tabIndex = myAddTab(tab);
addCloseButtonToTab(tab, tabIndex);
gameTabs.insert(event->getGameId(), tab);
setCurrentWidget(tab);
@ -189,10 +261,11 @@ void TabSupervisor::gameLeft(TabGame *tab)
void TabSupervisor::addRoomTab(ServerInfo_Room *info, bool setCurrent)
{
TabRoom *tab = new TabRoom(this, client, userName, info);
TabRoom *tab = new TabRoom(this, client, userInfo->getName(), 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);
int tabIndex = myAddTab(tab);
addCloseButtonToTab(tab, tabIndex);
roomTabs.insert(info->getRoomId(), tab);
if (setCurrent)
setCurrentWidget(tab);
@ -208,12 +281,13 @@ void TabSupervisor::roomLeft(TabRoom *tab)
TabMessage *TabSupervisor::addMessageTab(const QString &receiverName, bool focus)
{
if (receiverName == userName)
if (receiverName == userInfo->getName())
return 0;
TabMessage *tab = new TabMessage(this, client, userName, receiverName);
TabMessage *tab = new TabMessage(this, client, userInfo->getName(), receiverName);
connect(tab, SIGNAL(talkClosing(TabMessage *)), this, SLOT(talkLeft(TabMessage *)));
myAddTab(tab);
int tabIndex = myAddTab(tab);
addCloseButtonToTab(tab, tabIndex);
messageTabs.insert(receiverName, tab);
if (focus)
setCurrentWidget(tab);
@ -228,14 +302,15 @@ void TabSupervisor::talkLeft(TabMessage *tab)
removeTab(indexOf(tab));
}
void TabSupervisor::tabUserEvent()
void TabSupervisor::tabUserEvent(bool globalEvent)
{
Tab *tab = static_cast<Tab *>(sender());
if (tab != currentWidget()) {
tab->setContentsChanged(true);
setTabIcon(indexOf(tab), *tabChangedIcon);
}
QApplication::alert(this);
if (globalEvent)
QApplication::alert(this);
}
void TabSupervisor::processRoomEvent(RoomEvent *event)
@ -300,3 +375,8 @@ bool TabSupervisor::getAdminLocked() const
return true;
return tabAdmin->getLocked();
}
int TabSupervisor::getUserLevel() const
{
return userInfo->getUserLevel();
}

View file

@ -3,6 +3,7 @@
#include <QTabWidget>
#include <QMap>
#include <QAbstractButton>
class QMenu;
class AbstractClient;
@ -21,11 +22,22 @@ class Event_Message;
class ServerInfo_Room;
class ServerInfo_User;
class CloseButton : public QAbstractButton {
Q_OBJECT
public:
CloseButton(QWidget *parent = 0);
QSize sizeHint() const;
inline QSize minimumSizeHint() const { return sizeHint(); }
protected:
void enterEvent(QEvent *event);
void leaveEvent(QEvent *event);
void paintEvent(QPaintEvent *event);
};
class TabSupervisor : public QTabWidget {
Q_OBJECT
private:
QString userName;
int userLevel;
ServerInfo_User *userInfo;
QIcon *tabChangedIcon;
AbstractClient *client;
QList<AbstractClient *> localClients;
@ -36,7 +48,8 @@ private:
QMap<int, TabRoom *> roomTabs;
QMap<int, TabGame *> gameTabs;
QMap<QString, TabMessage *> messageTabs;
void myAddTab(Tab *tab);
int myAddTab(Tab *tab);
void addCloseButtonToTab(Tab *tab, int tabIndex);
public:
TabSupervisor(QWidget *parent = 0);
~TabSupervisor();
@ -47,11 +60,12 @@ public:
int getGameCount() const { return gameTabs.size(); }
TabUserLists *getUserListsTab() const { return tabUserLists; }
bool getAdminLocked() const;
int getUserLevel() const { return userLevel; }
int getUserLevel() const;
signals:
void setMenu(QMenu *menu);
void localGameEnded();
private slots:
void closeButtonPressed();
void updateCurrent(int index);
void updatePingTime(int value, int max);
void gameJoined(Event_GameJoined *event);
@ -63,7 +77,7 @@ private slots:
void processUserLeft(const QString &userName);
void processUserJoined(const QString &userName);
void talkLeft(TabMessage *tab);
void tabUserEvent();
void tabUserEvent(bool globalEvent);
void processRoomEvent(RoomEvent *event);
void processGameEventContainer(GameEventContainer *cont);
void processMessageEvent(Event_Message *event);

View file

@ -17,6 +17,8 @@ UserInfoBox::UserInfoBox(AbstractClient *_client, bool _fullInfo, QWidget *paren
nameLabel->setFont(nameFont);
realNameLabel1 = new QLabel;
realNameLabel2 = new QLabel;
genderLabel1 = new QLabel;
genderLabel2 = new QLabel;
countryLabel1 = new QLabel;
countryLabel2 = new QLabel;
userLevelLabel1 = new QLabel;
@ -28,11 +30,13 @@ UserInfoBox::UserInfoBox(AbstractClient *_client, bool _fullInfo, QWidget *paren
mainLayout->addWidget(nameLabel, 1, 0, 1, 3);
mainLayout->addWidget(realNameLabel1, 2, 0, 1, 1);
mainLayout->addWidget(realNameLabel2, 2, 1, 1, 2);
mainLayout->addWidget(countryLabel1, 3, 0, 1, 1);
mainLayout->addWidget(countryLabel2, 3, 1, 1, 2);
mainLayout->addWidget(userLevelLabel1, 4, 0, 1, 1);
mainLayout->addWidget(userLevelLabel2, 4, 1, 1, 1);
mainLayout->addWidget(userLevelLabel3, 4, 2, 1, 1);
mainLayout->addWidget(genderLabel1, 3, 0, 1, 1);
mainLayout->addWidget(genderLabel2, 3, 1, 1, 2);
mainLayout->addWidget(countryLabel1, 4, 0, 1, 1);
mainLayout->addWidget(countryLabel2, 4, 1, 1, 2);
mainLayout->addWidget(userLevelLabel1, 5, 0, 1, 1);
mainLayout->addWidget(userLevelLabel2, 5, 1, 1, 1);
mainLayout->addWidget(userLevelLabel3, 5, 2, 1, 1);
mainLayout->setColumnStretch(2, 10);
setWindowTitle(tr("User information"));
@ -43,6 +47,7 @@ UserInfoBox::UserInfoBox(AbstractClient *_client, bool _fullInfo, QWidget *paren
void UserInfoBox::retranslateUi()
{
realNameLabel1->setText(tr("Real name:"));
genderLabel1->setText(tr("Gender:"));
countryLabel1->setText(tr("Location:"));
userLevelLabel1->setText(tr("User level:"));
}
@ -58,13 +63,14 @@ void UserInfoBox::updateInfo(ServerInfo_User *user)
nameLabel->setText(user->getName());
realNameLabel2->setText(user->getRealName());
genderLabel2->setPixmap(GenderPixmapGenerator::generatePixmap(15, user->getGender()));
countryLabel2->setPixmap(CountryPixmapGenerator::generatePixmap(15, user->getCountry()));
userLevelLabel2->setPixmap(UserLevelPixmapGenerator::generatePixmap(15, userLevel));
QString userLevelText;
if (userLevel & ServerInfo_User::IsAdmin)
userLevelText = tr("Administrator");
else if (userLevel & ServerInfo_User::IsJudge)
userLevelText = tr("Judge");
else if (userLevel & ServerInfo_User::IsModerator)
userLevelText = tr("Moderator");
else if (userLevel & ServerInfo_User::IsRegistered)
userLevelText = tr("Registered user");
else

View file

@ -13,7 +13,7 @@ class UserInfoBox : public QWidget {
private:
AbstractClient *client;
bool fullInfo;
QLabel *avatarLabel, *nameLabel, *realNameLabel1, *realNameLabel2, *countryLabel1, *countryLabel2, *userLevelLabel1, *userLevelLabel2, *userLevelLabel3;
QLabel *avatarLabel, *nameLabel, *realNameLabel1, *realNameLabel2, *genderLabel1, *genderLabel2, *countryLabel1, *countryLabel2, *userLevelLabel1, *userLevelLabel2, *userLevelLabel3;
public:
UserInfoBox(AbstractClient *_client, bool fullInfo, QWidget *parent = 0, Qt::WindowFlags flags = 0);
void retranslateUi();

View file

@ -5,11 +5,59 @@
#include "pixmapgenerator.h"
#include "userinfobox.h"
#include "protocol_items.h"
#include "gameselector.h"
#include <QHeaderView>
#include <QVBoxLayout>
#include <QMouseEvent>
#include <QMenu>
#include <QInputDialog>
#include <QLabel>
#include <QSpinBox>
#include <QPlainTextEdit>
#include <QPushButton>
#include <QHBoxLayout>
BanDialog::BanDialog(QWidget *parent)
: QDialog(parent)
{
QLabel *durationLabel = new QLabel(tr("Please enter the duration of the ban (in minutes).\nEnter 0 for an indefinite ban."));
durationEdit = new QSpinBox;
durationEdit->setMinimum(0);
durationEdit->setValue(5);
QLabel *reasonLabel = new QLabel(tr("Please enter the reason for the ban.\nThis is only saved for moderators and cannot be seen by the banned person."));
reasonEdit = new QPlainTextEdit;
QPushButton *okButton = new QPushButton(tr("&OK"));
okButton->setAutoDefault(true);
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
QPushButton *cancelButton = new QPushButton(tr("&Cancel"));
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch();
buttonLayout->addWidget(okButton);
buttonLayout->addWidget(cancelButton);
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(durationLabel);
vbox->addWidget(durationEdit);
vbox->addWidget(reasonLabel);
vbox->addWidget(reasonEdit);
vbox->addLayout(buttonLayout);
setLayout(vbox);
setWindowTitle(tr("Ban user from server"));
}
int BanDialog::getMinutes() const
{
return durationEdit->value();
}
QString BanDialog::getReason() const
{
return reasonEdit->toPlainText();
}
UserListItemDelegate::UserListItemDelegate(QObject *const parent)
: QStyledItemDelegate(parent)
@ -59,6 +107,7 @@ UserList::UserList(TabSupervisor *_tabSupervisor, AbstractClient *_client, UserL
userTree->setRootIsDecorated(false);
userTree->setIconSize(QSize(20, 12));
userTree->setItemDelegate(itemDelegate);
userTree->setAlternatingRowColors(true);
connect(userTree, SIGNAL(itemActivated(QTreeWidgetItem *, int)), this, SLOT(userClicked(QTreeWidgetItem *, int)));
QVBoxLayout *vbox = new QVBoxLayout;
@ -163,6 +212,35 @@ void UserList::userClicked(QTreeWidgetItem *item, int /*column*/)
emit openMessageDialog(item->data(2, Qt::UserRole).toString(), true);
}
void UserList::gamesOfUserReceived(ProtocolResponse *resp)
{
Command_GetGamesOfUser *command = static_cast<Command_GetGamesOfUser *>(sender());
Response_GetGamesOfUser *response = qobject_cast<Response_GetGamesOfUser *>(resp);
if (!response)
return;
QMap<int, GameTypeMap> gameTypeMap;
QMap<int, QString> roomMap;
const QList<ServerInfo_Room *> roomList = response->getRoomList();
for (int i = 0; i < roomList.size(); ++i) {
roomMap.insert(roomList[i]->getRoomId(), roomList[i]->getName());
const QList<ServerInfo_GameType *> gameTypeList = roomList[i]->getGameTypeList();
GameTypeMap tempMap;
for (int j = 0; j < gameTypeList.size(); ++j)
tempMap.insert(gameTypeList[j]->getGameTypeId(), gameTypeList[j]->getDescription());
gameTypeMap.insert(roomList[i]->getRoomId(), tempMap);
}
GameSelector *selector = new GameSelector(client, 0, roomMap, gameTypeMap);
const QList<ServerInfo_Game *> gameList = response->getGameList();
for (int i = 0; i < gameList.size(); ++i)
selector->processGameInfo(gameList[i]);
selector->setWindowTitle(tr("%1's games").arg(command->getUserName()));
selector->setAttribute(Qt::WA_DeleteOnClose);
selector->show();
}
void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index)
{
const QString &userName = index.sibling(index.row(), 2).data(Qt::UserRole).toString();
@ -172,6 +250,7 @@ void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index)
aUserName->setEnabled(false);
QAction *aDetails = new QAction(tr("User &details"), this);
QAction *aChat = new QAction(tr("Direct &chat"), this);
QAction *aShowGames = new QAction(tr("Show this user's &games"), this);
QAction *aAddToBuddyList = new QAction(tr("Add to &buddy list"), this);
QAction *aRemoveFromBuddyList = new QAction(tr("Remove from &buddy list"), this);
QAction *aAddToIgnoreList = new QAction(tr("Add to &ignore list"), this);
@ -182,6 +261,7 @@ void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index)
menu->addAction(aUserName);
menu->addSeparator();
menu->addAction(aDetails);
menu->addAction(aShowGames);
menu->addAction(aChat);
if ((userLevel & ServerInfo_User::IsRegistered) && (tabSupervisor->getUserLevel() & ServerInfo_User::IsRegistered)) {
menu->addSeparator();
@ -210,14 +290,18 @@ void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index)
client->sendCommand(new Command_AddToList("buddy", userName));
else if (actionClicked == aRemoveFromBuddyList)
client->sendCommand(new Command_RemoveFromList("buddy", userName));
else if (actionClicked == aAddToIgnoreList)
else if (actionClicked == aShowGames) {
Command *cmd = new Command_GetGamesOfUser(userName);
connect(cmd, SIGNAL(finished(ProtocolResponse *)), this, SLOT(gamesOfUserReceived(ProtocolResponse *)));
client->sendCommand(cmd);
} else if (actionClicked == aAddToIgnoreList)
client->sendCommand(new Command_AddToList("ignore", userName));
else if (actionClicked == aRemoveFromIgnoreList)
client->sendCommand(new Command_RemoveFromList("ignore", userName));
else if (actionClicked == aBan) {
bool ok;
int minutes = QInputDialog::getInt(this, tr("Duration"), tr("Please enter the duration of the ban (in minutes).\nEnter 0 for an indefinite ban."), 0, 0, 2147483647, 10, &ok);
client->sendCommand(new Command_BanFromServer(userName, minutes));
BanDialog dlg(this);
if (dlg.exec())
client->sendCommand(new Command_BanFromServer(userName, dlg.getMinutes(), dlg.getReason()));
}
delete menu;

View file

@ -1,6 +1,7 @@
#ifndef USERLIST_H
#define USERLIST_H
#include <QDialog>
#include <QGroupBox>
#include <QTreeWidgetItem>
#include <QStyledItemDelegate>
@ -9,6 +10,20 @@ class QTreeWidget;
class ServerInfo_User;
class AbstractClient;
class TabSupervisor;
class QSpinBox;
class QPlainTextEdit;
class ProtocolResponse;
class BanDialog : public QDialog {
Q_OBJECT
private:
QSpinBox *durationEdit;
QPlainTextEdit *reasonEdit;
public:
BanDialog(QWidget *parent = 0);
int getMinutes() const;
QString getReason() const;
};
class UserListItemDelegate : public QStyledItemDelegate {
public:
@ -38,6 +53,7 @@ private:
void setUserOnline(QTreeWidgetItem *user, bool online);
private slots:
void userClicked(QTreeWidgetItem *item, int column);
void gamesOfUserReceived(ProtocolResponse *resp);
signals:
void openMessageDialog(const QString &userName, bool focus);
void addBuddy(const QString &userName);

View file

@ -26,6 +26,7 @@
#include "dlg_load_deck_from_clipboard.h"
#include "main.h"
#include "settingscache.h"
#include "priceupdater.h"
void SearchLineEdit::keyPressEvent(QKeyEvent *event)
{
@ -68,6 +69,7 @@ WndDeckEditor::WndDeckEditor(QWidget *parent)
databaseView = new QTreeView();
databaseView->setModel(databaseDisplayModel);
databaseView->setUniformRowHeights(true);
databaseView->setRootIsDecorated(false);
databaseView->setAlternatingRowColors(true);
databaseView->setSortingEnabled(true);
databaseView->sortByColumn(0, Qt::AscendingOrder);
@ -112,15 +114,37 @@ WndDeckEditor::WndDeckEditor(QWidget *parent)
commentsEdit->setMaximumHeight(70);
commentsLabel->setBuddy(commentsEdit);
connect(commentsEdit, SIGNAL(textChanged()), this, SLOT(updateComments()));
QGridLayout *grid = new QGridLayout;
grid->addWidget(nameLabel, 0, 0);
grid->addWidget(nameEdit, 0, 1);
grid->addWidget(commentsLabel, 1, 0);
grid->addWidget(commentsEdit, 1, 1);
// Update price
aUpdatePrices = new QAction(tr("&Update prices"), this);
aUpdatePrices->setShortcut(tr("Ctrl+U"));
aUpdatePrices->setIcon(QIcon(":/resources/icon_update.png"));
connect(aUpdatePrices, SIGNAL(triggered()), this, SLOT(actUpdatePrices()));
if (!settingsCache->getPriceTagFeature())
aUpdatePrices->setVisible(false);
QToolBar *deckToolBar = new QToolBar;
deckToolBar->setOrientation(Qt::Vertical);
deckToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
deckToolBar->setIconSize(QSize(24, 24));
deckToolBar->addAction(aUpdatePrices);
QHBoxLayout *deckToolbarLayout = new QHBoxLayout;
deckToolbarLayout->addStretch();
deckToolbarLayout->addWidget(deckToolBar);
deckToolbarLayout->addStretch();
QVBoxLayout *rightFrame = new QVBoxLayout;
rightFrame->addLayout(grid);
rightFrame->addWidget(deckView);
rightFrame->addLayout(deckToolbarLayout);
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addLayout(leftFrame, 10);
@ -456,6 +480,21 @@ void WndDeckEditor::actDecrement()
setWindowModified(true);
}
void WndDeckEditor::actUpdatePrices()
{
aUpdatePrices->setDisabled(true);
PriceUpdater *up = new PriceUpdater(deckModel->getDeckList());
connect(up, SIGNAL(finishedUpdate()), this, SLOT(finishedUpdatingPrices()));
up->updatePrices();
}
void WndDeckEditor::finishedUpdatingPrices()
{
deckModel->pricesUpdated();
setWindowModified(true);
aUpdatePrices->setDisabled(false);
}
void WndDeckEditor::setDeck(DeckList *_deck, const QString &_lastFileName, DeckList::FileFormat _lastFileFormat)
{
deckModel->setDeckList(_deck);

View file

@ -52,6 +52,9 @@ private slots:
void actRemoveCard();
void actIncrement();
void actDecrement();
void actUpdatePrices();
void finishedUpdatingPrices();
private:
void addCardHelper(const QString &zoneName);
void recursiveExpand(const QModelIndex &index);
@ -74,7 +77,7 @@ private:
QMenu *deckMenu, *dbMenu;
QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aPrintDeck, *aClose;
QAction *aEditSets, *aSearch, *aClearSearch;
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement;
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement, *aUpdatePrices;
public:
WndDeckEditor(QWidget *parent = 0);
~WndDeckEditor();

View file

@ -56,11 +56,18 @@ void MainWindow::processConnectionClosedEvent(Event_ConnectionClosed *event)
reasonStr = tr("There are too many concurrent connections from your address.");
else if (reason == "banned")
reasonStr = tr("Banned by moderator.");
else if (reason == "server_shutdown")
reasonStr = tr("Scheduled server shutdown.");
else
reasonStr = tr("Unknown reason.");
QMessageBox::critical(this, tr("Connection closed"), tr("The server has terminated your connection.\nReason: %1").arg(reasonStr));
}
void MainWindow::processServerShutdownEvent(Event_ServerShutdown *event)
{
QMessageBox::information(this, tr("Scheduled server shutdown"), tr("The server is going to be restarted in %n minute(s).\nAll running games will be lost.\nReason for shutdown: %1", "", event->getMinutes()).arg(event->getReason()));
}
void MainWindow::statusChanged(ClientStatus _status)
{
setClientStatusTitle();
@ -178,6 +185,8 @@ void MainWindow::actAbout()
+ tr("French:") + " Yannick Hammer, Arnaud Faes<br>"
+ tr("Japanese:") + " Nagase Task<br>"
+ tr("Russian:") + " Alexander Davidov<br>"
+ tr("Czech:") + " Ondřej Trhoň<br>"
+ tr("Slovak:") + " Ganjalf Rendy<br>"
));
}
@ -288,6 +297,7 @@ MainWindow::MainWindow(QWidget *parent)
client = new RemoteClient(this);
connect(client, SIGNAL(connectionClosedEventReceived(Event_ConnectionClosed *)), this, SLOT(processConnectionClosedEvent(Event_ConnectionClosed *)));
connect(client, SIGNAL(serverShutdownEventReceived(Event_ServerShutdown *)), this, SLOT(processServerShutdownEvent(Event_ServerShutdown *)));
connect(client, SIGNAL(serverError(ResponseCode)), this, SLOT(serverError(ResponseCode)));
connect(client, SIGNAL(socketError(const QString &)), this, SLOT(socketError(const QString &)));
connect(client, SIGNAL(serverTimeout()), this, SLOT(serverTimeout()));

View file

@ -36,6 +36,7 @@ private slots:
void updateTabMenu(QMenu *menu);
void statusChanged(ClientStatus _status);
void processConnectionClosedEvent(Event_ConnectionClosed *event);
void processServerShutdownEvent(Event_ServerShutdown *event);
void serverTimeout();
void serverError(ResponseCode r);
void socketError(const QString &errorStr);