Major Directory Refactoring (#5118)

* refactored cardzone.cpp, added doc and changed if to switch case

* started moving every files into different folders

* remove undercase to match with other files naming convention

* refactored dialog files

* ran format.sh

* refactored client/tabs folder

* refactored client/tabs folder

* refactored client/tabs folder

* refactored client folder

* refactored carddbparser

* refactored dialogs

* Create sonar-project.properties

temporary file for lint

* Create build.yml

temporary file for lint

* removed all files from root directory

* removed all files from root directory

* added current branch to workflow

* fixed most broken import

* fixed issues while renaming files

* fixed oracle importer

* fixed dbconverter

* updated translations

* made sub-folders for client

* removed linter

* removed linter folder

* fixed oracle import

* revert card_zone documentation

* renamed db parser files name and deck_view imports

* fixed dlg file issue

* ran format file and fixed test file

* fixed carddb test files

* moved player folder in game

* updated translations and format files

* fixed peglib import

* format cmake files

* removing vcpkg to try to add it back later

* tried fixing vcpkg file

* renamed filter to filters and moved database parser to cards folder

* reverted translation files

* reverted oracle translated

* Update cockatrice/src/dialogs/dlg_register.cpp

Co-authored-by: tooomm <tooomm@users.noreply.github.com>

* Update cockatrice/src/client/ui/window_main.cpp

Co-authored-by: tooomm <tooomm@users.noreply.github.com>

* removed empty line at file start

* removed useless include from tab_supervisor.cpp

* refactored cardzone.cpp, added doc and changed if to switch case

* started moving every files into different folders

* remove undercase to match with other files naming convention

* refactored dialog files

* ran format.sh

* refactored client/tabs folder

* refactored client folder

* refactored carddbparser

* refactored dialogs

* removed all files from root directory

* Create sonar-project.properties

temporary file for lint

* Create build.yml

temporary file for lint

* added current branch to workflow

* fixed most broken import

* fixed issues while renaming files

* fixed oracle importer

* fixed dbconverter

* updated translations

* made sub-folders for client

* removed linter

* removed linter folder

* fixed oracle import

* revert card_zone documentation

* renamed db parser files name and deck_view imports

* fixed dlg file issue

* ran format file and fixed test file

* fixed carddb test files

* moved player folder in game

* updated translations and format files

* fixed peglib import

* reverted translation files

* format cmake files

* removing vcpkg to try to add it back later

* tried fixing vcpkg file

* pre-updating of cockatrice changes

* removed empty line at file start

* reverted oracle translated

* Update cockatrice/src/dialogs/dlg_register.cpp

Co-authored-by: tooomm <tooomm@users.noreply.github.com>

* Update cockatrice/src/client/ui/window_main.cpp

Co-authored-by: tooomm <tooomm@users.noreply.github.com>

* removed useless include from tab_supervisor.cpp

---------

Co-authored-by: tooomm <tooomm@users.noreply.github.com>
This commit is contained in:
LunaticCat 2024-10-20 16:11:35 +02:00 committed by GitHub
parent d1e0f9dfc5
commit fa999880ee
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
261 changed files with 735 additions and 729 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,494 @@
#ifndef PLAYER_H
#define PLAYER_H
#include "../../client/tearoff_menu.h"
#include "../board/abstract_graphics_item.h"
#include "../cards/card_database.h"
#include "../filters/filter_string.h"
#include "pb/card_attributes.pb.h"
#include "pb/game_event.pb.h"
#include <QInputDialog>
#include <QMap>
#include <QPoint>
#include <QTimer>
namespace google
{
namespace protobuf
{
class Message;
}
} // namespace google
class AbstractCardItem;
class AbstractCounter;
class ArrowItem;
class ArrowTarget;
class CardDatabase;
class CardItem;
class CardZone;
class CommandContainer;
class Command_MoveCard;
class DeckLoader;
class Event_AttachCard;
class Event_ChangeZoneProperties;
class Event_CreateArrow;
class Event_CreateCounter;
class Event_CreateToken;
class Event_DelCounter;
class Event_DeleteArrow;
class Event_DestroyCard;
class Event_DrawCards;
class Event_DumpZone;
class Event_FlipCard;
class Event_GameSay;
class Event_MoveCard;
class Event_RevealCards;
class Event_RollDie;
class Event_SetCardAttr;
class Event_SetCardCounter;
class Event_SetCounter;
class Event_Shuffle;
class GameCommand;
class GameEvent;
class GameEventContext;
class HandZone;
class PendingCommand;
class PlayerTarget;
class QAction;
class QMenu;
class ServerInfo_Arrow;
class ServerInfo_Counter;
class ServerInfo_Player;
class ServerInfo_User;
class StackZone;
class TabGame;
class TableZone;
class ZoneViewZone;
const int MAX_TOKENS_PER_DIALOG = 99;
class PlayerArea : public QObject, public QGraphicsItem
{
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
private:
QRectF bRect;
int playerZoneId;
private slots:
void updateBg();
public:
enum
{
Type = typeOther
};
int type() const override
{
return Type;
}
explicit PlayerArea(QGraphicsItem *parent = nullptr);
QRectF boundingRect() const override
{
return bRect;
}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void setSize(qreal width, qreal height);
void setPlayerZoneId(int _playerZoneId);
int getPlayerZoneId() const
{
return playerZoneId;
}
};
class Player : public QObject, public QGraphicsItem
{
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
signals:
void openDeckEditor(const DeckLoader *deck);
void newCardAdded(AbstractCardItem *card);
// Log events
void logSay(Player *player, QString message);
void logShuffle(Player *player, CardZone *zone, int start, int end);
void logRollDie(Player *player, int sides, const QList<uint> &rolls);
void logCreateArrow(Player *player,
Player *startPlayer,
QString startCard,
Player *targetPlayer,
QString targetCard,
bool _playerTarget);
void logCreateToken(Player *player, QString cardName, QString pt);
void logDrawCards(Player *player, int number, bool deckIsEmpty);
void logUndoDraw(Player *player, QString cardName);
void logMoveCard(Player *player, CardItem *card, CardZone *startZone, int oldX, CardZone *targetZone, int newX);
void logFlipCard(Player *player, QString cardName, bool faceDown);
void logDestroyCard(Player *player, QString cardName);
void logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName);
void logUnattachCard(Player *player, QString cardName);
void logSetCardCounter(Player *player, QString cardName, int counterId, int value, int oldValue);
void logSetTapped(Player *player, CardItem *card, bool tapped);
void logSetCounter(Player *player, QString counterName, int value, int oldValue);
void logSetDoesntUntap(Player *player, CardItem *card, bool doesntUntap);
void logSetPT(Player *player, CardItem *card, QString newPT);
void logSetAnnotation(Player *player, CardItem *card, QString newAnnotation);
void logDumpZone(Player *player, CardZone *zone, int numberCards);
void logRevealCards(Player *player,
CardZone *zone,
int cardId,
QString cardName,
Player *otherPlayer,
bool faceDown,
int amount,
bool isLentToAnotherPlayer = false);
void logAlwaysRevealTopCard(Player *player, CardZone *zone, bool reveal);
void logAlwaysLookAtTopCard(Player *player, CardZone *zone, bool reveal);
void sizeChanged();
void playerCountChanged();
public slots:
void actUntapAll();
void actRollDie();
void actCreateToken();
void actCreateAnotherToken();
void actShuffle();
void actDrawCard();
void actDrawCards();
void actUndoDraw();
void actMulligan();
void actMoveTopCardToPlay();
void actMoveTopCardToPlayFaceDown();
void actMoveTopCardToGrave();
void actMoveTopCardToExile();
void actMoveTopCardsToGrave();
void actMoveTopCardsToExile();
void actMoveTopCardsUntil();
void actMoveTopCardToBottom();
void actDrawBottomCard();
void actDrawBottomCards();
void actMoveBottomCardToPlay();
void actMoveBottomCardToPlayFaceDown();
void actMoveBottomCardToGrave();
void actMoveBottomCardToExile();
void actMoveBottomCardsToGrave();
void actMoveBottomCardsToExile();
void actMoveBottomCardToTop();
void actViewLibrary();
void actViewHand();
void actViewTopCards();
void actAlwaysRevealTopCard();
void actAlwaysLookAtTopCard();
void actViewGraveyard();
void actRevealRandomGraveyardCard();
void actViewRfg();
void actViewSideboard();
void actSayMessage();
private slots:
void addPlayer(Player *player);
void removePlayer(Player *player);
void playerListActionTriggered();
void updateBoundingRect();
void rearrangeZones();
void actOpenDeckInDeckEditor();
void actCreatePredefinedToken();
void actCreateRelatedCard();
void actCreateAllRelatedCards();
void cardMenuAction();
void actMoveCardXCardsFromTop();
void actCardCounterTrigger();
void actAttach();
void actUnattach();
void actDrawArrow();
void actIncPT(int deltaP, int deltaT);
void actResetPT();
void actSetPT();
void actIncP();
void actDecP();
void actIncT();
void actDecT();
void actIncPT();
void actDecPT();
void actFlowP();
void actFlowT();
void actSetAnnotation();
void actPlay();
void actHide();
void actPlayFacedown();
void actReveal(QAction *action);
void refreshShortcuts();
void initSayMenu();
private:
TabGame *game;
QMenu *sbMenu, *countersMenu, *sayMenu, *createPredefinedTokenMenu, *mRevealLibrary, *mLendLibrary, *mRevealTopCard,
*mRevealHand, *mRevealRandomHandCard, *mRevealRandomGraveyardCard;
TearOffMenu *moveGraveMenu, *moveRfgMenu, *graveMenu, *moveHandMenu, *handMenu, *libraryMenu, *topLibraryMenu,
*bottomLibraryMenu, *rfgMenu, *playerMenu;
QList<QMenu *> playerLists;
QList<QMenu *> singlePlayerLists;
QList<QAction *> allPlayersActions;
QList<QPair<QString, int>> playersInfo;
QAction *aMoveHandToTopLibrary, *aMoveHandToBottomLibrary, *aMoveHandToGrave, *aMoveHandToRfg,
*aMoveGraveToTopLibrary, *aMoveGraveToBottomLibrary, *aMoveGraveToHand, *aMoveGraveToRfg, *aMoveRfgToTopLibrary,
*aMoveRfgToBottomLibrary, *aMoveRfgToHand, *aMoveRfgToGrave, *aViewHand, *aViewLibrary, *aViewTopCards,
*aAlwaysRevealTopCard, *aAlwaysLookAtTopCard, *aOpenDeckInDeckEditor, *aMoveTopCardToGraveyard,
*aMoveTopCardToExile, *aMoveTopCardsToGraveyard, *aMoveTopCardsToExile, *aMoveTopCardsUntil,
*aMoveTopCardToBottom, *aViewGraveyard, *aViewRfg, *aViewSideboard, *aDrawCard, *aDrawCards, *aUndoDraw,
*aMulligan, *aShuffle, *aMoveTopToPlay, *aMoveTopToPlayFaceDown, *aUntapAll, *aRollDie, *aCreateToken,
*aCreateAnotherToken, *aCardMenu, *aMoveBottomToPlay, *aMoveBottomToPlayFaceDown, *aMoveBottomCardToTop,
*aMoveBottomCardToGraveyard, *aMoveBottomCardToExile, *aMoveBottomCardsToGraveyard, *aMoveBottomCardsToExile,
*aDrawBottomCard, *aDrawBottomCards;
QList<QAction *> aAddCounter, aSetCounter, aRemoveCounter;
QAction *aPlay, *aPlayFacedown, *aHide, *aTap, *aDoesntUntap, *aAttach, *aUnattach, *aDrawArrow, *aSetPT, *aResetPT,
*aIncP, *aDecP, *aIncT, *aDecT, *aIncPT, *aDecPT, *aFlowP, *aFlowT, *aSetAnnotation, *aFlip, *aPeek, *aClone,
*aMoveToTopLibrary, *aMoveToBottomLibrary, *aMoveToHand, *aMoveToGraveyard, *aMoveToExile,
*aMoveToXfromTopOfLibrary;
bool movingCardsUntil;
QTimer *moveTopCardTimer;
QString previousMovingCardsUntilExpr = {};
FilterString movingCardsUntilFilter;
bool shortcutsActive;
int defaultNumberTopCards = 1;
int defaultNumberTopCardsToPlaceBelow = 1;
int defaultNumberBottomCards = 1;
int defaultNumberDieRoll = 20;
QString lastTokenName, lastTokenColor, lastTokenPT, lastTokenAnnotation;
bool lastTokenDestroy;
int lastTokenTableRow;
ServerInfo_User *userInfo;
int id;
bool active;
bool local;
bool judge;
bool mirrored;
bool handVisible;
bool conceded;
int zoneId;
bool dialogSemaphore;
bool clearCardsToDelete();
QList<CardItem *> cardsToDelete;
DeckLoader *deck;
QStringList predefinedTokens;
PlayerArea *playerArea;
QMap<QString, CardZone *> zones;
StackZone *stack;
TableZone *table;
HandZone *hand;
PlayerTarget *playerTarget;
void setCardAttrHelper(const GameEventContext &context,
CardItem *card,
CardAttribute attribute,
const QString &avalue,
bool allCards);
void addRelatedCardActions(const CardItem *card, QMenu *cardMenu);
void addRelatedCardView(const CardItem *card, QMenu *cardMenu);
void createCard(const CardItem *sourceCard,
const QString &dbCardName,
CardRelation::AttachType attach = CardRelation::DoesNotAttach,
bool persistent = false);
bool createRelatedFromRelation(const CardItem *sourceCard, const CardRelation *cardRelation);
void moveOneCardUntil(const CardInfoPtr card);
void addPlayerToList(QMenu *playerList, Player *player);
static void removePlayerFromList(QMenu *playerList, Player *player);
QRectF bRect;
QMap<int, AbstractCounter *> counters;
QMap<int, ArrowItem *> arrows;
void rearrangeCounters();
void initContextualPlayersMenu(QMenu *menu);
// void eventConnectionStateChanged(const Event_ConnectionStateChanged &event);
void eventGameSay(const Event_GameSay &event);
void eventShuffle(const Event_Shuffle &event);
void eventRollDie(const Event_RollDie &event);
void eventCreateArrow(const Event_CreateArrow &event);
void eventDeleteArrow(const Event_DeleteArrow &event);
void eventCreateToken(const Event_CreateToken &event);
void eventSetCardAttr(const Event_SetCardAttr &event, const GameEventContext &context);
void eventSetCardCounter(const Event_SetCardCounter &event);
void eventCreateCounter(const Event_CreateCounter &event);
void eventSetCounter(const Event_SetCounter &event);
void eventDelCounter(const Event_DelCounter &event);
void eventDumpZone(const Event_DumpZone &event);
void eventMoveCard(const Event_MoveCard &event, const GameEventContext &context);
void eventFlipCard(const Event_FlipCard &event);
void eventDestroyCard(const Event_DestroyCard &event);
void eventAttachCard(const Event_AttachCard &event);
void eventDrawCards(const Event_DrawCards &event);
void eventRevealCards(const Event_RevealCards &event);
void eventChangeZoneProperties(const Event_ChangeZoneProperties &event);
void cmdSetTopCard(Command_MoveCard &cmd);
void cmdSetBottomCard(Command_MoveCard &cmd);
QVariantList parsePT(const QString &pt);
public:
static const int counterAreaWidth = 55;
enum CardMenuActionType
{
cmTap,
cmUntap,
cmDoesntUntap,
cmFlip,
cmPeek,
cmClone,
cmMoveToTopLibrary,
cmMoveToBottomLibrary,
cmMoveToHand,
cmMoveToGraveyard,
cmMoveToExile
};
enum CardsToReveal
{
RANDOM_CARD_FROM_ZONE = -2
};
enum
{
Type = typeOther
};
int type() const override
{
return Type;
}
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void playCard(CardItem *c, bool faceDown, bool tapped);
void addCard(CardItem *c);
void deleteCard(CardItem *c);
void addZone(CardZone *z);
AbstractCounter *addCounter(const ServerInfo_Counter &counter);
AbstractCounter *addCounter(int counterId, const QString &name, QColor color, int radius, int value);
void delCounter(int counterId);
void clearCounters();
ArrowItem *addArrow(const ServerInfo_Arrow &arrow);
ArrowItem *addArrow(int arrowId, CardItem *startCard, ArrowTarget *targetItem, const QColor &color);
void delArrow(int arrowId);
void removeArrow(ArrowItem *arrow);
void clearArrows();
PlayerTarget *getPlayerTarget() const
{
return playerTarget;
}
Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, TabGame *_parent);
~Player() override;
void retranslateUi();
void clear();
TabGame *getGame() const
{
return game;
}
void setDeck(const DeckLoader &_deck);
QMenu *getPlayerMenu() const
{
return playerMenu;
}
int getId() const
{
return id;
}
QString getName() const;
ServerInfo_User *getUserInfo() const
{
return userInfo;
}
bool getLocal() const
{
return local;
}
bool getLocalOrJudge() const
{
return local || judge;
}
bool getJudge() const
{
return judge;
}
bool getMirrored() const
{
return mirrored;
}
int getZoneId() const
{
return zoneId;
}
void setZoneId(int _zoneId);
const QMap<QString, CardZone *> &getZones() const
{
return zones;
}
const QMap<int, ArrowItem *> &getArrows() const
{
return arrows;
}
void setCardMenu(QMenu *menu);
QMenu *getCardMenu() const;
void updateCardMenu(const CardItem *card);
bool getActive() const
{
return active;
}
void setActive(bool _active);
void setShortcutsActive();
void setShortcutsInactive();
void updateZones();
void setConceded(bool _conceded);
bool getConceded() const
{
return conceded;
}
void setGameStarted();
qreal getMinimumWidth() const;
void setMirrored(bool _mirrored);
void processSceneSizeChange(int newPlayerWidth);
void processPlayerInfo(const ServerInfo_Player &info);
void processCardAttachment(const ServerInfo_Player &info);
void processGameEvent(GameEvent::GameEventType type, const GameEvent &event, const GameEventContext &context);
PendingCommand *prepareGameCommand(const ::google::protobuf::Message &cmd);
PendingCommand *prepareGameCommand(const QList<const ::google::protobuf::Message *> &cmdList);
void sendGameCommand(PendingCommand *pend);
void sendGameCommand(const google::protobuf::Message &command);
void setLastToken(CardInfoPtr cardInfo);
};
class AnnotationDialog : public QInputDialog
{
Q_OBJECT
void keyPressEvent(QKeyEvent *e) override;
public:
AnnotationDialog(QWidget *parent) : QInputDialog(parent)
{
}
};
#endif

View file

@ -0,0 +1,227 @@
#include "player_list_widget.h"
#include "../../client/game_logic/abstract_client.h"
#include "../../client/tabs/tab_account.h"
#include "../../client/tabs/tab_game.h"
#include "../../client/tabs/tab_supervisor.h"
#include "../../client/ui/pixel_map_generator.h"
#include "../../server/user/user_context_menu.h"
#include "../../server/user/user_list.h"
#include "pb/command_kick_from_game.pb.h"
#include "pb/serverinfo_playerproperties.pb.h"
#include "pb/session_commands.pb.h"
#include <QAction>
#include <QHeaderView>
#include <QMenu>
#include <QMouseEvent>
PlayerListItemDelegate::PlayerListItemDelegate(QObject *const parent) : QStyledItemDelegate(parent)
{
}
bool PlayerListItemDelegate::editorEvent(QEvent *event,
QAbstractItemModel *model,
const QStyleOptionViewItem &option,
const QModelIndex &index)
{
if ((event->type() == QEvent::MouseButtonPress) && index.isValid()) {
QMouseEvent *const mouseEvent = static_cast<QMouseEvent *>(event);
if (mouseEvent->button() == Qt::RightButton) {
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
static_cast<PlayerListWidget *>(parent())->showContextMenu(mouseEvent->globalPosition().toPoint(), index);
#else
static_cast<PlayerListWidget *>(parent())->showContextMenu(mouseEvent->globalPos(), index);
#endif
return true;
}
}
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
PlayerListTWI::PlayerListTWI() : QTreeWidgetItem(Type)
{
}
bool PlayerListTWI::operator<(const QTreeWidgetItem &other) const
{
// Sort by spectator/player
if (data(1, Qt::UserRole) != other.data(1, Qt::UserRole))
return data(1, Qt::UserRole).toBool();
// Sort by player ID
return data(4, Qt::UserRole + 1).toInt() < other.data(4, Qt::UserRole + 1).toInt();
}
PlayerListWidget::PlayerListWidget(TabSupervisor *_tabSupervisor,
AbstractClient *_client,
TabGame *_game,
QWidget *parent)
: QTreeWidget(parent), tabSupervisor(_tabSupervisor), client(_client), game(_game), gameStarted(false)
{
readyIcon = QPixmap("theme:icons/ready_start");
notReadyIcon = QPixmap("theme:icons/not_ready_start");
concededIcon = QPixmap("theme:icons/conceded");
playerIcon = loadColorAdjustedPixmap("theme:icons/player");
judgeIcon = loadColorAdjustedPixmap("theme:icons/scales");
spectatorIcon = loadColorAdjustedPixmap("theme:icons/spectator");
lockIcon = QPixmap("theme:icons/lock");
if (tabSupervisor) {
itemDelegate = new PlayerListItemDelegate(this);
setItemDelegate(itemDelegate);
userContextMenu = new UserContextMenu(tabSupervisor, this, game);
connect(userContextMenu, SIGNAL(openMessageDialog(QString, bool)), this,
SIGNAL(openMessageDialog(QString, bool)));
} else {
userContextMenu = nullptr;
}
setMinimumHeight(40);
setIconSize(QSize(20, 15));
setColumnCount(6);
setColumnWidth(0, 20);
setColumnWidth(1, 20);
setColumnWidth(2, 20);
setColumnWidth(3, 20);
setColumnWidth(5, 20);
setHeaderHidden(true);
setRootIsDecorated(false);
setUniformRowHeights(true);
setItemsExpandable(false);
retranslateUi();
}
void PlayerListWidget::retranslateUi()
{
}
void PlayerListWidget::addPlayer(const ServerInfo_PlayerProperties &player)
{
QTreeWidgetItem *newPlayer = new PlayerListTWI;
players.insert(player.player_id(), newPlayer);
updatePlayerProperties(player);
addTopLevelItem(newPlayer);
sortItems(1, Qt::AscendingOrder);
resizeColumnToContents(4);
resizeColumnToContents(5);
}
void PlayerListWidget::updatePlayerProperties(const ServerInfo_PlayerProperties &prop, int playerId)
{
if (playerId == -1)
playerId = prop.player_id();
QTreeWidgetItem *player = players.value(playerId, 0);
if (!player)
return;
bool isSpectator = prop.has_spectator() && prop.spectator();
if (prop.has_judge() || prop.has_spectator()) {
if (prop.has_judge() && prop.judge()) {
player->setIcon(1, judgeIcon);
} else if (isSpectator) {
player->setIcon(1, spectatorIcon);
} else {
player->setIcon(1, playerIcon);
}
player->setData(1, Qt::UserRole, !isSpectator);
}
if (!isSpectator) {
if (prop.has_conceded())
player->setData(2, Qt::UserRole, prop.conceded());
if (prop.has_ready_start())
player->setData(2, Qt::UserRole + 1, prop.ready_start());
if (prop.has_conceded() || prop.has_ready_start())
player->setIcon(2, gameStarted ? (prop.conceded() ? concededIcon : QIcon())
: (prop.ready_start() ? readyIcon : notReadyIcon));
}
if (prop.has_user_info()) {
player->setData(3, Qt::UserRole, prop.user_info().user_level());
player->setIcon(
3, QIcon(UserLevelPixmapGenerator::generatePixmap(12, UserLevelFlags(prop.user_info().user_level()), false,
QString::fromStdString(prop.user_info().privlevel()))));
player->setText(4, QString::fromStdString(prop.user_info().name()));
const QString country = QString::fromStdString(prop.user_info().country());
if (!country.isEmpty())
player->setIcon(4, QIcon(CountryPixmapGenerator::generatePixmap(12, country)));
player->setData(4, Qt::UserRole, QString::fromStdString(prop.user_info().name()));
}
if (prop.has_player_id())
player->setData(4, Qt::UserRole + 1, prop.player_id());
if (!isSpectator) {
if (prop.has_deck_hash()) {
player->setText(5, QString::fromStdString(prop.deck_hash()));
}
if (prop.has_sideboard_locked())
player->setIcon(5, prop.sideboard_locked() ? lockIcon : QIcon());
}
if (prop.has_ping_seconds())
player->setIcon(0, QIcon(PingPixmapGenerator::generatePixmap(12, prop.ping_seconds(), 10)));
}
void PlayerListWidget::removePlayer(int playerId)
{
QTreeWidgetItem *player = players.value(playerId, 0);
if (!player)
return;
players.remove(playerId);
delete takeTopLevelItem(indexOfTopLevelItem(player));
}
void PlayerListWidget::setActivePlayer(int playerId)
{
QMapIterator<int, QTreeWidgetItem *> i(players);
while (i.hasNext()) {
i.next();
QTreeWidgetItem *twi = i.value();
if (i.key() == playerId) {
twi->setBackground(4, QColor(150, 255, 150));
twi->setForeground(4, QColor(0, 0, 0));
} else {
twi->setBackground(4, palette().base().color());
twi->setForeground(4, palette().text().color());
}
}
}
void PlayerListWidget::setGameStarted(bool _gameStarted, bool resuming)
{
gameStarted = _gameStarted;
QMapIterator<int, QTreeWidgetItem *> i(players);
while (i.hasNext()) {
QTreeWidgetItem *twi = i.next().value();
bool isPlayer = twi->data(1, Qt::UserRole).toBool();
if (!isPlayer)
continue;
if (gameStarted) {
if (resuming)
twi->setIcon(2, twi->data(2, Qt::UserRole).toBool() ? concededIcon : QIcon());
else {
twi->setData(2, Qt::UserRole, false);
twi->setIcon(2, QIcon());
}
} else {
twi->setIcon(2, notReadyIcon);
}
}
}
void PlayerListWidget::showContextMenu(const QPoint &pos, const QModelIndex &index)
{
if (!userContextMenu)
return;
const QString &userName = index.sibling(index.row(), 4).data(Qt::UserRole).toString();
int playerId = index.sibling(index.row(), 4).data(Qt::UserRole + 1).toInt();
UserLevelFlags userLevel(index.sibling(index.row(), 3).data(Qt::UserRole).toInt());
QString deckHash = index.sibling(index.row(), 5).data().toString();
userContextMenu->showContextMenu(pos, userName, userLevel, true, playerId, deckHash);
}

View file

@ -0,0 +1,56 @@
#ifndef PLAYERLISTWIDGET_H
#define PLAYERLISTWIDGET_H
#include <QIcon>
#include <QMap>
#include <QStyledItemDelegate>
#include <QTreeWidget>
class ServerInfo_PlayerProperties;
class TabSupervisor;
class AbstractClient;
class TabGame;
class UserContextMenu;
class PlayerListItemDelegate : public QStyledItemDelegate
{
public:
PlayerListItemDelegate(QObject *const parent);
bool
editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
};
class PlayerListTWI : public QTreeWidgetItem
{
public:
PlayerListTWI();
bool operator<(const QTreeWidgetItem &other) const;
};
class PlayerListWidget : public QTreeWidget
{
Q_OBJECT
private:
PlayerListItemDelegate *itemDelegate;
QMap<int, QTreeWidgetItem *> players;
TabSupervisor *tabSupervisor;
AbstractClient *client;
TabGame *game;
UserContextMenu *userContextMenu;
QIcon readyIcon, notReadyIcon, concededIcon, playerIcon, judgeIcon, spectatorIcon, lockIcon;
bool gameStarted;
signals:
void openMessageDialog(const QString &userName, bool focus);
public:
PlayerListWidget(TabSupervisor *_tabSupervisor, AbstractClient *_client, TabGame *_game, QWidget *parent = nullptr);
void retranslateUi();
void addPlayer(const ServerInfo_PlayerProperties &player);
void removePlayer(int playerId);
void setActivePlayer(int playerId);
void updatePlayerProperties(const ServerInfo_PlayerProperties &prop, int playerId = -1);
void setGameStarted(bool _gameStarted, bool resuming);
void showContextMenu(const QPoint &pos, const QModelIndex &index);
};
#endif

View file

@ -0,0 +1,169 @@
#include "player_target.h"
#include "../../client/ui/pixel_map_generator.h"
#include "pb/serverinfo_user.pb.h"
#include "player.h"
#include <QDebug>
#include <QPainter>
#include <QPixmapCache>
#include <QtMath>
PlayerCounter::PlayerCounter(Player *_player,
int _id,
const QString &_name,
int _value,
QGraphicsItem *parent,
QWidget *game)
: AbstractCounter(_player, _id, _name, false, _value, false, parent, game)
{
}
QRectF PlayerCounter::boundingRect() const
{
return {0, 0, 50, 30};
}
void PlayerCounter::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
{
const int radius = 8;
const qreal border = 1;
QPainterPath path(QPointF(50 - border / 2, border / 2));
path.lineTo(radius, border / 2);
path.arcTo(border / 2, border / 2, 2 * radius, 2 * radius, 90, 90);
path.lineTo(border / 2, 30 - border / 2);
path.lineTo(50 - border / 2, 30 - border / 2);
path.closeSubpath();
QPen pen(QColor(100, 100, 100));
pen.setWidth(border);
painter->setPen(pen);
painter->setBrush(hovered ? QColor(50, 50, 50, 160) : QColor(0, 0, 0, 160));
painter->drawPath(path);
QRectF translatedRect = path.controlPointRect();
QSize translatedSize = translatedRect.size().toSize();
QFont font("Serif");
font.setWeight(QFont::Bold);
font.setPixelSize(qMax(qRound(translatedSize.height() / 1.3), 9));
painter->setFont(font);
painter->setPen(Qt::white);
painter->drawText(translatedRect, Qt::AlignCenter, QString::number(value));
}
PlayerTarget::PlayerTarget(Player *_owner, QGraphicsItem *parentItem, QWidget *_game)
: ArrowTarget(_owner, parentItem), playerCounter(nullptr), game(_game)
{
setCacheMode(DeviceCoordinateCache);
const std::string &bmp = _owner->getUserInfo()->avatar_bmp();
if (!fullPixmap.loadFromData((const uchar *)bmp.data(), static_cast<uint>(bmp.size()))) {
fullPixmap = QPixmap();
}
}
PlayerTarget::~PlayerTarget()
{
// Explicit deletion is necessary in spite of parent/child relationship
// as we need this object to be alive to receive the destroyed() signal.
delete playerCounter;
}
QRectF PlayerTarget::boundingRect() const
{
return {0, 0, 160, 64};
}
void PlayerTarget::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
{
const ServerInfo_User *const info = owner->getUserInfo();
const qreal border = 2;
QRectF avatarBoundingRect = boundingRect().adjusted(border, border, -border, -border);
QRectF translatedRect = painter->combinedTransform().mapRect(avatarBoundingRect);
QSize translatedSize = translatedRect.size().toSize();
QPixmap cachedPixmap;
const QString cacheKey = "avatar" + QString::number(translatedSize.width()) + "_" +
QString::number(info->user_level()) + "_" + QString::number(fullPixmap.cacheKey());
if (!QPixmapCache::find(cacheKey, &cachedPixmap)) {
cachedPixmap = QPixmap(translatedSize.width(), translatedSize.height());
QPainter tempPainter(&cachedPixmap);
// pow(foo, 0.5) equals to sqrt(foo), but using sqrt(foo) in this context will produce a compile error with
// MSVC++
QRadialGradient grad(translatedRect.center(), qPow(translatedSize.width() * translatedSize.width() +
translatedSize.height() * translatedSize.height(),
0.5) /
2);
grad.setColorAt(1, Qt::black);
grad.setColorAt(0, QColor(180, 180, 180));
tempPainter.fillRect(QRectF(0, 0, translatedSize.width(), translatedSize.height()), grad);
QPixmap tempPixmap;
if (fullPixmap.isNull())
tempPixmap =
UserLevelPixmapGenerator::generatePixmap(translatedSize.height(), UserLevelFlags(info->user_level()),
false, QString::fromStdString(info->privlevel()));
else
tempPixmap = fullPixmap.scaled(translatedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
tempPainter.drawPixmap((translatedSize.width() - tempPixmap.width()) / 2,
(translatedSize.height() - tempPixmap.height()) / 2, tempPixmap);
QPixmapCache::insert(cacheKey, cachedPixmap);
}
painter->save();
resetPainterTransform(painter);
painter->translate((translatedSize.width() - cachedPixmap.width()) / 2.0, 0);
painter->drawPixmap(translatedRect, cachedPixmap, cachedPixmap.rect());
painter->restore();
QRectF nameRect = QRectF(0, boundingRect().height() - 20, 110, 20);
painter->fillRect(nameRect, QColor(0, 0, 0, 160));
QRectF translatedNameRect = painter->combinedTransform().mapRect(nameRect);
painter->save();
resetPainterTransform(painter);
QString name = QString::fromStdString(info->name());
if (name.size() > 13)
name = name.mid(0, 10) + "...";
QFont font;
font.setPixelSize(qMax(qRound(translatedNameRect.height() / 1.5), 9));
painter->setFont(font);
painter->setPen(Qt::white);
painter->drawText(translatedNameRect, Qt::AlignVCenter | Qt::AlignLeft, " " + name);
painter->restore();
QPen pen(QColor(100, 100, 100));
pen.setWidth(border);
pen.setJoinStyle(Qt::RoundJoin);
painter->setPen(pen);
painter->drawRect(boundingRect().adjusted(border / 2, border / 2, -border / 2, -border / 2));
if (getBeingPointedAt())
painter->fillRect(boundingRect(), QBrush(QColor(255, 0, 0, 100)));
}
AbstractCounter *PlayerTarget::addCounter(int _counterId, const QString &_name, int _value)
{
if (playerCounter) {
disconnect(playerCounter, nullptr, this, nullptr);
playerCounter->delCounter();
}
playerCounter = new PlayerCounter(owner, _counterId, _name, _value, this, game);
playerCounter->setPos(boundingRect().width() - playerCounter->boundingRect().width(),
boundingRect().height() - playerCounter->boundingRect().height());
connect(playerCounter, SIGNAL(destroyed()), this, SLOT(counterDeleted()));
return playerCounter;
}
void PlayerTarget::counterDeleted()
{
playerCounter = nullptr;
}

View file

@ -0,0 +1,54 @@
#ifndef PLAYERTARGET_H
#define PLAYERTARGET_H
#include "../board/abstract_counter.h"
#include "../board/arrow_target.h"
#include <QFont>
#include <QPixmap>
class Player;
class PlayerCounter : public AbstractCounter
{
Q_OBJECT
public:
PlayerCounter(Player *_player,
int _id,
const QString &_name,
int _value,
QGraphicsItem *parent = nullptr,
QWidget *game = nullptr);
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
};
class PlayerTarget : public ArrowTarget
{
Q_OBJECT
private:
QPixmap fullPixmap;
PlayerCounter *playerCounter;
QWidget *game;
public slots:
void counterDeleted();
public:
enum
{
Type = typePlayerTarget
};
int type() const
{
return Type;
}
PlayerTarget(Player *_player = nullptr, QGraphicsItem *parentItem = nullptr, QWidget *_game = nullptr);
~PlayerTarget();
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
AbstractCounter *addCounter(int _counterId, const QString &_name, int _value);
};
#endif