diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 6c66fa4b..5f13bf73 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -63,6 +63,7 @@ SET(cockatrice_SOURCES src/chatview.cpp src/userlist.cpp src/userinfobox.cpp + src/user_context_menu.cpp src/remotedecklist_treewidget.cpp src/remotereplaylist_treewidget.cpp src/deckview.cpp @@ -135,6 +136,7 @@ SET(cockatrice_HEADERS src/chatview.h src/userlist.h src/userinfobox.h + src/user_context_menu.h src/remotedecklist_treewidget.h src/remotereplaylist_treewidget.h src/deckview.h diff --git a/cockatrice/src/abstractcarditem.cpp b/cockatrice/src/abstractcarditem.cpp index 204b1d86..724a21fe 100644 --- a/cockatrice/src/abstractcarditem.cpp +++ b/cockatrice/src/abstractcarditem.cpp @@ -25,7 +25,6 @@ AbstractCardItem::AbstractCardItem(const QString &_name, Player *_owner, int _id AbstractCardItem::~AbstractCardItem() { - qDebug() << "AbstractCardItem destructor:" << name; emit deleteCardInfoPopup(name); } diff --git a/cockatrice/src/carddatabase.cpp b/cockatrice/src/carddatabase.cpp index 3b7078a3..115256ba 100644 --- a/cockatrice/src/carddatabase.cpp +++ b/cockatrice/src/carddatabase.cpp @@ -234,6 +234,7 @@ void PictureLoader::setPicDownload(bool _picDownload) CardInfo::CardInfo(CardDatabase *_db, const QString &_name, + bool _isToken, const QString &_manacost, const QString &_cardtype, const QString &_powtough, @@ -248,6 +249,7 @@ CardInfo::CardInfo(CardDatabase *_db, const QMap &_picURLsSt) : db(_db), name(_name), + isToken(_isToken), sets(_sets), manacost(_manacost), cardtype(_cardtype), @@ -426,6 +428,8 @@ QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info) xml.writeTextElement("loyalty", QString::number(info->getLoyalty())); if (info->getCipt()) xml.writeTextElement("cipt", "1"); + if (info->getIsToken()) + xml.writeTextElement("token", "1"); xml.writeEndElement(); // card return xml; @@ -469,7 +473,7 @@ void CardDatabase::clear() delete setIt.value(); } setHash.clear(); - + QHashIterator i(cardHash); while (i.hasNext()) { i.next(); @@ -485,7 +489,7 @@ CardInfo *CardDatabase::getCard(const QString &cardName) else if (cardHash.contains(cardName)) return cardHash.value(cardName); else { - CardInfo *newCard = new CardInfo(this, cardName); + CardInfo *newCard = new CardInfo(this, cardName, true); newCard->addToSet(getSet("TK")); cardHash.insert(cardName, newCard); return newCard; @@ -558,6 +562,7 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml) int tableRow = 0; int loyalty = 0; bool cipt = false; + bool isToken = false; while (!xml.atEnd()) { if (xml.readNext() == QXmlStreamReader::EndElement) break; @@ -588,8 +593,10 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml) cipt = (xml.readElementText() == "1"); else if (xml.name() == "loyalty") loyalty = xml.readElementText().toInt(); + else if (xml.name() == "token") + isToken = xml.readElementText().toInt(); } - cardHash.insert(name, new CardInfo(this, name, manacost, type, pt, text, colors, loyalty, cipt, tableRow, sets, picURLs, picURLsHq, picURLsSt)); + cardHash.insert(name, new CardInfo(this, name, isToken, manacost, type, pt, text, colors, loyalty, cipt, tableRow, sets, picURLs, picURLsHq, picURLsSt)); } } } diff --git a/cockatrice/src/carddatabase.h b/cockatrice/src/carddatabase.h index 719c9ce3..373d1981 100644 --- a/cockatrice/src/carddatabase.h +++ b/cockatrice/src/carddatabase.h @@ -91,6 +91,7 @@ private: CardDatabase *db; QString name; + bool isToken; SetList sets; QString manacost; QString cardtype; @@ -106,6 +107,7 @@ private: public: CardInfo(CardDatabase *_db, const QString &_name = QString(), + bool _isToken = false, const QString &_manacost = QString(), const QString &_cardtype = QString(), const QString &_powtough = QString(), @@ -120,6 +122,7 @@ public: const QStringMap &_picURLsSt = QStringMap()); ~CardInfo(); const QString &getName() const { return name; } + bool getIsToken() const { return isToken; } const SetList &getSets() const { return sets; } const QString &getManaCost() const { return manacost; } const QString &getCardType() const { return cardtype; } diff --git a/cockatrice/src/carddatabasemodel.cpp b/cockatrice/src/carddatabasemodel.cpp index 8e2a556b..eeca8bf3 100644 --- a/cockatrice/src/carddatabasemodel.cpp +++ b/cockatrice/src/carddatabasemodel.cpp @@ -71,7 +71,8 @@ void CardDatabaseModel::updateCardList() } CardDatabaseDisplayModel::CardDatabaseDisplayModel(QObject *parent) - : QSortFilterProxyModel(parent) + : QSortFilterProxyModel(parent), + isToken(ShowAll) { setFilterCaseSensitivity(Qt::CaseInsensitive); setSortCaseSensitivity(Qt::CaseInsensitive); @@ -79,7 +80,10 @@ CardDatabaseDisplayModel::CardDatabaseDisplayModel(QObject *parent) bool CardDatabaseDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex & /*sourceParent*/) const { - CardInfo *info = static_cast(sourceModel())->getCard(sourceRow); + CardInfo const *info = static_cast(sourceModel())->getCard(sourceRow); + + if (((isToken == ShowTrue) && !info->getIsToken()) || (isToken == ShowFalse) && info->getIsToken()) + return false; if (!cardNameBeginning.isEmpty()) if (!info->getName().startsWith(cardNameBeginning, Qt::CaseInsensitive)) @@ -89,6 +93,10 @@ bool CardDatabaseDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex if (!info->getName().contains(cardName, Qt::CaseInsensitive)) return false; + if (!cardNameSet.isEmpty()) + if (!cardNameSet.contains(info->getName())) + return false; + if (!cardText.isEmpty()) if (!info->getText().contains(cardText, Qt::CaseInsensitive)) return false; @@ -96,7 +104,7 @@ bool CardDatabaseDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex if (!cardColors.isEmpty()) if (QSet::fromList(info->getColors()).intersect(cardColors).isEmpty() && !(info->getColors().isEmpty() && cardColors.contains("X"))) return false; - + if (!cardTypes.isEmpty()) if (!cardTypes.contains(info->getMainCardType())) return false; diff --git a/cockatrice/src/carddatabasemodel.h b/cockatrice/src/carddatabasemodel.h index d6404b42..79475f4d 100644 --- a/cockatrice/src/carddatabasemodel.h +++ b/cockatrice/src/carddatabasemodel.h @@ -16,7 +16,7 @@ public: 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; - CardInfo *getCard(int index) const { return cardList[index]; } + CardInfo const *getCard(int index) const { return cardList[index]; } private: QList cardList; CardDatabase *db; @@ -26,13 +26,18 @@ private slots: class CardDatabaseDisplayModel : public QSortFilterProxyModel { Q_OBJECT +public: + enum FilterBool { ShowTrue, ShowFalse, ShowAll }; private: + FilterBool isToken; QString cardNameBeginning, cardName, cardText; - QSet cardTypes, cardColors; + QSet cardNameSet, cardTypes, cardColors; public: CardDatabaseDisplayModel(QObject *parent = 0); + void setIsToken(FilterBool _isToken) { isToken = _isToken; invalidate(); } void setCardNameBeginning(const QString &_beginning) { cardNameBeginning = _beginning; invalidate(); } void setCardName(const QString &_cardName) { cardName = _cardName; invalidate(); } + void setCardNameSet(const QSet &_cardNameSet) { cardNameSet = _cardNameSet; invalidate(); } void setCardText(const QString &_cardText) { cardText = _cardText; invalidate(); } void setCardTypes(const QSet &_cardTypes) { cardTypes = _cardTypes; invalidate(); } void setCardColors(const QSet &_cardColors) { cardColors = _cardColors; invalidate(); } diff --git a/cockatrice/src/chatview.cpp b/cockatrice/src/chatview.cpp index 3694fb0b..65a51fa2 100644 --- a/cockatrice/src/chatview.cpp +++ b/cockatrice/src/chatview.cpp @@ -4,16 +4,29 @@ #include #include #include "chatview.h" +#include "user_level.h" +#include "user_context_menu.h" +#include "tab_supervisor.h" +#include "pixmapgenerator.h" -ChatView::ChatView(const QString &_ownName, bool _showTimestamps, QWidget *parent) - : QTextBrowser(parent), evenNumber(true), ownName(_ownName), showTimestamps(_showTimestamps) +ChatView::ChatView(const TabSupervisor *_tabSupervisor, TabGame *_game, bool _showTimestamps, QWidget *parent) + : QTextBrowser(parent), tabSupervisor(_tabSupervisor), game(_game), evenNumber(true), showTimestamps(_showTimestamps), hoveredItemType(HoveredNothing) { + userContextMenu = new UserContextMenu(tabSupervisor, this, game); + connect(userContextMenu, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool))); + + viewport()->setCursor(Qt::IBeamCursor); setReadOnly(true); setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse); setOpenLinks(false); connect(this, SIGNAL(anchorClicked(const QUrl &)), this, SLOT(openLink(const QUrl &))); } +void ChatView::retranslateUi() +{ + userContextMenu->retranslateUi(); +} + QTextCursor ChatView::prepareBlock(bool same) { lastSender.clear(); @@ -40,7 +53,7 @@ void ChatView::appendHtml(const QString &html) verticalScrollBar()->setValue(verticalScrollBar()->maximum()); } -void ChatView::appendMessage(QString sender, QString message, QColor playerColor, bool playerBold) +void ChatView::appendMessage(QString message, QString sender, UserLevelFlags userLevel, bool playerBold) { bool atBottom = verticalScrollBar()->value() >= verticalScrollBar()->maximum(); bool sameSender = (sender == lastSender) && !lastSender.isEmpty(); @@ -55,18 +68,22 @@ void ChatView::appendMessage(QString sender, QString message, QColor playerColor } QTextCharFormat senderFormat; - if (sender == ownName) { + if (tabSupervisor && (sender == QString::fromStdString(tabSupervisor->getUserInfo()->name()))) { senderFormat.setFontWeight(QFont::Bold); senderFormat.setForeground(Qt::red); } else { - if (playerColor == QColor()) - senderFormat.setForeground(QColor(0, 0, 254)); - else - senderFormat.setForeground(playerColor); + senderFormat.setForeground(Qt::blue); if (playerBold) senderFormat.setFontWeight(QFont::Bold); } + senderFormat.setAnchor(true); + senderFormat.setAnchorHref("user://" + QString::number(userLevel) + "_" + sender); if (!sameSender) { + if (!sender.isEmpty()) { + const int pixelSize = QFontInfo(cursor.charFormat().font()).pixelSize(); + cursor.insertImage(UserLevelPixmapGenerator::generatePixmap(pixelSize, userLevel).toImage(), QString::number(pixelSize) + "_" + QString::number((int) userLevel)); + cursor.insertText(" "); + } cursor.setCharFormat(senderFormat); if (!sender.isEmpty()) sender.append(": "); @@ -88,33 +105,41 @@ void ChatView::appendMessage(QString sender, QString message, QColor playerColor 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); + QString cardName = message.left(closeTagIndex); if (closeTagIndex == -1) message.clear(); else message = message.mid(closeTagIndex + 7); + + QTextCharFormat tempFormat = messageFormat; + tempFormat.setForeground(Qt::blue); + tempFormat.setAnchor(true); + tempFormat.setAnchorHref("card://" + cardName); + + cursor.setCharFormat(tempFormat); + cursor.insertText(cardName); + cursor.setCharFormat(messageFormat); } 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); + + if (!url.contains("://")) + url.prepend("http://"); + + QTextCharFormat tempFormat = messageFormat; + tempFormat.setForeground(Qt::blue); + tempFormat.setAnchor(true); + tempFormat.setAnchorHref(url); + + cursor.setCharFormat(tempFormat); + cursor.insertText(url); + cursor.setCharFormat(messageFormat); } else from = 1; } @@ -148,47 +173,61 @@ QTextFragment ChatView::getFragmentUnderMouse(const QPoint &pos) const 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 + QString anchorHref = getFragmentUnderMouse(event->pos()).charFormat().anchorHref(); + if (!anchorHref.isEmpty()) { + const int delimiterIndex = anchorHref.indexOf("://"); + if (delimiterIndex != -1) { + const QString scheme = anchorHref.left(delimiterIndex); + hoveredContent = anchorHref.mid(delimiterIndex + 3); + if (scheme == "card") { + hoveredItemType = HoveredCard; + emit cardNameHovered(hoveredContent); + } else if (scheme == "user") + hoveredItemType = HoveredUser; + else + hoveredItemType = HoveredUrl; + viewport()->setCursor(Qt::PointingHandCursor); + } else { + hoveredItemType = HoveredNothing; + viewport()->setCursor(Qt::IBeamCursor); + } + } else { + hoveredItemType = HoveredNothing; viewport()->setCursor(Qt::IBeamCursor); - + } + QTextBrowser::mouseMoveEvent(event); } void ChatView::mousePressEvent(QMouseEvent *event) { - if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton)) { - QString cardName = getCardNameUnderMouse(event->pos()); - if (!cardName.isEmpty()) - emit showCardInfoPopup(event->globalPos(), cardName); + switch (hoveredItemType) { + case HoveredCard: { + if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton)) + emit showCardInfoPopup(event->globalPos(), hoveredContent); + break; + } + case HoveredUser: { + if (event->button() == Qt::RightButton) { + const int delimiterIndex = hoveredContent.indexOf("_"); + UserLevelFlags userLevel(hoveredContent.left(delimiterIndex).toInt()); + const QString userName = hoveredContent.mid(delimiterIndex + 1); + + userContextMenu->showContextMenu(event->globalPos(), userName, userLevel); + } + break; + } + default: { + QTextBrowser::mousePressEvent(event); + } } - - QTextBrowser::mousePressEvent(event); } void ChatView::mouseReleaseEvent(QMouseEvent *event) { - if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton)) + if (hoveredItemType == HoveredCard && ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton))) emit deleteCardInfoPopup(QString("_")); QTextBrowser::mouseReleaseEvent(event); @@ -196,5 +235,8 @@ void ChatView::mouseReleaseEvent(QMouseEvent *event) void ChatView::openLink(const QUrl &link) { + if ((link.scheme() == "card") || (link.scheme() == "user")) + return; + QDesktopServices::openUrl(link); } diff --git a/cockatrice/src/chatview.h b/cockatrice/src/chatview.h index 33c583c6..27e80f8c 100644 --- a/cockatrice/src/chatview.h +++ b/cockatrice/src/chatview.h @@ -5,27 +5,36 @@ #include #include #include +#include "user_level.h" class QTextTable; class QMouseEvent; +class UserContextMenu; +class TabSupervisor; +class TabGame; class ChatView : public QTextBrowser { - Q_OBJECT; + Q_OBJECT +protected: + const TabSupervisor * const tabSupervisor; + TabGame * const game; private: + enum HoveredItemType { HoveredNothing, HoveredUrl, HoveredCard, HoveredUser }; + UserContextMenu *userContextMenu; QString lastSender; bool evenNumber; - QString ownName; bool showTimestamps; + HoveredItemType hoveredItemType; + QString hoveredContent; 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, bool _showTimestamps, QWidget *parent = 0); + ChatView(const TabSupervisor *_tabSupervisor, TabGame *_game, bool _showTimestamps, QWidget *parent = 0); + void retranslateUi(); void appendHtml(const QString &html); - void appendMessage(QString sender, QString message, QColor playerColor = QColor(), bool playerBold = false); + void appendMessage(QString message, QString sender = QString(), UserLevelFlags userLevel = UserLevelFlags(), bool playerBold = false); protected: void enterEvent(QEvent *event); void leaveEvent(QEvent *event); @@ -33,6 +42,7 @@ protected: void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); signals: + void openMessageDialog(const QString &userName, bool focus); void cardNameHovered(QString cardName); void showCardInfoPopup(QPoint pos, QString cardName); void deleteCardInfoPopup(QString cardName); diff --git a/cockatrice/src/deckview.cpp b/cockatrice/src/deckview.cpp index 3704bace..5a0fa1fc 100644 --- a/cockatrice/src/deckview.cpp +++ b/cockatrice/src/deckview.cpp @@ -274,6 +274,7 @@ DeckViewScene::DeckViewScene(QObject *parent) DeckViewScene::~DeckViewScene() { clearContents(); + delete deck; } void DeckViewScene::clearContents() diff --git a/cockatrice/src/dlg_create_token.cpp b/cockatrice/src/dlg_create_token.cpp index 8bc9d7e1..62ec4076 100644 --- a/cockatrice/src/dlg_create_token.cpp +++ b/cockatrice/src/dlg_create_token.cpp @@ -6,10 +6,17 @@ #include #include #include +#include +#include +#include +#include +#include "decklist.h" #include "dlg_create_token.h" +#include "carddatabasemodel.h" +#include "main.h" -DlgCreateToken::DlgCreateToken(QWidget *parent) - : QDialog(parent) +DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *parent) + : QDialog(parent), predefinedTokens(_predefinedTokens) { nameLabel = new QLabel(tr("&Name:")); nameEdit = new QLineEdit(tr("Token")); @@ -24,7 +31,7 @@ DlgCreateToken::DlgCreateToken(QWidget *parent) colorEdit->addItem(tr("red"), "r"); colorEdit->addItem(tr("green"), "g"); colorEdit->addItem(tr("multicolor"), "m"); - colorEdit->addItem(tr("colorless"), ""); + colorEdit->addItem(tr("colorless"), QString()); colorLabel->setBuddy(colorEdit); ptLabel = new QLabel(tr("&P/T:")); @@ -49,12 +56,62 @@ DlgCreateToken::DlgCreateToken(QWidget *parent) grid->addWidget(annotationEdit, 3, 1); grid->addWidget(destroyCheckBox, 4, 0, 1, 2); + QGroupBox *tokenDataGroupBox = new QGroupBox(tr("Token data")); + tokenDataGroupBox->setLayout(grid); + + cardDatabaseModel = new CardDatabaseModel(db, this); + cardDatabaseDisplayModel = new CardDatabaseDisplayModel(this); + cardDatabaseDisplayModel->setSourceModel(cardDatabaseModel); + cardDatabaseDisplayModel->setIsToken(CardDatabaseDisplayModel::ShowTrue); + + chooseTokenFromAllRadioButton = new QRadioButton(tr("Show &all tokens")); + connect(chooseTokenFromAllRadioButton, SIGNAL(toggled(bool)), this, SLOT(actChooseTokenFromAll(bool))); + chooseTokenFromDeckRadioButton = new QRadioButton(tr("Show tokens from this &deck")); + connect(chooseTokenFromDeckRadioButton, SIGNAL(toggled(bool)), this, SLOT(actChooseTokenFromDeck(bool))); + QTreeView *chooseTokenView = new QTreeView; + chooseTokenView->setModel(cardDatabaseDisplayModel); + chooseTokenView->setUniformRowHeights(true); + chooseTokenView->setRootIsDecorated(false); + chooseTokenView->setAlternatingRowColors(true); + chooseTokenView->setSortingEnabled(true); + chooseTokenView->sortByColumn(0, Qt::AscendingOrder); + chooseTokenView->resizeColumnToContents(0); + chooseTokenView->header()->setStretchLastSection(false); + chooseTokenView->header()->hideSection(1); + chooseTokenView->header()->hideSection(2); + chooseTokenView->header()->setResizeMode(3, QHeaderView::ResizeToContents); + chooseTokenView->header()->setResizeMode(4, QHeaderView::ResizeToContents); + connect(chooseTokenView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex, QModelIndex)), this, SLOT(tokenSelectionChanged(QModelIndex, QModelIndex))); + + if (predefinedTokens.isEmpty()) + chooseTokenFromAllRadioButton->setChecked(true); + else { + chooseTokenFromDeckRadioButton->setChecked(true); + cardDatabaseDisplayModel->setCardNameSet(QSet::fromList(predefinedTokens)); + } + + QVBoxLayout *tokenChooseLayout = new QVBoxLayout; + tokenChooseLayout->addWidget(chooseTokenFromAllRadioButton); + tokenChooseLayout->addWidget(chooseTokenFromDeckRadioButton); + tokenChooseLayout->addWidget(chooseTokenView); + + QGroupBox *tokenChooseGroupBox = new QGroupBox(tr("Choose token from list")); + tokenChooseGroupBox->setLayout(tokenChooseLayout); + + QVBoxLayout *leftVBox = new QVBoxLayout; + leftVBox->addWidget(tokenDataGroupBox); + leftVBox->addStretch(); + + QHBoxLayout *hbox = new QHBoxLayout; + hbox->addLayout(leftVBox); + hbox->addWidget(tokenChooseGroupBox); + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOk())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addLayout(grid); + mainLayout->addLayout(hbox); mainLayout->addWidget(buttonBox); setLayout(mainLayout); @@ -63,6 +120,30 @@ DlgCreateToken::DlgCreateToken(QWidget *parent) setMinimumWidth(300); } +void DlgCreateToken::tokenSelectionChanged(const QModelIndex ¤t, const QModelIndex & /*previous*/) +{ + const QModelIndex realIndex = cardDatabaseDisplayModel->mapToSource(current); + const CardInfo *cardInfo = cardDatabaseModel->getCard(realIndex.row()); + + nameEdit->setText(cardInfo->getName()); + const QString cardColor = cardInfo->getColors().isEmpty() ? QString() : (cardInfo->getColors().size() > 1 ? QString("m") : cardInfo->getColors().first()); + colorEdit->setCurrentIndex(colorEdit->findData(cardColor, Qt::UserRole, Qt::MatchFixedString)); + ptEdit->setText(cardInfo->getPowTough()); + annotationEdit->setText(cardInfo->getText()); +} + +void DlgCreateToken::actChooseTokenFromAll(bool checked) +{ + if (checked) + cardDatabaseDisplayModel->setCardNameSet(QSet()); +} + +void DlgCreateToken::actChooseTokenFromDeck(bool checked) +{ + if (checked) + cardDatabaseDisplayModel->setCardNameSet(QSet::fromList(predefinedTokens)); +} + void DlgCreateToken::actOk() { accept(); diff --git a/cockatrice/src/dlg_create_token.h b/cockatrice/src/dlg_create_token.h index 684371ea..2bc371fe 100644 --- a/cockatrice/src/dlg_create_token.h +++ b/cockatrice/src/dlg_create_token.h @@ -2,29 +2,41 @@ #define DLG_CREATETOKEN_H #include -#include +#include class QLabel; +class QLineEdit; class QComboBox; class QCheckBox; class QPushButton; +class QRadioButton; +class DeckList; +class CardDatabaseModel; +class CardDatabaseDisplayModel; class DlgCreateToken : public QDialog { Q_OBJECT public: - DlgCreateToken(QWidget *parent = 0); + DlgCreateToken(const QStringList &_predefinedTokens, QWidget *parent = 0); QString getName() const; QString getColor() const; QString getPT() const; QString getAnnotation() const; bool getDestroy() const; private slots: + void tokenSelectionChanged(const QModelIndex ¤t, const QModelIndex &previous); + void actChooseTokenFromAll(bool checked); + void actChooseTokenFromDeck(bool checked); void actOk(); private: + CardDatabaseModel *cardDatabaseModel; + CardDatabaseDisplayModel *cardDatabaseDisplayModel; + QStringList predefinedTokens; QLabel *nameLabel, *colorLabel, *ptLabel, *annotationLabel; QComboBox *colorEdit; QLineEdit *nameEdit, *ptEdit, *annotationEdit; QCheckBox *destroyCheckBox; + QRadioButton *chooseTokenFromAllRadioButton, *chooseTokenFromDeckRadioButton; }; #endif diff --git a/cockatrice/src/dlg_creategame.cpp b/cockatrice/src/dlg_creategame.cpp index cf98f5f6..6dd88901 100644 --- a/cockatrice/src/dlg_creategame.cpp +++ b/cockatrice/src/dlg_creategame.cpp @@ -55,7 +55,8 @@ void DlgCreateGame::sharedCtor() onlyBuddiesCheckBox = new QCheckBox(tr("Only &buddies can join")); onlyRegisteredCheckBox = new QCheckBox(tr("Only ®istered users can join")); - onlyRegisteredCheckBox->setChecked(true); + if (room && room->getUserInfo()->user_level() & ServerInfo_User::IsRegistered) + onlyRegisteredCheckBox->setChecked(true); QGridLayout *joinRestrictionsLayout = new QGridLayout; joinRestrictionsLayout->addWidget(passwordLabel, 0, 0); diff --git a/cockatrice/src/dlg_filter_games.cpp b/cockatrice/src/dlg_filter_games.cpp index ae6fdc9d..45895678 100644 --- a/cockatrice/src/dlg_filter_games.cpp +++ b/cockatrice/src/dlg_filter_games.cpp @@ -61,12 +61,17 @@ DlgFilterGames::DlgFilterGames(const QMap &allGameTypes, QWidget * QGroupBox *maxPlayersGroupBox = new QGroupBox(tr("Maximum player count")); maxPlayersGroupBox->setLayout(maxPlayersFilterLayout); - QGridLayout *leftColumn = new QGridLayout; - leftColumn->addWidget(gameNameFilterLabel, 0, 0); - leftColumn->addWidget(gameNameFilterEdit, 0, 1); - leftColumn->addWidget(creatorNameFilterLabel, 1, 0); - leftColumn->addWidget(creatorNameFilterEdit, 1, 1); - leftColumn->addWidget(maxPlayersGroupBox, 2, 0, 1, 2); + QGridLayout *leftGrid = new QGridLayout; + leftGrid->addWidget(gameNameFilterLabel, 0, 0); + leftGrid->addWidget(gameNameFilterEdit, 0, 1); + leftGrid->addWidget(creatorNameFilterLabel, 1, 0); + leftGrid->addWidget(creatorNameFilterEdit, 1, 1); + leftGrid->addWidget(maxPlayersGroupBox, 2, 0, 1, 2); + leftGrid->addWidget(unavailableGamesVisibleCheckBox, 3, 0, 1, 2); + + QVBoxLayout *leftColumn = new QVBoxLayout; + leftColumn->addLayout(leftGrid); + leftColumn->addStretch(); QVBoxLayout *rightColumn = new QVBoxLayout; rightColumn->addWidget(gameTypeFilterGroupBox); diff --git a/cockatrice/src/gameselector.cpp b/cockatrice/src/gameselector.cpp index 8e8cc4ed..14350789 100644 --- a/cockatrice/src/gameselector.cpp +++ b/cockatrice/src/gameselector.cpp @@ -17,7 +17,7 @@ #include "pb/serverinfo_game.pb.h" #include "pb/response.pb.h" -GameSelector::GameSelector(AbstractClient *_client, TabSupervisor *_tabSupervisor, TabRoom *_room, const QMap &_rooms, const QMap &_gameTypes, QWidget *parent) +GameSelector::GameSelector(AbstractClient *_client, const TabSupervisor *_tabSupervisor, TabRoom *_room, const QMap &_rooms, const QMap &_gameTypes, QWidget *parent) : QGroupBox(parent), client(_client), tabSupervisor(_tabSupervisor), room(_room) { gameListView = new QTreeView; diff --git a/cockatrice/src/gameselector.h b/cockatrice/src/gameselector.h index 898739ee..4712e3a8 100644 --- a/cockatrice/src/gameselector.h +++ b/cockatrice/src/gameselector.h @@ -2,7 +2,6 @@ #define GAMESELECTOR_H #include -//#include "tab_room.h" #include "gametypemap.h" class QTreeView; @@ -28,7 +27,7 @@ signals: void gameJoined(int gameId); private: AbstractClient *client; - TabSupervisor *tabSupervisor; + const TabSupervisor *tabSupervisor; TabRoom *room; QTreeView *gameListView; @@ -36,7 +35,7 @@ private: GamesProxyModel *gameListProxyModel; QPushButton *filterButton, *clearFilterButton, *createButton, *joinButton, *spectateButton; public: - GameSelector(AbstractClient *_client, TabSupervisor *_tabSupervisor, TabRoom *_room, const QMap &_rooms, const QMap &_gameTypes, QWidget *parent = 0); + GameSelector(AbstractClient *_client, const TabSupervisor *_tabSupervisor, TabRoom *_room, const QMap &_rooms, const QMap &_gameTypes, QWidget *parent = 0); void retranslateUi(); void processGameInfo(const ServerInfo_Game &info); }; diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index 67f1c35d..5a1d6e6c 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -7,15 +7,6 @@ GamesModel::GamesModel(const QMap &_rooms, const QMap #include #include "gametypemap.h" +#include "pb/serverinfo_game.pb.h" -class ServerInfo_Game; class ServerInfo_User; class GamesModel : public QAbstractTableModel { @@ -18,7 +18,6 @@ private: QMap gameTypes; public: GamesModel(const QMap &_rooms, const QMap &_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 8; } QVariant data(const QModelIndex &index, int role) const; diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index 6a449359..4fd3870f 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -3,6 +3,7 @@ #include "cardzone.h" #include "carditem.h" #include "soundengine.h" +#include "tab_supervisor.h" #include "pb/serverinfo_user.pb.h" #include "pb/context_move_card.pb.h" #include "pb/context_mulligan.pb.h" @@ -21,9 +22,14 @@ bool MessageLogWidget::isFemale(Player *player) const return player->getUserInfo()->gender() == ServerInfo_User::Female; } +bool MessageLogWidget::userIsFemale() const +{ + return (tabSupervisor && tabSupervisor->getUserInfo()->gender() & ServerInfo_User::Female); +} + void MessageLogWidget::logGameJoined(int gameId) { - if (female) + if (userIsFemale()) appendHtml(tr("You have joined game #%1.", "female").arg(gameId)); else appendHtml(tr("You have joined game #%1.", "male").arg(gameId)); @@ -31,7 +37,7 @@ void MessageLogWidget::logGameJoined(int gameId) void MessageLogWidget::logReplayStarted(int gameId) { - if (female) + if (userIsFemale()) appendHtml(tr("You are watching a replay of game #%1.", "female").arg(gameId)); else appendHtml(tr("You are watching a replay of game #%1.", "male").arg(gameId)); @@ -143,12 +149,12 @@ void MessageLogWidget::logConnectionStateChanged(Player *player, bool connection void MessageLogWidget::logSay(Player *player, QString message) { - appendMessage(player->getName(), message, QColor(), true); + appendMessage(message, player->getName(), UserLevelFlags(player->getUserInfo()->user_level()), true); } -void MessageLogWidget::logSpectatorSay(QString spectatorName, QString message) +void MessageLogWidget::logSpectatorSay(QString spectatorName, UserLevelFlags spectatorUserLevel, QString message) { - appendMessage(spectatorName, message, QColor(), false); + appendMessage(message, spectatorName, spectatorUserLevel, false); } void MessageLogWidget::logShuffle(Player *player, CardZone *zone) @@ -858,7 +864,7 @@ void MessageLogWidget::connectToPlayer(Player *player) connect(player, SIGNAL(logAlwaysRevealTopCard(Player *, CardZone *, bool)), this, SLOT(logAlwaysRevealTopCard(Player *, CardZone *, bool))); } -MessageLogWidget::MessageLogWidget(const QString &_ownName, bool _female, QWidget *parent) - : ChatView(_ownName, false, parent), female(_female) +MessageLogWidget::MessageLogWidget(const TabSupervisor *_tabSupervisor, TabGame *_game, QWidget *parent) + : ChatView(_tabSupervisor, _game, false, parent) { } diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h index f471fcb8..da266918 100644 --- a/cockatrice/src/messagelogwidget.h +++ b/cockatrice/src/messagelogwidget.h @@ -2,8 +2,8 @@ #define MESSAGELOGWIDGET_H #include "chatview.h" -#include #include "translation.h" +#include "user_level.h" class Player; class CardZone; @@ -28,9 +28,9 @@ private: QString sanitizeHtml(QString dirty) const; bool isFemale(Player *player) const; + bool userIsFemale() const; QPair getFromStr(CardZone *zone, QString cardName, int position, bool ownerChange) const; MessageContext currentContext; - bool female; QList moveCardQueue; QMap moveCardPT; @@ -55,7 +55,7 @@ public slots: void logGameStart(); void logConnectionStateChanged(Player *player, bool connectionState); void logSay(Player *player, QString message); - void logSpectatorSay(QString spectatorName, QString message); + void logSpectatorSay(QString spectatorName, UserLevelFlags spectatorUserLevel, QString message); void logShuffle(Player *player, CardZone *zone); void logRollDie(Player *player, int sides, int roll); void logDrawCards(Player *player, int number); @@ -85,7 +85,7 @@ public slots: void containerProcessingDone(); public: void connectToPlayer(Player *player); - MessageLogWidget(const QString &_ownName, bool _female, QWidget *parent = 0); + MessageLogWidget(const TabSupervisor *_tabSupervisor, TabGame *_game, QWidget *parent = 0); }; #endif diff --git a/cockatrice/src/pixmapgenerator.cpp b/cockatrice/src/pixmapgenerator.cpp index aac7c1a3..48d3c204 100644 --- a/cockatrice/src/pixmapgenerator.cpp +++ b/cockatrice/src/pixmapgenerator.cpp @@ -131,18 +131,18 @@ QPixmap CountryPixmapGenerator::generatePixmap(int height, const QString &countr QMap CountryPixmapGenerator::pmCache; -QPixmap UserLevelPixmapGenerator::generatePixmap(int height, int userLevel) +QPixmap UserLevelPixmapGenerator::generatePixmap(int height, UserLevelFlags userLevel) { - int key = height * 10000 + userLevel; + int key = height * 10000 + (int) userLevel; if (pmCache.contains(key)) return pmCache.value(key); QString levelString; - if (userLevel & ServerInfo_User::IsAdmin) + if (userLevel.testFlag(ServerInfo_User::IsAdmin)) levelString = "admin"; - else if (userLevel & ServerInfo_User::IsModerator) + else if (userLevel.testFlag(ServerInfo_User::IsModerator)) levelString = "moderator"; - else if (userLevel &ServerInfo_User::IsRegistered) + else if (userLevel.testFlag(ServerInfo_User::IsRegistered)) levelString = "registered"; else levelString = "normal"; diff --git a/cockatrice/src/pixmapgenerator.h b/cockatrice/src/pixmapgenerator.h index 25fa00c9..b371bd91 100644 --- a/cockatrice/src/pixmapgenerator.h +++ b/cockatrice/src/pixmapgenerator.h @@ -4,6 +4,8 @@ #include #include +#include "user_level.h" + class PhasePixmapGenerator { private: static QMap pmCache; @@ -48,7 +50,7 @@ class UserLevelPixmapGenerator { private: static QMap pmCache; public: - static QPixmap generatePixmap(int height, int userLevel); + static QPixmap generatePixmap(int height, UserLevelFlags userLevel); static void clear() { pmCache.clear(); } }; diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index 4aa2f401..0f649b1e 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -18,6 +18,8 @@ #include "dlg_create_token.h" #include "carddatabase.h" #include "color.h" +#include "decklist.h" +#include "main.h" #include #include #include @@ -95,7 +97,19 @@ void PlayerArea::setSize(qreal width, qreal height) } Player::Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_parent) - : QObject(_parent), game(_parent), shortcutsActive(false), defaultNumberTopCards(3), lastTokenDestroy(true), id(_id), active(false), local(_local), mirrored(false), handVisible(false), conceded(false), dialogSemaphore(false) + : QObject(_parent), + game(_parent), + shortcutsActive(false), + defaultNumberTopCards(3), + lastTokenDestroy(true), + id(_id), + active(false), + local(_local), + mirrored(false), + handVisible(false), + conceded(false), + dialogSemaphore(false), + deck(0) { userInfo = new ServerInfo_User; userInfo->CopyFrom(info); @@ -295,6 +309,8 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_pare aCreateAnotherToken = new QAction(this); connect(aCreateAnotherToken, SIGNAL(triggered()), this, SLOT(actCreateAnotherToken())); aCreateAnotherToken->setEnabled(false); + + createPredefinedTokenMenu = new QMenu(QString()); playerMenu->addSeparator(); countersMenu = playerMenu->addMenu(QString()); @@ -305,6 +321,7 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_pare playerMenu->addSeparator(); playerMenu->addAction(aCreateToken); playerMenu->addAction(aCreateAnotherToken); + playerMenu->addMenu(createPredefinedTokenMenu); playerMenu->addSeparator(); sayMenu = playerMenu->addMenu(QString()); initSayMenu(); @@ -320,11 +337,11 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_pare allPlayersActions.append(newAction); playerLists[i]->addSeparator(); } - } else { countersMenu = 0; sbMenu = 0; aCreateAnotherToken = 0; + createPredefinedTokenMenu = 0; aCardMenu = 0; } @@ -599,6 +616,7 @@ void Player::retranslateUi() aRollDie->setText(tr("R&oll die...")); aCreateToken->setText(tr("&Create token...")); aCreateAnotherToken->setText(tr("C&reate another token")); + createPredefinedTokenMenu->setTitle(tr("Cr&eate predefined token")); sayMenu->setTitle(tr("S&ay")); QMapIterator counterIterator(counters); @@ -723,6 +741,24 @@ void Player::initSayMenu() } } +void Player::setDeck(DeckList *_deck) +{ + deck = _deck; + + createPredefinedTokenMenu->clear(); + predefinedTokens.clear(); + InnerDecklistNode *tokenZone = dynamic_cast(deck->getRoot()->findChild("tokens")); + if (tokenZone) + for (int i = 0; i < tokenZone->size(); ++i) { + const QString tokenName = tokenZone->at(i)->getName(); + predefinedTokens.append(tokenName); + QAction *a = createPredefinedTokenMenu->addAction(tokenName); + if (i < 10) + a->setShortcut("Alt+" + QString::number((i + 1) % 10)); + connect(a, SIGNAL(triggered()), this, SLOT(actCreatePredefinedToken())); + } +} + void Player::actViewLibrary() { static_cast(scene())->toggleZoneView(this, "deck", -1); @@ -876,7 +912,7 @@ void Player::actRollDie() void Player::actCreateToken() { - DlgCreateToken dlg; + DlgCreateToken dlg(predefinedTokens); if (!dlg.exec()) return; @@ -905,6 +941,21 @@ void Player::actCreateAnotherToken() sendGameCommand(cmd); } +void Player::actCreatePredefinedToken() +{ + QAction *action = static_cast(sender()); + CardInfo *cardInfo = db->getCard(action->text()); + + lastTokenName = cardInfo->getName(); + lastTokenColor = cardInfo->getColors().isEmpty() ? QString() : cardInfo->getColors().first().toLower(); + lastTokenPT = cardInfo->getPowTough(); + lastTokenAnnotation = cardInfo->getText(); + lastTokenDestroy = true; + aCreateAnotherToken->setEnabled(true); + + actCreateAnotherToken(); +} + void Player::actSayMessage() { QAction *a = qobject_cast(sender()); diff --git a/cockatrice/src/player.h b/cockatrice/src/player.h index 3687ab59..b52b6b87 100644 --- a/cockatrice/src/player.h +++ b/cockatrice/src/player.h @@ -10,6 +10,7 @@ namespace google { namespace protobuf { class Message; } } class CardDatabase; +class DeckList; class QMenu; class QAction; class ZoneViewZone; @@ -133,6 +134,7 @@ private slots: void updateBoundingRect(); void rearrangeZones(); + void actCreatePredefinedToken(); void cardMenuAction(); void actCardCounterTrigger(); void actAttach(); @@ -152,7 +154,7 @@ private slots: private: TabGame *game; - QMenu *playerMenu, *handMenu, *graveMenu, *rfgMenu, *libraryMenu, *sbMenu, *countersMenu, *sayMenu, + QMenu *playerMenu, *handMenu, *graveMenu, *rfgMenu, *libraryMenu, *sbMenu, *countersMenu, *sayMenu, *createPredefinedTokenMenu, *mRevealLibrary, *mRevealTopCard, *mRevealHand, *mRevealRandomHandCard; QList playerLists; QList allPlayersActions; @@ -187,6 +189,9 @@ private: bool clearCardsToDelete(); QList cardsToDelete; + DeckList *deck; + QStringList predefinedTokens; + PlayerArea *playerArea; QMap zones; StackZone *stack; @@ -256,6 +261,7 @@ public: void retranslateUi(); void clear(); TabGame *getGame() const { return game; } + void setDeck(DeckList *_deck); QMenu *getPlayerMenu() const { return playerMenu; } int getId() const { return id; } QString getName() const; diff --git a/cockatrice/src/playerlistwidget.cpp b/cockatrice/src/playerlistwidget.cpp index 27aa93b9..9c706ac9 100644 --- a/cockatrice/src/playerlistwidget.cpp +++ b/cockatrice/src/playerlistwidget.cpp @@ -7,6 +7,7 @@ #include "tab_userlists.h" #include "userlist.h" #include "userinfobox.h" +#include "user_context_menu.h" #include #include #include @@ -60,7 +61,11 @@ PlayerListWidget::PlayerListWidget(TabSupervisor *_tabSupervisor, AbstractClient 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 = 0; setMinimumHeight(60); setIconSize(QSize(20, 15)); @@ -105,7 +110,7 @@ void PlayerListWidget::updatePlayerProperties(const ServerInfo_PlayerProperties 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, prop.user_info().user_level()))); + player->setIcon(3, QIcon(UserLevelPixmapGenerator::generatePixmap(12, UserLevelFlags(prop.user_info().user_level())))); player->setText(4, QString::fromStdString(prop.user_info().name())); const QString country = QString::fromStdString(prop.user_info().country()); if (!country.isEmpty()) @@ -162,93 +167,12 @@ void PlayerListWidget::setGameStarted(bool _gameStarted, bool resuming) 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(); - ServerInfo_User::UserLevelFlags userLevel = static_cast(index.sibling(index.row(), 3).data(Qt::UserRole).toInt()); + UserLevelFlags userLevel(index.sibling(index.row(), 3).data(Qt::UserRole).toInt()); - QAction *aUserName = new QAction(userName, this); - aUserName->setEnabled(false); - QAction *aDetails = new QAction(tr("User &details"), this); - QAction *aChat = new QAction(tr("Direct &chat"), 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); - QAction *aRemoveFromIgnoreList = new QAction(tr("Remove from &ignore list"), this); - QAction *aKick = new QAction(tr("Kick from &game"), this); - - QMenu *menu = new QMenu(this); - menu->addAction(aUserName); - menu->addSeparator(); - menu->addAction(aDetails); - menu->addAction(aChat); - if ((userLevel & ServerInfo_User::IsRegistered) && (tabSupervisor->getUserLevel() & ServerInfo_User::IsRegistered)) { - menu->addSeparator(); - if (tabSupervisor->getUserListsTab()->getBuddyList()->getUsers().contains(userName)) - menu->addAction(aRemoveFromBuddyList); - else - menu->addAction(aAddToBuddyList); - if (tabSupervisor->getUserListsTab()->getIgnoreList()->getUsers().contains(userName)) - menu->addAction(aRemoveFromIgnoreList); - else - menu->addAction(aAddToIgnoreList); - } - if (game->isHost() || !game->getTabSupervisor()->getAdminLocked()) { - menu->addSeparator(); - menu->addAction(aKick); - } - if (userName == QString::fromStdString(game->getTabSupervisor()->getUserInfo()->name())) { - aChat->setEnabled(false); - aAddToBuddyList->setEnabled(false); - aRemoveFromBuddyList->setEnabled(false); - aAddToIgnoreList->setEnabled(false); - aRemoveFromIgnoreList->setEnabled(false); - aKick->setEnabled(false); - } - - QAction *actionClicked = menu->exec(pos); - if (actionClicked == aDetails) { - UserInfoBox *infoWidget = new UserInfoBox(client, true, this, Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint); - infoWidget->setAttribute(Qt::WA_DeleteOnClose); - infoWidget->updateInfo(userName); - } else if (actionClicked == aChat) - emit openMessageDialog(userName, true); - else if (actionClicked == aAddToBuddyList) { - Command_AddToList cmd; - cmd.set_list("buddy"); - cmd.set_user_name(userName.toStdString()); - - client->sendCommand(client->prepareSessionCommand(cmd)); - } else if (actionClicked == aRemoveFromBuddyList) { - Command_RemoveFromList cmd; - cmd.set_list("buddy"); - cmd.set_user_name(userName.toStdString()); - - client->sendCommand(client->prepareSessionCommand(cmd)); - } else if (actionClicked == aAddToIgnoreList) { - Command_AddToList cmd; - cmd.set_list("ignore"); - cmd.set_user_name(userName.toStdString()); - - client->sendCommand(client->prepareSessionCommand(cmd)); - } else if (actionClicked == aRemoveFromIgnoreList) { - Command_RemoveFromList cmd; - cmd.set_list("ignore"); - cmd.set_user_name(userName.toStdString()); - - client->sendCommand(client->prepareSessionCommand(cmd)); - } else if (actionClicked == aKick) { - Command_KickFromGame cmd; - cmd.set_player_id(playerId); - game->sendGameCommand(cmd); - } - - delete menu; - delete aUserName; - delete aDetails; - delete aChat; - delete aAddToBuddyList; - delete aRemoveFromBuddyList; - delete aAddToIgnoreList; - delete aRemoveFromIgnoreList; - delete aKick; + userContextMenu->showContextMenu(pos, userName, userLevel, playerId); } diff --git a/cockatrice/src/playerlistwidget.h b/cockatrice/src/playerlistwidget.h index b5626f78..c07799af 100644 --- a/cockatrice/src/playerlistwidget.h +++ b/cockatrice/src/playerlistwidget.h @@ -10,6 +10,7 @@ class ServerInfo_PlayerProperties; class TabSupervisor; class AbstractClient; class TabGame; +class UserContextMenu; class PlayerListItemDelegate : public QStyledItemDelegate { public: @@ -31,6 +32,7 @@ private: TabSupervisor *tabSupervisor; AbstractClient *client; TabGame *game; + UserContextMenu *userContextMenu; QIcon readyIcon, notReadyIcon, concededIcon, playerIcon, spectatorIcon, lockIcon; bool gameStarted; signals: diff --git a/cockatrice/src/playertarget.cpp b/cockatrice/src/playertarget.cpp index a20c5c85..358fc3ab 100644 --- a/cockatrice/src/playertarget.cpp +++ b/cockatrice/src/playertarget.cpp @@ -87,7 +87,7 @@ void PlayerTarget::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*o QPixmap tempPixmap; if (fullPixmap.isNull()) - tempPixmap = UserLevelPixmapGenerator::generatePixmap(translatedSize.height(), info->user_level()); + tempPixmap = UserLevelPixmapGenerator::generatePixmap(translatedSize.height(), UserLevelFlags(info->user_level())); else tempPixmap = fullPixmap.scaled(translatedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); diff --git a/cockatrice/src/remoteclient.cpp b/cockatrice/src/remoteclient.cpp index acf63082..91b9d17a 100644 --- a/cockatrice/src/remoteclient.cpp +++ b/cockatrice/src/remoteclient.cpp @@ -118,7 +118,9 @@ void RemoteClient::readData() ServerMessage newServerMessage; newServerMessage.ParseFromArray(inputBuffer.data(), messageLength); - qDebug(("IN " + QString::number(messageLength) + ": " + QString::fromStdString(newServerMessage.DebugString())).toUtf8()); +#ifdef QT_DEBUG + qDebug(("IN " + QString::number(messageLength) + ": " + QString::fromStdString(newServerMessage.ShortDebugString())).toUtf8()); +#endif inputBuffer.remove(0, messageLength); messageInProgress = false; @@ -133,7 +135,9 @@ void RemoteClient::sendCommandContainer(const CommandContainer &cont) { QByteArray buf; unsigned int size = cont.ByteSize(); - qDebug(("OUT " + QString::number(size) + ": " + QString::fromStdString(cont.DebugString())).toUtf8()); +#ifdef QT_DEBUG + qDebug(("OUT " + QString::number(size) + ": " + QString::fromStdString(cont.ShortDebugString())).toUtf8()); +#endif buf.resize(size + 4); cont.SerializeToArray(buf.data() + 4, size); buf.data()[3] = (unsigned char) size; diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index f0ee0848..34a7e803 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "dlg_creategame.h" #include "tab_game.h" @@ -234,8 +235,8 @@ void DeckViewContainer::setDeck(DeckList *deck) sideboardLockButton->setEnabled(true); } -TabGame::TabGame(GameReplay *_replay) - : Tab(0), +TabGame::TabGame(TabSupervisor *_tabSupervisor, GameReplay *_replay) + : Tab(_tabSupervisor), hostId(-1), localPlayerId(-1), spectator(true), @@ -282,7 +283,7 @@ TabGame::TabGame(GameReplay *_replay) timeElapsedLabel = new QLabel; timeElapsedLabel->setAlignment(Qt::AlignCenter); - messageLog = new MessageLogWidget(QString(), false); + messageLog = new MessageLogWidget(tabSupervisor, this); connect(messageLog, SIGNAL(cardNameHovered(QString)), cardInfo, SLOT(setCard(QString))); connect(messageLog, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString))); connect(messageLog, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); @@ -411,7 +412,8 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, QList &_client timeElapsedLabel = new QLabel; timeElapsedLabel->setAlignment(Qt::AlignCenter); - messageLog = new MessageLogWidget(QString::fromStdString(tabSupervisor->getUserInfo()->name()), tabSupervisor->getUserInfo()->gender() == ServerInfo_User::Female); + messageLog = new MessageLogWidget(tabSupervisor, this); + connect(messageLog, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool))); connect(messageLog, SIGNAL(cardNameHovered(QString)), cardInfo, SLOT(setCard(QString))); connect(messageLog, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString))); connect(messageLog, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); @@ -813,6 +815,17 @@ AbstractClient *TabGame::getClientForPlayer(int playerId) const return clients.first(); } +int TabGame::getPlayerIdByName(const QString &playerName) const +{ + QMapIterator playerIterator(players); + while (playerIterator.hasNext()) { + const Player *const p = playerIterator.next().value(); + if (p->getName() == playerName) + return p->getId(); + } + return -1; +} + void TabGame::sendGameCommand(PendingCommand *pend, int playerId) { getClientForPlayer(playerId)->sendCommand(pend); @@ -898,12 +911,13 @@ void TabGame::closeGame() void TabGame::eventSpectatorSay(const Event_GameSay &event, int eventPlayerId, const GameEventContext & /*context*/) { - messageLog->logSpectatorSay(spectators.value(eventPlayerId), QString::fromStdString(event.message())); + const ServerInfo_User &userInfo = spectators.value(eventPlayerId); + messageLog->logSpectatorSay(QString::fromStdString(userInfo.name()), UserLevelFlags(userInfo.user_level()), QString::fromStdString(event.message())); } void TabGame::eventSpectatorLeave(const Event_Leave & /*event*/, int eventPlayerId, const GameEventContext & /*context*/) { - messageLog->logLeaveSpectator(spectators.value(eventPlayerId)); + messageLog->logLeaveSpectator(QString::fromStdString(spectators.value(eventPlayerId).name())); playerListWidget->removePlayer(eventPlayerId); spectators.remove(eventPlayerId); @@ -919,7 +933,7 @@ void TabGame::eventGameStateChanged(const Event_GameStateChanged &event, int /*e const int playerId = prop.player_id(); if (prop.spectator()) { if (!spectators.contains(playerId)) { - spectators.insert(playerId, QString::fromStdString(prop.user_info().name())); + spectators.insert(playerId, prop.user_info()); playerListWidget->addPlayer(prop); } } else { @@ -935,6 +949,7 @@ void TabGame::eventGameStateChanged(const Event_GameStateChanged &event, int /*e DeckList *newDeck = new DeckList(QString::fromStdString(playerInfo.deck_list())); db->cacheCardPixmaps(newDeck->getCardList()); deckViewContainer->setDeck(newDeck); + player->setDeck(newDeck); } deckViewContainer->setReadyStart(prop.ready_start()); deckViewContainer->setSideboardLocked(prop.sideboard_locked()); @@ -1023,7 +1038,7 @@ void TabGame::eventJoin(const Event_Join &event, int /*eventPlayerId*/, const Ga if (players.contains(playerId)) return; if (playerInfo.spectator()) { - spectators.insert(playerId, QString::fromStdString(playerInfo.user_info().name())); + spectators.insert(playerId, playerInfo.user_info()); messageLog->logJoinSpectator(QString::fromStdString(playerInfo.user_info().name())); } else { Player *newPlayer = addPlayer(playerId, playerInfo.user_info()); diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index 821091a3..9857a7ac 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -107,7 +107,7 @@ private: int localPlayerId; bool spectator; QMap players; - QMap spectators; + QMap spectators; bool gameStateKnown; bool resuming; QStringList phasesList; @@ -195,7 +195,7 @@ private slots: void actNextTurn(); public: TabGame(TabSupervisor *_tabSupervisor, QList &_clients, const Event_GameJoined &event, const QMap &_roomGameTypes); - TabGame(GameReplay *replay); + TabGame(TabSupervisor *_tabSupervisor, GameReplay *replay); ~TabGame(); void retranslateUi(); void closeRequest(); @@ -208,6 +208,7 @@ public: bool getSpectatorsSeeEverything() const { return gameInfo.spectators_omniscient(); } Player *getActiveLocalPlayer() const; AbstractClient *getClientForPlayer(int playerId) const; + int getPlayerIdByName(const QString &playerName) const; void setActiveCard(CardItem *_card) { activeCard = _card; } CardItem *getActiveCard() const { return activeCard; } diff --git a/cockatrice/src/tab_message.cpp b/cockatrice/src/tab_message.cpp index 2cb1d15c..d5938c2a 100644 --- a/cockatrice/src/tab_message.cpp +++ b/cockatrice/src/tab_message.cpp @@ -10,11 +10,12 @@ #include "pending_command.h" #include "pb/session_commands.pb.h" #include "pb/event_user_message.pb.h" +#include "pb/serverinfo_user.pb.h" -TabMessage::TabMessage(TabSupervisor *_tabSupervisor, AbstractClient *_client, const QString &_ownName, const QString &_userName) - : Tab(_tabSupervisor), client(_client), userName(_userName), userOnline(true) +TabMessage::TabMessage(TabSupervisor *_tabSupervisor, AbstractClient *_client, const ServerInfo_User &_ownUserInfo, const ServerInfo_User &_otherUserInfo) + : Tab(_tabSupervisor), client(_client), ownUserInfo(new ServerInfo_User(_ownUserInfo)), otherUserInfo(new ServerInfo_User(_otherUserInfo)), userOnline(true) { - chatView = new ChatView(_ownName, true); + chatView = new ChatView(tabSupervisor, 0, true); connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString))); connect(chatView, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); sayEdit = new QLineEdit; @@ -37,6 +38,8 @@ TabMessage::TabMessage(TabSupervisor *_tabSupervisor, AbstractClient *_client, c TabMessage::~TabMessage() { emit talkClosing(this); + delete ownUserInfo; + delete otherUserInfo; } void TabMessage::retranslateUi() @@ -45,6 +48,16 @@ void TabMessage::retranslateUi() aLeave->setText(tr("&Leave")); } +QString TabMessage::getUserName() const +{ + return QString::fromStdString(otherUserInfo->name()); +} + +QString TabMessage::getTabText() const +{ + return tr("Talking to %1").arg(QString::fromStdString(otherUserInfo->name())); +} + void TabMessage::closeRequest() { actLeave(); @@ -56,7 +69,7 @@ void TabMessage::sendMessage() return; Command_Message cmd; - cmd.set_user_name(userName.toStdString()); + cmd.set_user_name(otherUserInfo->name()); cmd.set_message(sayEdit->text().toStdString()); PendingCommand *pend = client->prepareSessionCommand(cmd); @@ -69,7 +82,7 @@ void TabMessage::sendMessage() void TabMessage::messageSent(const Response &response) { if (response.response_code() == Response::RespInIgnoreList) - chatView->appendMessage(QString(), tr("This user is ignoring you.")); + chatView->appendMessage(tr("This user is ignoring you.")); } void TabMessage::actLeave() @@ -79,18 +92,20 @@ void TabMessage::actLeave() void TabMessage::processUserMessageEvent(const Event_UserMessage &event) { - chatView->appendMessage(QString::fromStdString(event.sender_name()), QString::fromStdString(event.message())); + const UserLevelFlags userLevel(event.sender_name() == otherUserInfo->name() ? otherUserInfo->user_level() : ownUserInfo->user_level()); + chatView->appendMessage(QString::fromStdString(event.message()), QString::fromStdString(event.sender_name()), userLevel); emit userEvent(); } void TabMessage::processUserLeft() { - chatView->appendMessage(QString(), tr("%1 has left the server.").arg(userName)); + chatView->appendMessage(tr("%1 has left the server.").arg(QString::fromStdString(otherUserInfo->name()))); userOnline = false; } -void TabMessage::processUserJoined() +void TabMessage::processUserJoined(const ServerInfo_User &_userInfo) { - chatView->appendMessage(QString(), tr("%1 has joined the server.").arg(userName)); + chatView->appendMessage(tr("%1 has joined the server.").arg(QString::fromStdString(otherUserInfo->name()))); userOnline = true; + *otherUserInfo = _userInfo; } diff --git a/cockatrice/src/tab_message.h b/cockatrice/src/tab_message.h index e47281c2..a5d566cd 100644 --- a/cockatrice/src/tab_message.h +++ b/cockatrice/src/tab_message.h @@ -8,12 +8,14 @@ class ChatView; class QLineEdit; class Event_UserMessage; class Response; +class ServerInfo_User; class TabMessage : public Tab { Q_OBJECT private: AbstractClient *client; - QString userName; + ServerInfo_User *ownUserInfo; + ServerInfo_User *otherUserInfo; bool userOnline; ChatView *chatView; @@ -27,16 +29,16 @@ private slots: void actLeave(); void messageSent(const Response &response); public: - TabMessage(TabSupervisor *_tabSupervisor, AbstractClient *_client, const QString &_ownName, const QString &_userName); + TabMessage(TabSupervisor *_tabSupervisor, AbstractClient *_client, const ServerInfo_User &_ownUserInfo, const ServerInfo_User &_otherUserInfo); ~TabMessage(); void retranslateUi(); void closeRequest(); - QString getUserName() const { return userName; } - QString getTabText() const { return tr("Talking to %1").arg(userName); } + QString getUserName() const; + QString getTabText() const; void processUserMessageEvent(const Event_UserMessage &event); void processUserLeft(); - void processUserJoined(); + void processUserJoined(const ServerInfo_User &_userInfo); }; #endif diff --git a/cockatrice/src/tab_room.cpp b/cockatrice/src/tab_room.cpp index 85fe80f5..522ef412 100644 --- a/cockatrice/src/tab_room.cpp +++ b/cockatrice/src/tab_room.cpp @@ -40,7 +40,8 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, ServerI userList = new UserList(tabSupervisor, client, UserList::RoomList); connect(userList, SIGNAL(openMessageDialog(const QString &, bool)), this, SIGNAL(openMessageDialog(const QString &, bool))); - chatView = new ChatView(QString::fromStdString(ownUser->name()), true); + chatView = new ChatView(tabSupervisor, 0, true); + connect(chatView, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool))); connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString))); connect(chatView, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); sayLabel = new QLabel; @@ -105,6 +106,7 @@ TabRoom::~TabRoom() void TabRoom::retranslateUi() { gameSelector->retranslateUi(); + chatView->retranslateUi(); sayLabel->setText(tr("&Say:")); chatGroupBox->setTitle(tr("Chat")); tabMenu->setTitle(tr("&Room")); @@ -142,7 +144,7 @@ void TabRoom::sendMessage() void TabRoom::sayFinished(const Response &response) { if (response.response_code() == Response::RespChatFlood) - chatView->appendMessage(QString(), tr("You are flooding the chat. Please wait a couple of seconds.")); + chatView->appendMessage(tr("You are flooding the chat. Please wait a couple of seconds.")); } void TabRoom::actLeaveRoom() @@ -197,20 +199,13 @@ void TabRoom::processRoomSayEvent(const Event_RoomSay &event) if (tabSupervisor->getUserListsTab()->getIgnoreList()->getUsers().contains(senderName)) return; UserListTWI *twi = userList->getUsers().value(senderName); - QColor senderColor; - if (twi && (senderName != QString::fromStdString(ownUser->name()))) { - ServerInfo_User::UserLevelFlags userLevel = static_cast(twi->getUserLevel()); - if (userLevel & ServerInfo_User::IsModerator) - senderColor = Qt::darkMagenta; - else if (userLevel & ServerInfo_User::IsRegistered) - senderColor = Qt::darkGreen; - else { - if (settingsCache->getIgnoreUnregisteredUsers()) - return; - senderColor = QColor(0, 0, 254); - } + UserLevelFlags userLevel; + if (twi) { + userLevel = UserLevelFlags(twi->getUserInfo().user_level()); + if (settingsCache->getIgnoreUnregisteredUsers() && !userLevel.testFlag(ServerInfo_User::IsRegistered)) + return; } - chatView->appendMessage(QString::fromStdString(event.name()), QString::fromStdString(event.message()), senderColor); + chatView->appendMessage(QString::fromStdString(event.message()), senderName, userLevel); emit userEvent(false); } diff --git a/cockatrice/src/tab_room.h b/cockatrice/src/tab_room.h index b54afc95..9c1179b8 100644 --- a/cockatrice/src/tab_room.h +++ b/cockatrice/src/tab_room.h @@ -68,6 +68,7 @@ public: const QMap &getGameTypes() const { return gameTypes; } QString getChannelName() const { return roomName; } QString getTabText() const { return roomName; } + const ServerInfo_User *getUserInfo() const { return ownUser; } PendingCommand *prepareRoomCommand(const ::google::protobuf::Message &cmd); void sendRoomCommand(PendingCommand *pend); diff --git a/cockatrice/src/tab_supervisor.cpp b/cockatrice/src/tab_supervisor.cpp index fc4aa376..c9df68a0 100644 --- a/cockatrice/src/tab_supervisor.cpp +++ b/cockatrice/src/tab_supervisor.cpp @@ -10,6 +10,7 @@ #include "tab_message.h" #include "tab_userlists.h" #include "pixmapgenerator.h" +#include "userlist.h" #include #include @@ -96,21 +97,31 @@ TabSupervisor::~TabSupervisor() void TabSupervisor::retranslateUi() { QList tabs; - if (tabServer) - tabs.append(tabServer); - if (tabDeckStorage) - tabs.append(tabDeckStorage); + tabs.append(tabServer); + tabs.append(tabReplays); + tabs.append(tabDeckStorage); + tabs.append(tabAdmin); + tabs.append(tabUserLists); QMapIterator roomIterator(roomTabs); while (roomIterator.hasNext()) tabs.append(roomIterator.next().value()); QMapIterator gameIterator(gameTabs); while (gameIterator.hasNext()) tabs.append(gameIterator.next().value()); + QListIterator replayIterator(replayTabs); + while (replayIterator.hasNext()) + tabs.append(replayIterator.next()); - for (int i = 0; i < tabs.size(); ++i) { - setTabText(indexOf(tabs[i]), tabs[i]->getTabText()); - tabs[i]->retranslateUi(); - } + for (int i = 0; i < tabs.size(); ++i) + if (tabs[i]) { + setTabText(indexOf(tabs[i]), tabs[i]->getTabText()); + tabs[i]->retranslateUi(); + } +} + +AbstractClient *TabSupervisor::getClient() const +{ + return localClients.isEmpty() ? client : localClients.first(); } int TabSupervisor::myAddTab(Tab *tab) @@ -129,7 +140,7 @@ void TabSupervisor::start(const ServerInfo_User &_userInfo) tabUserLists = new TabUserLists(this, client, *userInfo); connect(tabUserLists, SIGNAL(openMessageDialog(const QString &, bool)), this, SLOT(addMessageTab(const QString &, bool))); - connect(tabUserLists, SIGNAL(userJoined(const QString &)), this, SLOT(processUserJoined(const QString &))); + connect(tabUserLists, SIGNAL(userJoined(ServerInfo_User)), this, SLOT(processUserJoined(ServerInfo_User))); connect(tabUserLists, SIGNAL(userLeft(const QString &)), this, SLOT(processUserLeft(const QString &))); myAddTab(tabUserLists); @@ -316,7 +327,7 @@ void TabSupervisor::roomLeft(TabRoom *tab) void TabSupervisor::openReplay(GameReplay *replay) { - TabGame *replayTab = new TabGame(replay); + TabGame *replayTab = new TabGame(this, replay); connect(replayTab, SIGNAL(gameClosing(TabGame *)), this, SLOT(replayLeft(TabGame *))); int tabIndex = myAddTab(replayTab); addCloseButtonToTab(replayTab, tabIndex); @@ -337,7 +348,13 @@ TabMessage *TabSupervisor::addMessageTab(const QString &receiverName, bool focus if (receiverName == QString::fromStdString(userInfo->name())) return 0; - TabMessage *tab = new TabMessage(this, client, QString::fromStdString(userInfo->name()), receiverName); + ServerInfo_User otherUser; + UserListTWI *twi = tabUserLists->getAllUsersList()->getUsers().value(receiverName); + if (twi) + otherUser = twi->getUserInfo(); + else + otherUser.set_name(receiverName.toStdString()); + TabMessage *tab = new TabMessage(this, client, *userInfo, otherUser); connect(tab, SIGNAL(talkClosing(TabMessage *)), this, SLOT(talkLeft(TabMessage *))); int tabIndex = myAddTab(tab); addCloseButtonToTab(tab, tabIndex); @@ -402,11 +419,11 @@ void TabSupervisor::processUserLeft(const QString &userName) tab->processUserLeft(); } -void TabSupervisor::processUserJoined(const QString &userName) +void TabSupervisor::processUserJoined(const ServerInfo_User &userInfo) { - TabMessage *tab = messageTabs.value(userName); + TabMessage *tab = messageTabs.value(QString::fromStdString(userInfo.name())); if (tab) - tab->processUserJoined(); + tab->processUserJoined(userInfo); } void TabSupervisor::updateCurrent(int index) @@ -428,8 +445,3 @@ bool TabSupervisor::getAdminLocked() const return true; return tabAdmin->getLocked(); } - -int TabSupervisor::getUserLevel() const -{ - return userInfo->user_level(); -} diff --git a/cockatrice/src/tab_supervisor.h b/cockatrice/src/tab_supervisor.h index a0d83409..379ef877 100644 --- a/cockatrice/src/tab_supervisor.h +++ b/cockatrice/src/tab_supervisor.h @@ -64,9 +64,9 @@ public: int getGameCount() const { return gameTabs.size(); } TabUserLists *getUserListsTab() const { return tabUserLists; } ServerInfo_User *getUserInfo() const { return userInfo; } + AbstractClient *getClient() const; const QMap &getRoomTabs() const { return roomTabs; } bool getAdminLocked() const; - int getUserLevel() const; signals: void setMenu(QMenu *menu); void localGameEnded(); @@ -84,7 +84,7 @@ private slots: void openReplay(GameReplay *replay); void replayLeft(TabGame *tab); void processUserLeft(const QString &userName); - void processUserJoined(const QString &userName); + void processUserJoined(const ServerInfo_User &userInfo); void talkLeft(TabMessage *tab); void tabUserEvent(bool globalEvent); void processRoomEvent(const RoomEvent &event); diff --git a/cockatrice/src/tab_userlists.cpp b/cockatrice/src/tab_userlists.cpp index b99054ca..4059a3e7 100644 --- a/cockatrice/src/tab_userlists.cpp +++ b/cockatrice/src/tab_userlists.cpp @@ -88,7 +88,7 @@ void TabUserLists::processUserJoinedEvent(const Event_UserJoined &event) ignoreList->sortItems(); buddyList->sortItems(); - emit userJoined(userName); + emit userJoined(info); } void TabUserLists::processUserLeftEvent(const Event_UserLeft &event) diff --git a/cockatrice/src/tab_userlists.h b/cockatrice/src/tab_userlists.h index e2f5f61b..866ae579 100644 --- a/cockatrice/src/tab_userlists.h +++ b/cockatrice/src/tab_userlists.h @@ -21,7 +21,7 @@ class TabUserLists : public Tab { signals: void openMessageDialog(const QString &userName, bool focus); void userLeft(const QString &userName); - void userJoined(const QString &userName); + void userJoined(const ServerInfo_User &userInfo); private slots: void processListUsersResponse(const Response &response); void processUserJoinedEvent(const Event_UserJoined &event); @@ -40,8 +40,9 @@ public: TabUserLists(TabSupervisor *_tabSupervisor, AbstractClient *_client, const ServerInfo_User &userInfo, QWidget *parent = 0); void retranslateUi(); QString getTabText() const { return tr("User lists"); } - UserList *getBuddyList() const { return buddyList; } - UserList *getIgnoreList() const { return ignoreList; } + const UserList *getAllUsersList() const { return allUsersList; } + const UserList *getBuddyList() const { return buddyList; } + const UserList *getIgnoreList() const { return ignoreList; } }; #endif diff --git a/cockatrice/src/user_context_menu.cpp b/cockatrice/src/user_context_menu.cpp new file mode 100644 index 00000000..8898e21f --- /dev/null +++ b/cockatrice/src/user_context_menu.cpp @@ -0,0 +1,198 @@ +#include +#include +#include "user_context_menu.h" +#include "tab_supervisor.h" +#include "tab_userlists.h" +#include "tab_game.h" +#include "userlist.h" +#include "abstractclient.h" +#include "userinfobox.h" +#include "gameselector.h" +#include "pending_command.h" + +#include "pb/commands.pb.h" +#include "pb/session_commands.pb.h" +#include "pb/moderator_commands.pb.h" +#include "pb/command_kick_from_game.pb.h" +#include "pb/response_get_games_of_user.pb.h" +#include "pb/response_get_user_info.pb.h" + +UserContextMenu::UserContextMenu(const TabSupervisor *_tabSupervisor, QWidget *parent, TabGame *_game) + : QObject(parent), client(_tabSupervisor->getClient()), tabSupervisor(_tabSupervisor), game(_game) +{ + aUserName = new QAction(QString(), this); + aUserName->setEnabled(false); + aDetails = new QAction(QString(), this); + aChat = new QAction(QString(), this); + aShowGames = new QAction(QString(), this); + aAddToBuddyList = new QAction(QString(), this); + aRemoveFromBuddyList = new QAction(QString(), this); + aAddToIgnoreList = new QAction(QString(), this); + aRemoveFromIgnoreList = new QAction(QString(), this); + aKick = new QAction(QString(), this); + aBan = new QAction(QString(), this); + + retranslateUi(); +} + +void UserContextMenu::retranslateUi() +{ + aDetails->setText(tr("User &details")); + aChat->setText(tr("Direct &chat")); + aShowGames->setText(tr("Show this user's &games")); + aAddToBuddyList->setText(tr("Add to &buddy list")); + aRemoveFromBuddyList->setText(tr("Remove from &buddy list")); + aAddToIgnoreList->setText(tr("Add to &ignore list")); + aRemoveFromIgnoreList->setText(tr("Remove from &ignore list")); + aKick->setText(tr("Kick from &game")); + aBan->setText(tr("Ban from &server")); +} + +void UserContextMenu::gamesOfUserReceived(const Response &resp, const CommandContainer &commandContainer) +{ + const Response_GetGamesOfUser &response = resp.GetExtension(Response_GetGamesOfUser::ext); + const Command_GetGamesOfUser &cmd = commandContainer.session_command(0).GetExtension(Command_GetGamesOfUser::ext); + + QMap gameTypeMap; + QMap roomMap; + const int roomListSize = response.room_list_size(); + for (int i = 0; i < roomListSize; ++i) { + const ServerInfo_Room &roomInfo = response.room_list(i); + roomMap.insert(roomInfo.room_id(), QString::fromStdString(roomInfo.name())); + GameTypeMap tempMap; + const int gameTypeListSize = roomInfo.gametype_list_size(); + for (int j = 0; j < gameTypeListSize; ++j) { + const ServerInfo_GameType &gameTypeInfo = roomInfo.gametype_list(j); + tempMap.insert(gameTypeInfo.game_type_id(), QString::fromStdString(gameTypeInfo.description())); + } + gameTypeMap.insert(roomInfo.room_id(), tempMap); + } + + GameSelector *selector = new GameSelector(client, tabSupervisor, 0, roomMap, gameTypeMap); + const int gameListSize = response.game_list_size(); + for (int i = 0; i < gameListSize; ++i) + selector->processGameInfo(response.game_list(i)); + + selector->setWindowTitle(tr("%1's games").arg(QString::fromStdString(cmd.user_name()))); + selector->setAttribute(Qt::WA_DeleteOnClose); + selector->show(); +} + +void UserContextMenu::banUser_processUserInfoResponse(const Response &r) +{ + const Response_GetUserInfo &response = r.GetExtension(Response_GetUserInfo::ext); + + // The dialog needs to be non-modal in order to not block the event queue of the client. + BanDialog *dlg = new BanDialog(response.user_info(), static_cast(parent())); + connect(dlg, SIGNAL(accepted()), this, SLOT(banUser_dialogFinished())); + dlg->show(); +} + +void UserContextMenu::banUser_dialogFinished() +{ + BanDialog *dlg = static_cast(sender()); + + Command_BanFromServer cmd; + cmd.set_user_name(dlg->getBanName().toStdString()); + cmd.set_address(dlg->getBanIP().toStdString()); + cmd.set_minutes(dlg->getMinutes()); + cmd.set_reason(dlg->getReason().toStdString()); + cmd.set_visible_reason(dlg->getVisibleReason().toStdString()); + + client->sendCommand(client->prepareModeratorCommand(cmd)); +} + +void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, int playerId) +{ + aUserName->setText(userName); + + QMenu *menu = new QMenu(static_cast(parent())); + menu->addAction(aUserName); + menu->addSeparator(); + menu->addAction(aDetails); + menu->addAction(aShowGames); + menu->addAction(aChat); + if (userLevel.testFlag(ServerInfo_User::IsRegistered) && (tabSupervisor->getUserInfo()->user_level() & ServerInfo_User::IsRegistered)) { + menu->addSeparator(); + if (tabSupervisor->getUserListsTab()->getBuddyList()->getUsers().contains(userName)) + menu->addAction(aRemoveFromBuddyList); + else + menu->addAction(aAddToBuddyList); + if (tabSupervisor->getUserListsTab()->getIgnoreList()->getUsers().contains(userName)) + menu->addAction(aRemoveFromIgnoreList); + else + menu->addAction(aAddToIgnoreList); + } + if (game && (game->isHost() || !tabSupervisor->getAdminLocked())) { + menu->addSeparator(); + menu->addAction(aKick); + } + if (!tabSupervisor->getAdminLocked()) { + menu->addSeparator(); + menu->addAction(aBan); + } + bool anotherUser = userName != QString::fromStdString(tabSupervisor->getUserInfo()->name()); + aChat->setEnabled(anotherUser); + aShowGames->setEnabled(anotherUser); + aAddToBuddyList->setEnabled(anotherUser); + aRemoveFromBuddyList->setEnabled(anotherUser); + aAddToIgnoreList->setEnabled(anotherUser); + aRemoveFromIgnoreList->setEnabled(anotherUser); + aKick->setEnabled(anotherUser); + aBan->setEnabled(anotherUser); + + QAction *actionClicked = menu->exec(pos); + if (actionClicked == aDetails) { + UserInfoBox *infoWidget = new UserInfoBox(client, true, static_cast(parent()), Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint); + infoWidget->setAttribute(Qt::WA_DeleteOnClose); + infoWidget->updateInfo(userName); + } else if (actionClicked == aChat) + emit openMessageDialog(userName, true); + else if (actionClicked == aShowGames) { + Command_GetGamesOfUser cmd; + cmd.set_user_name(userName.toStdString()); + + PendingCommand *pend = client->prepareSessionCommand(cmd); + connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(gamesOfUserReceived(Response, CommandContainer))); + + client->sendCommand(pend); + } else if (actionClicked == aAddToBuddyList) { + Command_AddToList cmd; + cmd.set_list("buddy"); + cmd.set_user_name(userName.toStdString()); + + client->sendCommand(client->prepareSessionCommand(cmd)); + } else if (actionClicked == aRemoveFromBuddyList) { + Command_RemoveFromList cmd; + cmd.set_list("buddy"); + cmd.set_user_name(userName.toStdString()); + + client->sendCommand(client->prepareSessionCommand(cmd)); + } else if (actionClicked == aAddToIgnoreList) { + Command_AddToList cmd; + cmd.set_list("ignore"); + cmd.set_user_name(userName.toStdString()); + + client->sendCommand(client->prepareSessionCommand(cmd)); + } else if (actionClicked == aRemoveFromIgnoreList) { + Command_RemoveFromList cmd; + cmd.set_list("ignore"); + cmd.set_user_name(userName.toStdString()); + + client->sendCommand(client->prepareSessionCommand(cmd)); + } else if (actionClicked == aKick) { + Command_KickFromGame cmd; + cmd.set_player_id(game->getPlayerIdByName(userName)); + game->sendGameCommand(cmd); + } else if (actionClicked == aBan) { + Command_GetUserInfo cmd; + cmd.set_user_name(userName.toStdString()); + + PendingCommand *pend = client->prepareSessionCommand(cmd); + connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(banUser_processUserInfoResponse(Response))); + + client->sendCommand(pend); + } + + delete menu; +} diff --git a/cockatrice/src/user_context_menu.h b/cockatrice/src/user_context_menu.h new file mode 100644 index 00000000..7634b962 --- /dev/null +++ b/cockatrice/src/user_context_menu.h @@ -0,0 +1,42 @@ +#ifndef USER_CONTEXT_MENU_H +#define USER_CONTEXT_MENU_H + +#include +#include "user_level.h" + +class QAction; +class TabSupervisor; +class TabGame; +class QPoint; +class CommandContainer; +class Response; +class AbstractClient; + +class UserContextMenu : public QObject { + Q_OBJECT +private: + AbstractClient *client; + const TabSupervisor *tabSupervisor; + TabGame *game; + + QAction *aUserName; + QAction *aDetails; + QAction *aShowGames; + QAction *aChat; + QAction *aAddToBuddyList, *aRemoveFromBuddyList; + QAction *aAddToIgnoreList, *aRemoveFromIgnoreList; + QAction *aKick; + QAction *aBan; +signals: + void openMessageDialog(const QString &userName, bool focus); +private slots: + void banUser_processUserInfoResponse(const Response &resp); + void banUser_dialogFinished(); + void gamesOfUserReceived(const Response &resp, const CommandContainer &commandContainer); +public: + UserContextMenu(const TabSupervisor *_tabSupervisor, QWidget *_parent, TabGame *_game = 0); + void retranslateUi(); + void showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, int playerId = -1); +}; + +#endif diff --git a/cockatrice/src/userinfobox.cpp b/cockatrice/src/userinfobox.cpp index 6fd2736d..79d64afa 100644 --- a/cockatrice/src/userinfobox.cpp +++ b/cockatrice/src/userinfobox.cpp @@ -56,7 +56,7 @@ void UserInfoBox::retranslateUi() void UserInfoBox::updateInfo(const ServerInfo_User &user) { - const int userLevel = user.user_level(); + const UserLevelFlags userLevel(user.user_level()); QPixmap avatarPixmap; const std::string bmp = user.avatar_bmp(); @@ -70,11 +70,11 @@ void UserInfoBox::updateInfo(const ServerInfo_User &user) countryLabel2->setPixmap(CountryPixmapGenerator::generatePixmap(15, QString::fromStdString(user.country()))); userLevelLabel2->setPixmap(UserLevelPixmapGenerator::generatePixmap(15, userLevel)); QString userLevelText; - if (userLevel & ServerInfo_User::IsAdmin) + if (userLevel.testFlag(ServerInfo_User::IsAdmin)) userLevelText = tr("Administrator"); - else if (userLevel & ServerInfo_User::IsModerator) + else if (userLevel.testFlag(ServerInfo_User::IsModerator)) userLevelText = tr("Moderator"); - else if (userLevel & ServerInfo_User::IsRegistered) + else if (userLevel.testFlag(ServerInfo_User::IsRegistered)) userLevelText = tr("Registered user"); else userLevelText = tr("Unregistered user"); diff --git a/cockatrice/src/userlist.cpp b/cockatrice/src/userlist.cpp index 5ae1da20..5e3a4611 100644 --- a/cockatrice/src/userlist.cpp +++ b/cockatrice/src/userlist.cpp @@ -4,6 +4,7 @@ #include "abstractclient.h" #include "pixmapgenerator.h" #include "userinfobox.h" +#include "user_context_menu.h" #include "gameselector.h" #include #include @@ -169,19 +170,27 @@ bool UserListItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, return QStyledItemDelegate::editorEvent(event, model, option, index); } -UserListTWI::UserListTWI() +UserListTWI::UserListTWI(const ServerInfo_User &_userInfo) : QTreeWidgetItem(Type) { + setUserInfo(_userInfo); } -QString UserListTWI::getUserName() const +void UserListTWI::setUserInfo(const ServerInfo_User &_userInfo) { - return data(2, Qt::UserRole).toString(); + userInfo = _userInfo; + + setData(0, Qt::UserRole, userInfo.user_level()); + setIcon(0, QIcon(UserLevelPixmapGenerator::generatePixmap(12, UserLevelFlags(userInfo.user_level())))); + setIcon(1, QIcon(CountryPixmapGenerator::generatePixmap(12, QString::fromStdString(userInfo.country())))); + setData(2, Qt::UserRole, QString::fromStdString(userInfo.name())); + setData(2, Qt::DisplayRole, QString::fromStdString(userInfo.name())); } -int UserListTWI::getUserLevel() const +void UserListTWI::setOnline(bool online) { - return data(0, Qt::UserRole).toInt(); + setData(0, Qt::UserRole + 1, online); + setData(2, Qt::ForegroundRole, online ? QBrush() : QBrush(Qt::gray)); } bool UserListTWI::operator<(const QTreeWidgetItem &other) const @@ -202,6 +211,8 @@ UserList::UserList(TabSupervisor *_tabSupervisor, AbstractClient *_client, UserL : QGroupBox(parent), tabSupervisor(_tabSupervisor), client(_client), type(_type), onlineCount(0) { itemDelegate = new UserListItemDelegate(this); + userContextMenu = new UserContextMenu(tabSupervisor, this); + connect(userContextMenu, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool))); userTree = new QTreeWidget; userTree->setColumnCount(3); @@ -236,25 +247,17 @@ void UserList::processUserInfo(const ServerInfo_User &user, bool online) { const QString userName = QString::fromStdString(user.name()); UserListTWI *item = users.value(userName); - if (!item) { - item = new UserListTWI; + if (item) + item->setUserInfo(user); + else { + item = new UserListTWI(user); users.insert(userName, item); userTree->addTopLevelItem(item); if (online) ++onlineCount; updateCount(); } - item->setData(0, Qt::UserRole, user.user_level()); - item->setIcon(0, QIcon(UserLevelPixmapGenerator::generatePixmap(12, user.user_level()))); - item->setIcon(1, QIcon(CountryPixmapGenerator::generatePixmap(12, QString::fromStdString(user.country())))); - item->setData(2, Qt::UserRole, QString::fromStdString(user.name())); - item->setData(2, Qt::DisplayRole, QString::fromStdString(user.name())); - - item->setData(0, Qt::UserRole + 1, online); - if (online) - item->setData(2, Qt::ForegroundRole, QBrush()); - else - item->setData(2, Qt::ForegroundRole, QBrush(Qt::gray)); + item->setOnline(online); } bool UserList::deleteUser(const QString &userName) @@ -273,25 +276,18 @@ bool UserList::deleteUser(const QString &userName) return false; } -void UserList::setUserOnline(QTreeWidgetItem *item, bool online) -{ - item->setData(0, Qt::UserRole + 1, online); - - if (online) { - item->setData(2, Qt::ForegroundRole, QBrush()); - ++onlineCount; - } else { - item->setData(2, Qt::ForegroundRole, QBrush(Qt::gray)); - --onlineCount; - } - updateCount(); -} - void UserList::setUserOnline(const QString &userName, bool online) { UserListTWI *twi = users.value(userName); - if (twi) - setUserOnline(twi, online); + if (!twi) + return; + + twi->setOnline(online); + if (online) + ++onlineCount; + else + --onlineCount; + updateCount(); } void UserList::updateCount() @@ -307,165 +303,11 @@ void UserList::userClicked(QTreeWidgetItem *item, int /*column*/) emit openMessageDialog(item->data(2, Qt::UserRole).toString(), true); } -void UserList::gamesOfUserReceived(const Response &resp, const CommandContainer &commandContainer) -{ - const Response_GetGamesOfUser &response = resp.GetExtension(Response_GetGamesOfUser::ext); - const Command_GetGamesOfUser &cmd = commandContainer.session_command(0).GetExtension(Command_GetGamesOfUser::ext); - - QMap gameTypeMap; - QMap roomMap; - const int roomListSize = response.room_list_size(); - for (int i = 0; i < roomListSize; ++i) { - const ServerInfo_Room &roomInfo = response.room_list(i); - roomMap.insert(roomInfo.room_id(), QString::fromStdString(roomInfo.name())); - GameTypeMap tempMap; - const int gameTypeListSize = roomInfo.gametype_list_size(); - for (int j = 0; j < gameTypeListSize; ++j) { - const ServerInfo_GameType &gameTypeInfo = roomInfo.gametype_list(j); - tempMap.insert(gameTypeInfo.game_type_id(), QString::fromStdString(gameTypeInfo.description())); - } - gameTypeMap.insert(roomInfo.room_id(), tempMap); - } - - GameSelector *selector = new GameSelector(client, tabSupervisor, 0, roomMap, gameTypeMap); - const int gameListSize = response.game_list_size(); - for (int i = 0; i < gameListSize; ++i) - selector->processGameInfo(response.game_list(i)); - - selector->setWindowTitle(tr("%1's games").arg(QString::fromStdString(cmd.user_name()))); - selector->setAttribute(Qt::WA_DeleteOnClose); - selector->show(); -} - -void UserList::banUser_processUserInfoResponse(const Response &r) -{ - const Response_GetUserInfo &response = r.GetExtension(Response_GetUserInfo::ext); - - // The dialog needs to be non-modal in order to not block the event queue of the client. - BanDialog *dlg = new BanDialog(response.user_info(), this); - connect(dlg, SIGNAL(accepted()), this, SLOT(banUser_dialogFinished())); - dlg->show(); -} - -void UserList::banUser_dialogFinished() -{ - BanDialog *dlg = static_cast(sender()); - - Command_BanFromServer cmd; - cmd.set_user_name(dlg->getBanName().toStdString()); - cmd.set_address(dlg->getBanIP().toStdString()); - cmd.set_minutes(dlg->getMinutes()); - cmd.set_reason(dlg->getReason().toStdString()); - cmd.set_visible_reason(dlg->getVisibleReason().toStdString()); - - client->sendCommand(client->prepareModeratorCommand(cmd)); -} - void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index) { - UserListTWI *twi = static_cast(userTree->topLevelItem(index.row())); - const QString &userName = twi->getUserName(); - ServerInfo_User::UserLevelFlags userLevel = static_cast(twi->getUserLevel()); + const ServerInfo_User &userInfo = static_cast(userTree->topLevelItem(index.row()))->getUserInfo(); - QAction *aUserName = new QAction(userName, this); - 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); - QAction *aRemoveFromIgnoreList = new QAction(tr("Remove from &ignore list"), this); - QAction *aBan = new QAction(tr("Ban from &server"), this); - - QMenu *menu = new QMenu(this); - 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(); - if (tabSupervisor->getUserListsTab()->getBuddyList()->getUsers().contains(userName)) - menu->addAction(aRemoveFromBuddyList); - else - menu->addAction(aAddToBuddyList); - if (tabSupervisor->getUserListsTab()->getIgnoreList()->getUsers().contains(userName)) - menu->addAction(aRemoveFromIgnoreList); - else - menu->addAction(aAddToIgnoreList); - } - if (!tabSupervisor->getAdminLocked()) { - menu->addSeparator(); - menu->addAction(aBan); - } - if (userName == QString::fromStdString(tabSupervisor->getUserInfo()->name())) { - aChat->setEnabled(false); - aAddToBuddyList->setEnabled(false); - aRemoveFromBuddyList->setEnabled(false); - aAddToIgnoreList->setEnabled(false); - aRemoveFromIgnoreList->setEnabled(false); - aBan->setEnabled(false); - } - - QAction *actionClicked = menu->exec(pos); - if (actionClicked == aDetails) { - UserInfoBox *infoWidget = new UserInfoBox(client, true, this, Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint); - infoWidget->setAttribute(Qt::WA_DeleteOnClose); - infoWidget->updateInfo(userName); - } else if (actionClicked == aChat) - emit openMessageDialog(userName, true); - else if (actionClicked == aAddToBuddyList) { - Command_AddToList cmd; - cmd.set_list("buddy"); - cmd.set_user_name(userName.toStdString()); - - client->sendCommand(client->prepareSessionCommand(cmd)); - } else if (actionClicked == aRemoveFromBuddyList) { - Command_RemoveFromList cmd; - cmd.set_list("buddy"); - cmd.set_user_name(userName.toStdString()); - - client->sendCommand(client->prepareSessionCommand(cmd)); - } else if (actionClicked == aShowGames) { - Command_GetGamesOfUser cmd; - cmd.set_user_name(userName.toStdString()); - - PendingCommand *pend = client->prepareSessionCommand(cmd); - connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(gamesOfUserReceived(Response, CommandContainer))); - - client->sendCommand(pend); - } else if (actionClicked == aAddToIgnoreList) { - Command_AddToList cmd; - cmd.set_list("ignore"); - cmd.set_user_name(userName.toStdString()); - - client->sendCommand(client->prepareSessionCommand(cmd)); - } else if (actionClicked == aRemoveFromIgnoreList) { - Command_RemoveFromList cmd; - cmd.set_list("ignore"); - cmd.set_user_name(userName.toStdString()); - - client->sendCommand(client->prepareSessionCommand(cmd)); - } else if (actionClicked == aBan) { - Command_GetUserInfo cmd; - cmd.set_user_name(userName.toStdString()); - - PendingCommand *pend = client->prepareSessionCommand(cmd); - connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(banUser_processUserInfoResponse(Response))); - - client->sendCommand(pend); - } - - delete menu; - delete aUserName; - delete aDetails; - delete aChat; - delete aAddToBuddyList; - delete aRemoveFromBuddyList; - delete aAddToIgnoreList; - delete aRemoveFromIgnoreList; - delete aBan; + userContextMenu->showContextMenu(pos, QString::fromStdString(userInfo.name()), UserLevelFlags(userInfo.user_level())); } void UserList::sortItems() diff --git a/cockatrice/src/userlist.h b/cockatrice/src/userlist.h index 19de8b0a..32d576af 100644 --- a/cockatrice/src/userlist.h +++ b/cockatrice/src/userlist.h @@ -5,6 +5,7 @@ #include #include #include +#include "user_level.h" class QTreeWidget; class ServerInfo_User; @@ -17,6 +18,7 @@ class QRadioButton; class QPlainTextEdit; class Response; class CommandContainer; +class UserContextMenu; class BanDialog : public QDialog { Q_OBJECT @@ -46,10 +48,13 @@ public: }; class UserListTWI : public QTreeWidgetItem { +private: + ServerInfo_User userInfo; public: - UserListTWI(); - QString getUserName() const; - int getUserLevel() const; + UserListTWI(const ServerInfo_User &_userInfo); + const ServerInfo_User &getUserInfo() const { return userInfo; } + void setUserInfo(const ServerInfo_User &_userInfo); + void setOnline(bool online); bool operator<(const QTreeWidgetItem &other) const; }; @@ -64,15 +69,12 @@ private: UserListType type; QTreeWidget *userTree; UserListItemDelegate *itemDelegate; + UserContextMenu *userContextMenu; int onlineCount; QString titleStr; void updateCount(); - void setUserOnline(QTreeWidgetItem *user, bool online); private slots: void userClicked(QTreeWidgetItem *item, int column); - void banUser_processUserInfoResponse(const Response &resp); - void banUser_dialogFinished(); - void gamesOfUserReceived(const Response &resp, const CommandContainer &commandContainer); signals: void openMessageDialog(const QString &userName, bool focus); void addBuddy(const QString &userName); diff --git a/cockatrice/src/window_deckeditor.cpp b/cockatrice/src/window_deckeditor.cpp index b7d9b836..a4d652d0 100644 --- a/cockatrice/src/window_deckeditor.cpp +++ b/cockatrice/src/window_deckeditor.cpp @@ -437,13 +437,17 @@ void WndDeckEditor::recursiveExpand(const QModelIndex &index) deckView->expand(index); } -void WndDeckEditor::addCardHelper(const QString &zoneName) +void WndDeckEditor::addCardHelper(QString zoneName) { const QModelIndex currentIndex = databaseView->selectionModel()->currentIndex(); if (!currentIndex.isValid()) return; const QString cardName = currentIndex.sibling(currentIndex.row(), 0).data().toString(); - + + CardInfo *info = db->getCard(cardName); + if (info->getIsToken()) + zoneName = "tokens"; + QModelIndex newCardIndex = deckModel->addCard(cardName, zoneName); recursiveExpand(newCardIndex); deckView->setCurrentIndex(newCardIndex); diff --git a/cockatrice/src/window_deckeditor.h b/cockatrice/src/window_deckeditor.h index 7f3dd927..d231ab82 100644 --- a/cockatrice/src/window_deckeditor.h +++ b/cockatrice/src/window_deckeditor.h @@ -58,7 +58,7 @@ private slots: void finishedUpdatingPrices(); private: - void addCardHelper(const QString &zoneName); + void addCardHelper(QString zoneName); void recursiveExpand(const QModelIndex &index); bool confirmClose(); diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index bd4a2db1..8652ad5e 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -176,7 +176,7 @@ void MainWindow::actWatchReplay() GameReplay *replay = new GameReplay; replay->ParseFromArray(buf.data(), buf.size()); - TabGame *replayWatcher = new TabGame(replay); + TabGame *replayWatcher = new TabGame(0, replay); replayWatcher->show(); } diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index f5665671..7877b1da 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -174,84 +174,84 @@ Geben Sie 0 ein für einen unbefristeten Bann. Bitte geben Sie den Grund für den Bann ein. Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nicht gesehen werden. - + ban &user name &Benutzername - + ban &IP address &IP-Adresse - + Ban type Art des Banns - + &permanent ban &permanenter Bann - + &temporary ban &temporärer Bann - + &Days: T&age: - + &Hours: &Stunden: - + &Minutes: &Minuten: - + Duration of the ban Länge des Banns - + Please enter the reason for the ban. This is only saved for moderators and cannot be seen by the banned person. Bitte geben Sie den Grund für den Bann ein. Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nicht gesehen werden. - + Please enter the reason for the ban that will be visible to the banned person. Bitte geben Sie den Grund ein, den die gebannte Person sehen kann. - + &OK &OK - + &Cancel &Abbrechen - + Ban user from server Benutzer vom Server bannen - + Error Fehler - + You have to select a name-based or IP-based ban, or both. Bitte wählen Sie einen Namens- oder Adressbann. @@ -1280,32 +1280,32 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic DeckViewContainer - + Load &local deck &Lokales Deck laden - + Load d&eck from server Deck vom Server l&aden - + Ready to s&tart Bereit zum S&tarten - + S&ideboard unlocked S&ideboard entsperrt - + S&ideboard locked S&ideboard gesperrt - + Load deck Deck laden @@ -1429,17 +1429,17 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic Nur &registrierte Benutzer können teilnehmen - + Joining restrictions Teilnahmebedingungen - + &Spectators allowed &Zuschauer zugelassen - + Spectators &need a password to join Zuschauer brauchen &auch ein Passwort @@ -1448,17 +1448,17 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic Zuschauer können sp&rechen - + Spectators can &chat Zuschauer können s&chreiben - + Spectators see &everything Zuschauer sehen &alles - + Spectators Zuschauer @@ -1471,17 +1471,17 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic &Abbruch - + Create game Spiel erstellen - + Game information &Spielinformationen - + Error Fehler @@ -1490,7 +1490,7 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic Ungültige Anzahl an Spielern. - + Server error. Serverfehler. @@ -1502,70 +1502,90 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic DlgCreateToken - + &Name: &Name: - + Token Spielstein - + C&olor: &Farbe: - + white weiß - + blue blau - + black schwarz - + red rot - + green grün - + multicolor mehrfarbig - + colorless farblos - + &P/T: &Kampfwerte: - + &Annotation: &Hinweis: - + &Destroy token when it leaves the table Spielstein &zerstören, wenn er das Spielfeld verlässt + + + Token data + Spielstein-Daten + + + + Show &all tokens + &Alle möglichen Spielsteine zeigen + + + + Show tokens from this &deck + Spielsteine dieses &Decks zeigen + + + + Choose token from list + Spielstein aus Liste auswählen + &OK &OK @@ -1575,7 +1595,7 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic A&bbrechen - + Create token Spielstein erstellen @@ -1649,7 +1669,7 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic O&K - + Filter games Spiele filtern @@ -2158,12 +2178,12 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic GamesModel - + yes ja - + no nein @@ -2172,62 +2192,62 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic Spiel ID - + Creator Ersteller - + Description Beschreibung - + yes, free for spectators ja, außer für Zuschauer - + buddies only nur Freunde - + reg. users only nur reg. Benutzer - + not allowed nicht erlaubt - + Room Raum - + Game type Spieltyp - + Password Passwort - + Restrictions Bedingungen - + Players Spieler - + Spectators Zuschauer @@ -2709,8 +2729,8 @@ Lokale Version ist %1, Serverversion ist %2. %1 zieht %2 Karten - - + + a card eine Karte @@ -2767,7 +2787,7 @@ Lokale Version ist %1, Serverversion ist %2. %1s Sideboard - + The game has started. Das Spiel hat begonnen. @@ -2804,22 +2824,22 @@ Lokale Version ist %1, Serverversion ist %2. %1 hat das Spiel verlassen. - + The game has been closed. Das Spiel wurde geschlossen. - + You have been kicked out of the game. Sie wurden aus dem Spiel geworfen. - + %1 is now watching the game. %1 schaut nun dem Spiel zu. - + %1 is not watching the game any more. %1 schaut dem Spiel nicht mehr zu. @@ -2875,49 +2895,49 @@ Lokale Version ist %1, Serverversion ist %2. - + You have joined game #%1. female Sie sind dem Spiel %1 beigetreten. - - - You have joined game #%1. - male - Sie sind dem Spiel %1 beigetreten. - + You have joined game #%1. + male + Sie sind dem Spiel %1 beigetreten. + + + You are watching a replay of game #%1. female Dies ist eine Aufzeichnung des Spiels #%1. - + You are watching a replay of game #%1. male Dies ist eine Aufzeichnung des Spiels #%1. - + %1 has joined the game. female %1 ist dem Spiel beigetreten. - - - %1 has joined the game. - male - %1 ist dem Spiel beigetreten. - + %1 has joined the game. + male + %1 ist dem Spiel beigetreten. + + + %1 has left the game. female %1 hat das Spiel verlassen. - + %1 has left the game. male %1 hat das Spiel verlassen. @@ -2943,91 +2963,91 @@ Lokale Version ist %1, Serverversion ist %2. %1 hat das Deck Nr. %2 geladen. - + %1 is ready to start the game. female %1 ist bereit, das Spiel zu starten. - - - %1 is ready to start the game. - male - %1 ist bereit, das Spiel zu starten. - + %1 is ready to start the game. + male + %1 ist bereit, das Spiel zu starten. + + + %1 is not ready to start the game any more. female %1 ist nicht mehr bereit, das Spiel zu starten. - + %1 is not ready to start the game any more. male %1 ist nicht mehr bereit, das Spiel zu starten. - + %1 has conceded the game. female %1 hat das Spiel aufgegeben. - + %1 has conceded the game. male %1 hat das Spiel aufgegeben. - + %1 has restored connection to the game. female %1 ist wieder mit dem Spiel verbunden. - + %1 has restored connection to the game. male %1 ist wieder mit dem Spiel verbunden. - + %1 has lost connection to the game. female %1 hat die Verbindung zum Spiel verloren. - + %1 has lost connection to the game. male %1 hat die Verbindung zum Spiel verloren. - + %1 shuffles %2. female %1 mischt %2. - + %1 shuffles %2. male %1 mischt %2. - + %1 rolls a %2 with a %3-sided die. female %1 würfelt eine %2 mit einem %3-seitigen Würfel. - + %1 rolls a %2 with a %3-sided die. male %1 würfelt eine %2 mit einem %3-seitigen Würfel. - + %1 draws %n card(s). female @@ -3036,7 +3056,7 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 draws %n card(s). male @@ -3045,182 +3065,182 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 undoes his last draw. %1 legt die zuletzt gezogene Karte zurück. - + %1 undoes her last draw. %1 legt die zuletzt gezogene Karte zurück. - + %1 undoes his last draw (%2). %1 legt die zuletzt gezogene Karte zurück (%2). - + %1 undoes her last draw (%2). %1 legt die zuletzt gezogene Karte zurück (%2). - + from table vom Spielfeld - + from graveyard aus dem Friedhof - + from exile aus dem Exil - + from hand von der Hand - + the bottom card of his library die unterste Karte seiner Bibliothek - + the bottom card of her library die unterste Karte ihrer Bibliothek - + from the bottom of his library , die unterste Karte seiner Bibliothek, - + from the bottom of her library , die unterste Karte ihrer Bibliothek, - + the top card of his library die oberste Karte seiner Bibliothek - + the top card of her library die oberste Karte ihrer Bibliothek - + from the top of his library , die oberste Karte seiner Bibliothek, - + from the top of her library , die oberste Karte ihrer Bibliothek, - + from library aus der Bibliothek - + from sideboard aus dem Sideboard - + from the stack vom Stapel - + %1 gives %2 control over %3. %1 überlässt %2 die Kontrolle über %3. - + %1 puts %2 into play tapped%3. %1 bringt %2 getappt%3 ins Spiel. - + %1 puts %2 into play%3. %1 bringt %2%3 ins Spiel. - + %1 puts %2%3 into graveyard. %1 legt %2%3 auf den Friedhof. - + %1 exiles %2%3. %1 schickt %2%3 ins Exil. - + %1 moves %2%3 to hand. %1 nimmt %2%3 auf die Hand. - + %1 puts %2%3 into his library. %1 legt %2%3 in seine Bibliothek. - + %1 puts %2%3 into her library. %1 legt %2%3 in ihre Bibliothek. - + %1 puts %2%3 on bottom of his library. %1 legt %2%3 unter seine Bibliothek. - + %1 puts %2%3 on bottom of her library. %1 legt %2%3 unter ihre Bibliothek. - + %1 puts %2%3 on top of his library. %1 legt %2%3 auf die Bibliothek. - + %1 puts %2%3 on top of her library. %1 legt %2%3 auf die Bibliothek. - + %1 puts %2%3 into his library at position %4. %1 legt %2%3 in seine Bibliothek an %4. Stelle. - + %1 puts %2%3 into her library at position %4. %1 legt %2%3 in ihre Bibliothek an %4. Stelle. - + %1 moves %2%3 to sideboard. %1 legt %2%3 in sein Sideboard. - + %1 plays %2%3. %1 spielt %2%3 aus. - + %1 takes a mulligan to %n. female @@ -3229,7 +3249,7 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 takes a mulligan to %n. male @@ -3238,37 +3258,37 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 flips %2 face-down. female %1 wendet %2 auf die Rückseite. - + %1 flips %2 face-down. male %1 wendet %2 auf die Rückseite. - + %1 flips %2 face-up. female %1 wendet %2 auf die Vorderseite. - + %1 flips %2 face-up. male %1 wendet %2 auf die Vorderseite. - + %1 destroys %2. female %1 zerstört %2. - + %1 destroys %2. male %1 zerstört %2. @@ -3284,332 +3304,332 @@ Lokale Version ist %1, Serverversion ist %2. %1 legt %2 an %3s %4 an. - + %1 has loaded a deck (%2). female %1 hat ein Deck geladen (%2). - + %1 has loaded a deck (%2). male %1 hat ein Deck geladen (%2). - + %1 has locked her sideboard. female %1 hat ihr Sideboard gesperrt. - + %1 has locked his sideboard. male %1 hat sein Sideboard gesperrt. - + %1 has unlocked her sideboard. female %1 hat ihr Sideboard entsperrt. - + %1 has unlocked his sideboard. male %1 hat sein Sideboard entsperrt. - + the bottom card of %1's library die unterste Karte von %1s Bibliothek - + from the bottom of %1's library von der Unterseite von %1s Bibliothek - + the top card of %1's library die oberste Karte von %1s Bibliothek - + from the top of %1's library oben von %1s Bibliothek - + from %1's library aus %1s Bibliothek - + %1 attaches %2 to %3's %4. p1 female, p2 female %1 legt %2 an %3s %4 an. - + %1 attaches %2 to %3's %4. p1 female, p2 male %1 legt %2 an %3s %4 an. - + %1 attaches %2 to %3's %4. p1 male, p2 female %1 legt %2 an %3s %4 an. - + %1 attaches %2 to %3's %4. p1 male, p2 male %1 legt %2 an %3s %4 an. - + %1 unattaches %2. female %1 löst %2 ab. - - - %1 unattaches %2. - male - %1 löst %2 ab. - + %1 unattaches %2. + male + %1 löst %2 ab. + + + %1 creates token: %2%3. female %1 erstellt Token: %2%3. - + %1 creates token: %2%3. male %1 erstellt Token: %2%3. - + %1 points from her %2 to herself. female %1 zeigt von ihrem %2 auf sich selbst. - + %1 points from his %2 to himself. male %1 zeigt von seinem %2 auf sich selbst. - + %1 points from her %2 to %3. p1 female, p2 female %1 zeigt von ihrem %2 auf %3. - + %1 points from her %2 to %3. p1 female, p2 male %1 zeigt von ihrem %2 auf %3. - + %1 points from his %2 to %3. p1 male, p2 female %1 zeigt von seinem %2 auf %3. - + %1 points from his %2 to %3. p1 male, p2 male %1 zeigt von seinem %2 auf %3. - + %1 points from %2's %3 to herself. card owner female, target female %1 zeigt von %2s %3 auf sich selbst. - + %1 points from %2's %3 to herself. card owner male, target female %1 zeigt von %2s %3 auf sich selbst. - + %1 points from %2's %3 to himself. card owner female, target male %1 zeigt von %2s %3 auf sich selbst. - + %1 points from %2's %3 to himself. card owner male, target male %1 zeigt von %2s %3 auf sich selbst. - + %1 points from %2's %3 to %4. p1 female, p2 female, p3 female %1 zeigt von %2s %3 auf %4. - + %1 points from %2's %3 to %4. p1 female, p2 female, p3 male %1 zeigt von %2s %3 auf %4. - + %1 points from %2's %3 to %4. p1 female, p2 male, p3 female %1 zeigt von %2s %3 auf %4. - + %1 points from %2's %3 to %4. p1 female, p2 male, p3 male %1 zeigt von %2s %3 auf %4. - + %1 points from %2's %3 to %4. p1 male, p2 female, p3 female %1 zeigt von %2s %3 auf %4. - + %1 points from %2's %3 to %4. p1 male, p2 female, p3 male %1 zeigt von %2s %3 auf %4. - + %1 points from %2's %3 to %4. p1 male, p2 male, p3 female %1 zeigt von %2s %3 auf %4. - + %1 points from %2's %3 to %4. p1 male, p2 male, p3 male %1 zeigt von %2s %3 auf %4. - + %1 points from her %2 to her %3. female %1 zeigt von ihrem %2 auf ihren %3. - + %1 points from his %2 to his %3. male %1 zeigt von seinem %2 auf seinen %3. - + %1 points from her %2 to %3's %4. p1 female, p2 female %1 zeigt von ihrem %2 auf %3s %4. - + %1 points from her %2 to %3's %4. p1 female, p2 male %1 zeigt von ihrem %2 auf %3s %4. - + %1 points from his %2 to %3's %4. p1 male, p2 female %1 zeigt von seinem %2 auf %3s %4. - + %1 points from his %2 to %3's %4. p1 male, p2 male %1 zeigt von seinem %2 auf %3s %4. - + %1 points from %2's %3 to her own %4. card owner female, target female %1 zeigt von %2s %3 auf ihren eigenen %4. - + %1 points from %2's %3 to her own %4. card owner male, target female %1 zeigt von %2s %3 auf ihren eigenen %4. - + %1 points from %2's %3 to his own %4. card owner female, target male %1 zeigt von %2s %3 auf seinen eigenen %4. - + %1 points from %2's %3 to his own %4. card owner male, target male %1 zeigt von %2s %3 auf seinen eigenen %4. - + %1 points from %2's %3 to %4's %5. p1 female, p2 female, p3 female %1 zeigt von %2s %3 auf %4s %5. - + %1 points from %2's %3 to %4's %5. p1 female, p2 female, p3 male %1 zeigt von %2s %3 auf %4s %5. - + %1 points from %2's %3 to %4's %5. p1 female, p2 male, p3 female %1 zeigt von %2s %3 auf %4s %5. - + %1 points from %2's %3 to %4's %5. p1 female, p2 male, p3 male %1 zeigt von %2s %3 auf %4s %5. - + %1 points from %2's %3 to %4's %5. p1 male, p2 female, p3 female %1 zeigt von %2s %3 auf %4s %5. - + %1 points from %2's %3 to %4's %5. p1 male, p2 female, p3 male %1 zeigt von %2s %3 auf %4s %5. - + %1 points from %2's %3 to %4's %5. p1 male, p2 male, p3 female %1 zeigt von %2s %3 auf %4s %5. - + %1 points from %2's %3 to %4's %5. p1 male, p2 male, p3 male %1 zeigt von %2s %3 auf %4s %5. - + %1 places %n %2 counter(s) on %3 (now %4). female @@ -3618,7 +3638,7 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 places %n %2 counter(s) on %3 (now %4). male @@ -3627,7 +3647,7 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 removes %n %2 counter(s) from %3 (now %4). female @@ -3636,7 +3656,7 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 removes %n %2 counter(s) from %3 (now %4). male @@ -3645,289 +3665,299 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 taps her permanents. female %1 tappt ihre bleibenden Karten. - + %1 untaps her permanents. female %1 enttappt ihre bleibenden Karten. - + %1 taps his permanents. male %1 tappt seine bleibenden Karten. - + %1 untaps his permanents. male %1 enttappt seine bleibenden Karten. - + %1 taps %2. female %1 tappt %2. - + %1 untaps %2. female %1 enttappt %2. - + %1 taps %2. male %1 tappt %2. - + %1 untaps %2. male %1 enttappt %2. - + %1 sets counter %2 to %3 (%4%5). female %1 setzt Zähler %2 auf %3 (%4%5). - + %1 sets counter %2 to %3 (%4%5). male %1 setzt Zähler %2 auf %3 (%4%5). - + %1 sets %2 to not untap normally. female %1 setzt %2 auf explizites Enttappen. - + %1 sets %2 to not untap normally. male %1 setzt %2 auf explizites Enttappen. - + %1 sets %2 to untap normally. female %1 setzt %2 auf normales Enttappen. - + %1 sets %2 to untap normally. male %1 setzt %2 auf normales Enttappen. - + %1 sets PT of %2 to %3. female %1 setzt Kampfwerte von %2 auf %3. - + %1 sets PT of %2 to %3. male %1 setzt Kampfwerte von %2 auf %3. - + %1 sets annotation of %2 to %3. female %1 versieht %2 mit dem Hinweis %3. - + %1 sets annotation of %2 to %3. male %1 versieht %2 mit dem Hinweis %3. - + %1 is looking at the top %2 cards %3. female %1 sieht sich die obersten %2 Karten %3 an. - + %1 is looking at the top %2 cards %3. male %1 sieht sich die obersten %2 Karten %3 an. - + %1 is looking at %2. female %1 sieht sich %2 an. - + %1 is looking at %2. male %1 sieht sich %2 an. - + %1 stops looking at %2. female %1 sieht sich %2 nicht mehr an. - + %1 stops looking at %2. male %1 sieht sich %2 nicht mehr an. - + %1 reveals %2 to %3. p1 female, p2 female %1 zeigt %3 %2. - + %1 reveals %2 to %3. p1 female, p2 male %1 zeigt %3 %2. - + %1 reveals %2 to %3. p1 male, p2 female %1 zeigt %3 %2. - + %1 reveals %2 to %3. p1 male, p2 male %1 zeigt %3 %2. - + %1 reveals %2. female %1 zeigt %2 offen vor. - - - %1 reveals %2. - male - %1 zeigt %2 offen vor. - + %1 reveals %2. + male + %1 zeigt %2 offen vor. + + + %1 randomly reveals %2%3 to %4. p1 female, p2 female %1 zeigt %4 zufällig %2%3 vor. - + %1 randomly reveals %2%3 to %4. p1 female, p2 male %1 zeigt %4 zufällig %2%3 vor. - + %1 randomly reveals %2%3 to %4. p1 male, p2 female %1 zeigt %4 zufällig %2%3 vor. - + %1 randomly reveals %2%3 to %4. p1 male, p2 male %1 zeigt %4 zufällig %2%3 vor. - + %1 randomly reveals %2%3. female %1 zeigt zufällig %2%3 offen vor. - - - %1 randomly reveals %2%3. - male - %1 zeigt zufällig %2%3 offen vor. - - %1 peeks at face down card #%2. - female - %1 schaut sich die umgedrehte Karte #%2 an. - - - - %1 peeks at face down card #%2. + %1 randomly reveals %2%3. male - %1 schaut sich die umgedrehte Karte #%2 an. + %1 zeigt zufällig %2%3 offen vor. - %1 peeks at face down card #%2: %3. + %1 peeks at face down card #%2. female - %1 schaut sich die umgedrehte Karte #%2 an: %3. + %1 schaut sich die umgedrehte Karte #%2 an. - %1 peeks at face down card #%2: %3. + %1 peeks at face down card #%2. male + %1 schaut sich die umgedrehte Karte #%2 an. + + + + %1 peeks at face down card #%2: %3. + female %1 schaut sich die umgedrehte Karte #%2 an: %3. + %1 peeks at face down card #%2: %3. + male + %1 schaut sich die umgedrehte Karte #%2 an: %3. + + + %1 reveals %2%3 to %4. p1 female, p2 female %1 zeigt %4 %2%3 vor. - + %1 reveals %2%3 to %4. p1 female, p2 male %1 zeigt %4 %2%3 vor. - + %1 reveals %2%3 to %4. p1 male, p2 female %1 zeigt %4 %2%3 vor. - + %1 reveals %2%3 to %4. p1 male, p2 male %1 zeigt %4 %2%3 vor. - + %1 reveals %2%3. female %1 zeigt %2%3 offen vor. - + %1 reveals %2%3. male %1 zeigt %2%3 offen vor. - + + %1 is now keeping the top card %2 revealed. + %1 lässt nun die oberste Karte %2 aufgedeckt. + + + + %1 is not revealing the top card %2 any longer. + %1 lässt die oberste Karte %2 nicht mehr aufgedeckt. + + + It is now %1's turn. female %1 ist am Zug. - + It is now %1's turn. male %1 ist am Zug. @@ -3940,12 +3970,12 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 draws his initial hand. %1 zieht seine Starthand. - + %1 draws her initial hand. %1 zieht ihre Starthand. @@ -4034,7 +4064,7 @@ Lokale Version ist %1, Serverversion ist %2. - + red rote @@ -4042,7 +4072,7 @@ Lokale Version ist %1, Serverversion ist %2. - + yellow gelbe @@ -4050,7 +4080,7 @@ Lokale Version ist %1, Serverversion ist %2. - + green grüne @@ -4210,7 +4240,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 zeigt %2 aus %3 offen vor. - + ending phase die Zugendphase @@ -4243,52 +4273,52 @@ Lokale Version ist %1, Serverversion ist %2. %1 ist am Zug. - + untap step das Enttappsegment - + upkeep step das Versorgungssegment - + draw step das Ziehsegment - + first main phase die erste Hauptphase - + beginning of combat step das Anfangssegment der Kampfphase - + declare attackers step das Angreifer-Deklarieren-Segment - + declare blockers step das Blocker-Deklarieren-Segment - + combat damage step das Kampfschadenssegment - + end of combat step das Endsegment der Kampfphase - + second main phase die zweite Hauptphase @@ -4297,7 +4327,7 @@ Lokale Version ist %1, Serverversion ist %2. das Ende-des-Zuges-Segment - + It is now the %1. Es ist nun %1. @@ -4454,21 +4484,21 @@ Lokale Version ist %1, Serverversion ist %2. Player - - - + + + Move to &top of library Oben auf die Biblio&thek legen - - - + + + Move to &bottom of library Unter die &Bibliothek legen - + &View library Bibliothek &ansehen @@ -4477,172 +4507,182 @@ Lokale Version ist %1, Serverversion ist %2. Oberste Karten in den F&riedhof legen... - + Move top cards to &exile... Oberste Karten ins &Exil schicken... - + F3 F3 - + View &top cards of library... Oberste Karten der Bibliothek a&nsehen... - + &View graveyard &Zeige Friedhof - + + &Always reveal top card + &Oberste Karte aufgedeckt lassen + + + + Cr&eate predefined token + &Vordefinierten Spielstein erstellen + + + &All players &allen Spielern - + &Peek at card face &Vorderseite anschauen - + &Clone &Kopieren - + Ctrl+H Ctrl+H - + Attac&h to card... An Karte &anlegen... - + Ctrl+A Ctrl+A - + Unattac&h &Von Karte lösen - + &Draw arrow... &Pfeil zeichnen... - + &Increase power &Stärke erhöhen - + Ctrl++ Ctrl++ - + &Decrease power S&tärke senken - + Ctrl+- Ctrl+- - + I&ncrease toughness &Widerstandskraft erhöhen - + Alt++ Alt++ - + D&ecrease toughness W&iderstandskraft senken - + Alt+- Alt+- - + In&crease power and toughness Stärke und Widerstandskraft &erhöhen - + Ctrl+Alt++ Ctrl+Alt++ - + Dec&rease power and toughness Stärke und Widerstandskraft s&enken - + Ctrl+Alt+- Ctrl+Alt+- - + Set &power and toughness... &Kampfwerte setzen... - + Ctrl+P Ctrl+P - + red rot - + yellow gelb - + green grün - + &Add counter (%1) Zählmarke &hinzufügen (%1) - + &Remove counter (%1) Zählmarke &entfernen (%1) - + &Set counters (%1)... Zählmarken &setzen (%1)... - + Ctrl+F3 Ctrl+F3 - + F4 F4 @@ -4651,73 +4691,73 @@ Lokale Version ist %1, Serverversion ist %2. Zeige ent&fernte Karten - + &View sideboard Zeige &Sideboard - + Player "%1" Spieler "%1" - - + + Move to &graveyard Auf den &Friedhof legen - + Reveal &library to &Bibliothek jemandem zeigen - + Reveal t&op card to &Oberste Karte jemandem zeigen - + &Undo last draw Zuletzt gezogene Karte zur&ücklegen - + Take &mulligan &Mulligan nehmen - + Move top cards to &graveyard... Oberste Karten auf den F&riedhof legen... - + Put top card on &bottom Oberste Karte nach &unten legen - + &Hand &Hand - + &Reveal to Jemandem &zeigen - + Reveal r&andom card to Z&ufällige Karte jemandem zeigen - + &Library Bib&liothek - + &Graveyard &Friedhof @@ -4726,7 +4766,7 @@ Lokale Version ist %1, Serverversion ist %2. Entfe&rnte Karten - + &Sideboard &Sideboard @@ -4735,38 +4775,38 @@ Lokale Version ist %1, Serverversion ist %2. &Kampfwerte setzen... - + &Set annotation... &Hinweis setzen... - + View top cards of library Zeige die obersten Karten der Bibliothek - + Number of cards: Anzahl der Karten: - + &Draw card Karte &ziehen - + &View exile &Zeige Exil - + &Exile &Exil - - + + Move to &hand auf die &Hand nehmen @@ -4775,28 +4815,28 @@ Lokale Version ist %1, Serverversion ist %2. auf den &Friedhof legen - - + + Move to &exile ins &Exil schicken - + Ctrl+W Ctrl+W - + Ctrl+D Ctrl+D - + D&raw cards... Ka&rten ziehen... - + Ctrl+E Ctrl+E @@ -4805,37 +4845,37 @@ Lokale Version ist %1, Serverversion ist %2. &Mulligan nehmen... - + Ctrl+M Ctrl+M - + &Shuffle Mi&schen - + Ctrl+S Ctrl+S - + &Counters &Zähler - + &Untap all permanents &Enttappe alle bleibenden Karten - + Ctrl+Shift+D Ctrl+Shift+D - + Ctrl+U Ctrl+U @@ -4864,72 +4904,72 @@ Lokale Version ist %1, Serverversion ist %2. Ctrl+L - + R&oll die... &Würfeln... - + Ctrl+I Ctrl+I - + &Create token... Spiels&tein erstellen... - + Ctrl+T Ctrl+T - + C&reate another token &Noch einen Spielstein erstellen - + Ctrl+G Ctrl+G - + S&ay S&agen - + C&ard &Karte - + &Play &Ausspielen - + &Hide &Verstecken - + &Tap &Tappen - + &Untap E&nttappen - + Toggle &normal untapping &Normales Enttappen umschalten - + &Flip &Umdrehen @@ -4958,27 +4998,27 @@ Lokale Version ist %1, Serverversion ist %2. &Setze Zählmarken... - + &top of library &auf die Bibliothek - + &bottom of library &unter die Bibliothek - + &graveyard in den &Friedhof - + Ctrl+Del Ctrl+Del - + &exile ins &Exil @@ -5011,50 +5051,50 @@ Lokale Version ist %1, Serverversion ist %2. F10 - + Draw cards Karten ziehen - - - - + + + + Number: Anzahl: - + Move top cards to grave Oberste Karten in den Friedhof legen - + Move top cards to exile Oberste Karten ins Exil schicken - + Set power/toughness Kampfwerte setzen - + Please enter the new PT: Bitte die neuen Kampfwerte eingeben: - + Set annotation Hinweis setzen - + Please enter the new annotation: Bitte den Hinweis eingeben: - + Set counters Setze Zählmarken @@ -5067,12 +5107,12 @@ Lokale Version ist %1, Serverversion ist %2. Neue Lebenspunkte insgesamt: - + Roll die Würfeln - + Number of sides: Anzahl der Seiten: @@ -5120,39 +5160,32 @@ Lokale Version ist %1, Serverversion ist %2. Deck #%1 - User &details - Benutzer&details + Benutzer&details - Direct &chat - &Persönliches Gespräch + &Persönliches Gespräch - Add to &buddy list - Zur &Freundesliste hinzufügen + Zur &Freundesliste hinzufügen - Remove from &buddy list - Von &Freundesliste entfernen + Von &Freundesliste entfernen - Add to &ignore list - &Ignorieren + &Ignorieren - Remove from &ignore list - Nicht mehr &ignorieren + Nicht mehr &ignorieren - Kick from &game - Aus dem &Spiel werfen + Aus dem &Spiel werfen ID #%1 @@ -5400,66 +5433,66 @@ Lokale Version ist %1, Serverversion ist %2. TabDeckStorage - + Local file system Lokales Dateisystem - + Server deck storage Deckspeicherplatz auf dem Server - - + + Open in deck editor Im Deckeditor öffnen - + Upload deck Deck hochladen - + Download deck Deck herunterladen - - + + New folder Neuer Ordner - + Delete Löschen - + Enter deck name Decknamen eingeben - + This decklist does not have a name. Please enter a name: Diese Deckliste hat keinen Namen. Bitte geben Sie einen Namen ein: - + Unnamed deck Unbenanntes Deck - + Name of new folder: Name für den neuen Ordner: - + Deck storage Deckspeicherplatz @@ -5573,7 +5606,7 @@ Bitte geben Sie einen Namen ein: Replay sch&ließen - + Replay %1: %2 Replay %1: %2 @@ -5639,7 +5672,7 @@ Bitte geben Sie einen Namen ein: Deck laden - + Game %1: %2 Spiel %1: %2 @@ -5647,32 +5680,32 @@ Bitte geben Sie einen Namen ein: TabMessage - + Personal &talk Persönliches &Gespräch - + &Leave Ver&lassen - + This user is ignoring you. Dieser Benutzer ignoriert Sie. - + %1 has left the server. %1 hat den Server verlassen. - + %1 has joined the server. %1 hat den Server betreten. - + Talking to %1 Gespräch mit %1 @@ -5680,33 +5713,33 @@ Bitte geben Sie einen Namen ein: TabReplays - + Local file system Lokales Dateisystem - + Server replay storage Replay-Speicherplatz auf dem Server - - + + Watch replay Replay abspielen - + Download replay Replay herunterladen - + Toggle expiration lock automatische Löschung umschalten - + Game replays Replays @@ -5714,27 +5747,32 @@ Bitte geben Sie einen Namen ein: TabRoom - + &Say: &Sagen: - + Chat Unterhaltung - + &Room &Raum - + &Leave room Raum ver&lassen - + + &Ignore unregistered users in chat + Unregistrierte Benutzer im Chat &ignorieren + + + You are flooding the chat. Please wait a couple of seconds. Sie überfluten den Chatraum. Bitte warten Sie ein paar Sekunden. @@ -5778,6 +5816,59 @@ Bitte geben Sie einen Namen ein: Benutzerlisten + + UserContextMenu + + + User &details + Benutzer&details + + + + Direct &chat + &Persönliches Gespräch + + + + Show this user's &games + Spiele dieses &Benutzers anzeigen + + + + Add to &buddy list + Zur &Freundesliste hinzufügen + + + + Remove from &buddy list + Von &Freundesliste entfernen + + + + Add to &ignore list + &Ignorieren + + + + Remove from &ignore list + Nicht mehr &ignorieren + + + + Kick from &game + Aus dem &Spiel werfen + + + + Ban from &server + Vom &Server bannen + + + + %1's games + %1s Spiele + + UserInfoBox @@ -5871,69 +5962,60 @@ Bitte geben Sie einen Namen ein: UserList - + Users online: %1 Benutzer online: %1 - + Users in this room: %1 Benutzer in diesem Raum: %1 - + Buddies online: %1 / %2 Freunde online: %1 / %2 - + Ignored users online: %1 / %2 Ignorierte Benutzer online: %1 / %2 - %1's games - %1s Spiele + %1s Spiele - User &details - Benutzer&details + Benutzer&details - Direct &chat - &Persönliches Gespräch + &Persönliches Gespräch - Show this user's &games - Spiele dieses &Benutzers anzeigen + Spiele dieses &Benutzers anzeigen - Add to &buddy list - Zur &Freundesliste hinzufügen + Zur &Freundesliste hinzufügen - Remove from &buddy list - Von &Freundesliste entfernen + Von &Freundesliste entfernen - Add to &ignore list - &Ignorieren + &Ignorieren - Remove from &ignore list - Nicht mehr &ignorieren + Nicht mehr &ignorieren - Ban from &server - Vom &Server bannen + Vom &Server bannen Duration @@ -6181,17 +6263,17 @@ Bitte überprüfen Sie, dass Sie Schreibrechte in dem Verzeichnis haben, und ver alphabetisch sortieren - + sort by name nach Namen sortieren - + sort by type nach Kartentypen sortieren - + shuffle when closing beim Schließen mischen diff --git a/common/decklist.cpp b/common/decklist.cpp index 733ade93..72ddc8c1 100644 --- a/common/decklist.cpp +++ b/common/decklist.cpp @@ -98,6 +98,8 @@ QString InnerDecklistNode::visibleNameFromName(const QString &_name) return QObject::tr("Maindeck"); else if (_name == "side") return QObject::tr("Sideboard"); + else if (_name == "tokens") + return QObject::tr("Tokens"); else return _name; } diff --git a/common/pb/serverinfo_game.proto b/common/pb/serverinfo_game.proto index 7544abe8..3a0e10d4 100644 --- a/common/pb/serverinfo_game.proto +++ b/common/pb/serverinfo_game.proto @@ -19,4 +19,5 @@ message ServerInfo_Game { optional uint32 spectators_count = 31; optional bool started = 50; optional uint32 start_time = 51; + optional bool closed = 52; } diff --git a/common/pb/serverinfo_user.proto b/common/pb/serverinfo_user.proto index 267ac3f2..b06f7bba 100644 --- a/common/pb/serverinfo_user.proto +++ b/common/pb/serverinfo_user.proto @@ -1,7 +1,7 @@ message ServerInfo_User { - enum UserLevelFlags { - IsNothing = 0; - IsUser = 1; + enum UserLevelFlag { + IsNothing = 0; + IsUser = 1; IsRegistered = 2; IsModerator = 4; IsAdmin = 8; diff --git a/common/server_game.cpp b/common/server_game.cpp index 7ece50b5..5d8f7de5 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -294,7 +294,9 @@ void Server_Game::doStartGameIfReady() locker.unlock(); ServerInfo_Game gameInfo; - getInfo(gameInfo); + gameInfo.set_room_id(room->getId()); + gameInfo.set_game_id(gameId); + gameInfo.set_started(true); emit gameInfoChanged(gameInfo); } @@ -327,6 +329,14 @@ void Server_Game::stopGameIfFinished() } sendGameStateToPlayers(); + + locker.unlock(); + + ServerInfo_Game gameInfo; + gameInfo.set_room_id(room->getId()); + gameInfo.set_game_id(gameId); + gameInfo.set_started(false); + emit gameInfoChanged(gameInfo); } Response::ResponseCode Server_Game::checkJoin(ServerInfo_User *user, const QString &_password, bool spectator, bool overrideRestrictions) @@ -377,7 +387,7 @@ void Server_Game::addPlayer(Server_AbstractUserInterface *userInterface, Respons newPlayer->moveToThread(thread()); Event_Join joinEvent; - joinEvent.mutable_player_properties()->CopyFrom(newPlayer->getProperties(true)); + newPlayer->getProperties(*joinEvent.mutable_player_properties(), true); sendGameEventContainer(prepareGameEvent(joinEvent, -1)); const QString playerName = QString::fromStdString(newPlayer->getUserInfo()->name()); @@ -393,7 +403,9 @@ void Server_Game::addPlayer(Server_AbstractUserInterface *userInterface, Respons if (broadcastUpdate) { ServerInfo_Game gameInfo; - getInfo(gameInfo); + gameInfo.set_room_id(room->getId()); + gameInfo.set_game_id(gameId); + gameInfo.set_player_count(getPlayerCount()); emit gameInfoChanged(gameInfo); } @@ -421,9 +433,10 @@ void Server_Game::removePlayer(Server_Player *player) bool spectator = player->getSpectator(); player->prepareDestroy(); - if (!getPlayerCount()) + if (!getPlayerCount()) { deleteLater(); - else if (!spectator) { + return; + } else if (!spectator) { if (playerHost) { int newHostId = -1; QMapIterator playerIterator(players); @@ -445,7 +458,9 @@ void Server_Game::removePlayer(Server_Player *player) } ServerInfo_Game gameInfo; - getInfo(gameInfo); + gameInfo.set_room_id(room->getId()); + gameInfo.set_game_id(gameId); + gameInfo.set_player_count(getPlayerCount()); emit gameInfoChanged(gameInfo); } @@ -645,8 +660,10 @@ void Server_Game::getInfo(ServerInfo_Game &result) const QMutexLocker locker(&gameMutex); result.set_room_id(room->getId()); - result.set_game_id(getGameId()); - if (!players.isEmpty()) { + result.set_game_id(gameId); + if (players.isEmpty()) + result.set_closed(true); + else { for (int i = 0; i < gameTypes.size(); ++i) result.add_game_types(gameTypes[i]); diff --git a/common/server_player.cpp b/common/server_player.cpp index 3fa79997..cc5c79ec 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -240,9 +240,8 @@ void Server_Player::clearZones() lastDrawList.clear(); } -ServerInfo_PlayerProperties Server_Player::getProperties(bool withUserInfo) +void Server_Player::getProperties(ServerInfo_PlayerProperties &result, bool withUserInfo) { - ServerInfo_PlayerProperties result; result.set_player_id(playerId); if (withUserInfo) result.mutable_user_info()->CopyFrom(*userInfo); @@ -253,8 +252,6 @@ ServerInfo_PlayerProperties Server_Player::getProperties(bool withUserInfo) if (deck) result.set_deck_hash(deck->getDeckHash().toStdString()); result.set_ping_seconds(pingTime); - - return result; } void Server_Player::addZone(Server_CardZone *zone) @@ -1674,7 +1671,7 @@ void Server_Player::disconnectClient() void Server_Player::getInfo(ServerInfo_Player *info, Server_Player *playerWhosAsking, bool omniscient, bool withUserInfo) { - info->mutable_properties()->CopyFrom(getProperties(withUserInfo)); + getProperties(*info->mutable_properties(), withUserInfo); if (playerWhosAsking == this) if (deck) info->set_deck_list(deck->writeToString_Native().toStdString()); diff --git a/common/server_player.h b/common/server_player.h index b6546b46..c136ef9d 100644 --- a/common/server_player.h +++ b/common/server_player.h @@ -105,7 +105,7 @@ public: int getPingTime() const { return pingTime; } void setPingTime(int _pingTime) { pingTime = _pingTime; } - ServerInfo_PlayerProperties getProperties(bool withUserInfo); + void getProperties(ServerInfo_PlayerProperties &result, bool withUserInfo); int newCardId(); int newCounterId() const; diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 8e74a9ee..06df1df6 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -422,7 +422,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdGetGamesOfUser(const Command_G while (roomIterator.hasNext()) { Server_Room *room = roomIterator.next().value(); room->gamesMutex.lock(); - re->add_room_list()->CopyFrom(room->getInfo(false, true)); + room->getInfo(*re->add_room_list(), false, true); QListIterator gameIterator(room->getGamesOfUser(QString::fromStdString(cmd.user_name()))); while (gameIterator.hasNext()) re->add_game_list()->CopyFrom(gameIterator.next()); @@ -470,7 +470,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdListRooms(const Command_ListRo Event_ListRooms event; QMapIterator roomIterator(server->getRooms()); while (roomIterator.hasNext()) - event.add_room_list()->CopyFrom(roomIterator.next().value()->getInfo(false)); + roomIterator.next().value()->getInfo(*event.add_room_list(), false); rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, prepareSessionEvent(event)); acceptsRoomListChanges = true; @@ -498,7 +498,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdJoinRoom(const Command_JoinRoo rc.enqueuePostResponseItem(ServerMessage::ROOM_EVENT, r->prepareRoomEvent(joinMessageEvent)); Response_JoinRoom *re = new Response_JoinRoom; - re->mutable_room_info()->CopyFrom(r->getInfo(true)); + r->getInfo(*re->mutable_room_info(), true); rc.setResponseExtension(re); return Response::RespOk; diff --git a/common/server_room.cpp b/common/server_room.cpp index 5a112b4b..85f0a9c7 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -9,6 +9,7 @@ #include "pb/event_leave_room.pb.h" #include "pb/event_list_games.pb.h" #include "pb/event_room_say.pb.h" +#include "pb/serverinfo_room.pb.h" #include Server_Room::Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent) @@ -38,9 +39,8 @@ Server *Server_Room::getServer() const return static_cast(parent()); } -ServerInfo_Room Server_Room::getInfo(bool complete, bool showGameTypes, bool updating, bool includeExternalData) const +const ServerInfo_Room &Server_Room::getInfo(ServerInfo_Room &result, bool complete, bool showGameTypes, bool updating, bool includeExternalData) const { - ServerInfo_Room result; result.set_room_id(id); if (!updating) { @@ -104,7 +104,8 @@ void Server_Room::addClient(Server_ProtocolHandler *client) userList.append(client); usersLock.unlock(); - emit roomInfoChanged(getInfo(false, false, true)); + ServerInfo_Room roomInfo; + emit roomInfoChanged(getInfo(roomInfo, false, false, true)); } void Server_Room::removeClient(Server_ProtocolHandler *client) @@ -117,7 +118,8 @@ void Server_Room::removeClient(Server_ProtocolHandler *client) event.set_name(client->getUserInfo()->name()); sendRoomEvent(prepareRoomEvent(event)); - emit roomInfoChanged(getInfo(false, false, true)); + ServerInfo_Room roomInfo; + emit roomInfoChanged(getInfo(roomInfo, false, false, true)); } void Server_Room::addExternalUser(const ServerInfo_User &userInfo) @@ -132,7 +134,8 @@ void Server_Room::addExternalUser(const ServerInfo_User &userInfo) externalUsers.insert(QString::fromStdString(userInfo.name()), userInfoContainer); usersLock.unlock(); - emit roomInfoChanged(getInfo(false, false, true)); + ServerInfo_Room roomInfo; + emit roomInfoChanged(getInfo(roomInfo, false, false, true)); } void Server_Room::removeExternalUser(const QString &name) @@ -147,7 +150,8 @@ void Server_Room::removeExternalUser(const QString &name) event.set_name(name.toStdString()); sendRoomEvent(prepareRoomEvent(event), false); - emit roomInfoChanged(getInfo(false, false, true)); + ServerInfo_Room roomInfo; + emit roomInfoChanged(getInfo(roomInfo, false, false, true)); } void Server_Room::updateExternalGameList(const ServerInfo_Game &gameInfo) @@ -161,7 +165,8 @@ void Server_Room::updateExternalGameList(const ServerInfo_Game &gameInfo) gamesMutex.unlock(); broadcastGameListUpdate(gameInfo, false); - emit roomInfoChanged(getInfo(false, false, true)); + ServerInfo_Room roomInfo; + emit roomInfoChanged(getInfo(roomInfo, false, false, true)); } Response::ResponseCode Server_Room::processJoinGameCommand(const Command_JoinGame &cmd, ResponseContainer &rc, Server_AbstractUserInterface *userInterface) @@ -215,7 +220,7 @@ void Server_Room::sendRoomEvent(RoomEvent *event, bool sendToIsl) delete event; } -void Server_Room::broadcastGameListUpdate(ServerInfo_Game gameInfo, bool sendToIsl) +void Server_Room::broadcastGameListUpdate(const ServerInfo_Game &gameInfo, bool sendToIsl) { Event_ListGames event; event.add_game_list()->CopyFrom(gameInfo); @@ -236,7 +241,8 @@ void Server_Room::addGame(Server_Game *game) game->gameMutex.unlock(); emit gameListChanged(gameInfo); - emit roomInfoChanged(getInfo(false, false, true)); + ServerInfo_Room roomInfo; + emit roomInfoChanged(getInfo(roomInfo, false, false, true)); } void Server_Room::removeGame(Server_Game *game) @@ -252,7 +258,8 @@ void Server_Room::removeGame(Server_Game *game) games.remove(game->getGameId()); - emit roomInfoChanged(getInfo(false, false, true)); + ServerInfo_Room roomInfo; + emit roomInfoChanged(getInfo(roomInfo, false, false, true)); } int Server_Room::getGamesCreatedByUser(const QString &userName) const diff --git a/common/server_room.h b/common/server_room.h index 0f887710..1a2801e0 100644 --- a/common/server_room.h +++ b/common/server_room.h @@ -8,7 +8,6 @@ #include #include #include "serverinfo_user_container.h" -#include "pb/serverinfo_room.pb.h" #include "pb/response.pb.h" class Server_ProtocolHandler; @@ -26,8 +25,8 @@ class Server_AbstractUserInterface; class Server_Room : public QObject { Q_OBJECT signals: - void roomInfoChanged(ServerInfo_Room roomInfo); - void gameListChanged(ServerInfo_Game gameInfo); + void roomInfoChanged(const ServerInfo_Room &roomInfo); + void gameListChanged(const ServerInfo_Game &gameInfo); private: int id; QString name; @@ -40,7 +39,7 @@ private: QList userList; QMap externalUsers; private slots: - void broadcastGameListUpdate(ServerInfo_Game gameInfo, bool sendToIsl = true); + void broadcastGameListUpdate(const ServerInfo_Game &gameInfo, bool sendToIsl = true); public: mutable QReadWriteLock usersLock; mutable QMutex gamesMutex; @@ -55,7 +54,7 @@ public: const QMap &getGames() const { return games; } const QMap &getExternalGames() const { return externalGames; } Server *getServer() const; - ServerInfo_Room getInfo(bool complete, bool showGameTypes = false, bool updating = false, bool includeExternalData = true) const; + const ServerInfo_Room &getInfo(ServerInfo_Room &result, bool complete, bool showGameTypes = false, bool updating = false, bool includeExternalData = true) const; int getGamesCreatedByUser(const QString &name) const; QList getGamesOfUser(const QString &name) const; diff --git a/common/user_level.h b/common/user_level.h new file mode 100644 index 00000000..cf743b8d --- /dev/null +++ b/common/user_level.h @@ -0,0 +1,10 @@ +#ifndef USER_LEVEL_H +#define USER_LEVEL_H + +#include "pb/serverinfo_user.pb.h" +#include + +Q_DECLARE_FLAGS(UserLevelFlags, ServerInfo_User::UserLevelFlag) +Q_DECLARE_OPERATORS_FOR_FLAGS(UserLevelFlags) + +#endif diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index 3a0de8d6..6b903ca6 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -75,6 +75,7 @@ bool OracleImporter::readSetsFromXml(QXmlStreamReader &xml) CardInfo *OracleImporter::addCard(const QString &setName, QString cardName, + bool isToken, int cardId, const QString &cardCost, const QString &cardType, @@ -125,7 +126,7 @@ CardInfo *OracleImporter::addCard(const QString &setName, bool cipt = (cardText.contains(cardName + " enters the battlefield tapped.")); - card = new CardInfo(this, cardName, cardCost, cardType, cardPT, fullCardText, colors, cardLoyalty, cipt); + card = new CardInfo(this, cardName, isToken, cardCost, cardType, cardPT, fullCardText, colors, cardLoyalty, cipt); int tableRow = 1; QString mainCardType = card->getMainCardType(); if ((mainCardType == "Land") || mArtifact) @@ -183,7 +184,7 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QByteArray &data) for (int i = 0; i < cardTextSplit.size(); ++i) cardTextSplit[i] = cardTextSplit[i].trimmed(); - CardInfo *card = addCard(set->getShortName(), cardName, cardId, cardCost, cardType, cardPT, cardLoyalty, cardTextSplit); + CardInfo *card = addCard(set->getShortName(), cardName, false, cardId, cardCost, cardType, cardPT, cardLoyalty, cardTextSplit); if (!set->contains(card)) { card->addToSet(set); cards++; diff --git a/oracle/src/oracleimporter.h b/oracle/src/oracleimporter.h index c29a7883..3e03586f 100644 --- a/oracle/src/oracleimporter.h +++ b/oracle/src/oracleimporter.h @@ -35,7 +35,7 @@ private: void downloadNextFile(); bool readSetsFromXml(QXmlStreamReader &xml); - CardInfo *addCard(const QString &setName, QString cardName, int cardId, const QString &cardCost, const QString &cardType, const QString &cardPT, int cardLoyalty, const QStringList &cardText); + CardInfo *addCard(const QString &setName, QString cardName, bool isToken, int cardId, const QString &cardCost, const QString &cardType, const QString &cardPT, int cardLoyalty, const QStringList &cardText); private slots: void httpRequestFinished(int requestId, bool error); void readResponseHeader(const QHttpResponseHeader &responseHeader); diff --git a/servatrice/src/isl_interface.cpp b/servatrice/src/isl_interface.cpp index 96e55800..52968422 100644 --- a/servatrice/src/isl_interface.cpp +++ b/servatrice/src/isl_interface.cpp @@ -129,7 +129,7 @@ void IslInterface::initServer() Server_Room *room = roomIterator.next().value(); room->usersLock.lockForRead(); room->gamesMutex.lock(); - event.add_room_list()->CopyFrom(room->getInfo(true, true, false, false)); + room->getInfo(*event.add_room_list(), true, true, false, false); } IslMessage message; diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 38c0c0a5..0f724a29 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -80,11 +80,11 @@ Servatrice::Servatrice(QSettings *_settings, QObject *parent) else databaseType = DatabaseNone; dbPrefix = settings->value("database/prefix").toString(); - if (databaseType != DatabaseNone) + if (databaseType != DatabaseNone) { openDatabase(); - - updateServerList(); - clearSessionTables(); + updateServerList(); + clearSessionTables(); + } const QString roomMethod = settings->value("rooms/method").toString(); if (roomMethod == "sql") {