diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index 45f2a5d2..a9fd180d 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -59,6 +59,7 @@ HEADERS += src/abstractcounter.h \ src/tab_deck_storage.h \ src/tab_supervisor.h \ src/userlist.h \ + src/userinfobox.h \ src/remotedecklist_treewidget.h \ src/deckview.h \ src/playerlistwidget.h \ @@ -139,6 +140,7 @@ SOURCES += src/abstractcounter.cpp \ src/tab_deck_storage.cpp \ src/tab_supervisor.cpp \ src/userlist.cpp \ + src/userinfobox.cpp \ src/remotedecklist_treewidget.cpp \ src/deckview.cpp \ src/playerlistwidget.cpp \ diff --git a/cockatrice/src/tab_room.cpp b/cockatrice/src/tab_room.cpp index 18c9b123..8b7fb13b 100644 --- a/cockatrice/src/tab_room.cpp +++ b/cockatrice/src/tab_room.cpp @@ -163,7 +163,7 @@ TabRoom::TabRoom(AbstractClient *_client, const QString &_ownName, ServerInfo_Ro : Tab(), client(_client), roomId(info->getRoomId()), roomName(info->getName()), ownName(_ownName) { gameSelector = new GameSelector(client, roomId); - userList = new UserList(false); + userList = new UserList(client, false); connect(userList, SIGNAL(openMessageDialog(const QString &, bool)), this, SIGNAL(openMessageDialog(const QString &, bool))); chatView = new ChatView(ownName); diff --git a/cockatrice/src/tab_server.cpp b/cockatrice/src/tab_server.cpp index 21b88e5b..8db7e41d 100644 --- a/cockatrice/src/tab_server.cpp +++ b/cockatrice/src/tab_server.cpp @@ -14,7 +14,8 @@ #include "protocol.h" #include "protocol_items.h" #include "userlist.h" -#include "pixmapgenerator.h" +#include "userinfobox.h" +//#include "pixmapgenerator.h" #include RoomSelector::RoomSelector(AbstractClient *_client, QWidget *parent) @@ -117,74 +118,14 @@ void RoomSelector::joinFinished(ProtocolResponse *r) emit roomJoined(resp->getRoomInfo(), static_cast(sender())->getExtraData().toBool()); } -UserInfoBox::UserInfoBox(ServerInfo_User *userInfo, QWidget *parent) - : QWidget(parent) -{ - avatarLabel = new QLabel; - nameLabel = new QLabel; - QFont nameFont = nameLabel->font(); - nameFont.setBold(true); - nameFont.setPointSize(nameFont.pointSize() * 1.5); - nameLabel->setFont(nameFont); - countryLabel1 = new QLabel; - countryLabel2 = new QLabel; - userLevelLabel1 = new QLabel; - userLevelLabel2 = new QLabel; - userLevelLabel3 = new QLabel; - - QGridLayout *mainLayout = new QGridLayout; - mainLayout->addWidget(avatarLabel, 0, 0, 3, 1, Qt::AlignCenter); - mainLayout->addWidget(nameLabel, 0, 1, 1, 3); - mainLayout->addWidget(countryLabel1, 1, 1, 1, 1); - mainLayout->addWidget(countryLabel2, 1, 2, 1, 2); - mainLayout->addWidget(userLevelLabel1, 2, 1, 1, 1); - mainLayout->addWidget(userLevelLabel2, 2, 2, 1, 1); - mainLayout->addWidget(userLevelLabel3, 2, 3, 1, 1); - mainLayout->setColumnMinimumWidth(0, 80); - mainLayout->setColumnStretch(3, 10); - - setLayout(mainLayout); - - updateInfo(userInfo); -} - -void UserInfoBox::retranslateUi() -{ - countryLabel1->setText(tr("Location:")); - userLevelLabel1->setText(tr("User level:")); -} - -void UserInfoBox::updateInfo(ServerInfo_User *user) -{ - int userLevel = user->getUserLevel(); - - QPixmap avatarPixmap; - if (!avatarPixmap.loadFromData(user->getAvatarBmp())) - avatarPixmap = UserLevelPixmapGenerator::generatePixmap(64, userLevel); - avatarLabel->setPixmap(avatarPixmap); - - nameLabel->setText(user->getName()); - countryLabel2->setPixmap(CountryPixmapGenerator::generatePixmap(15, user->getCountry())); - userLevelLabel2->setPixmap(UserLevelPixmapGenerator::generatePixmap(15, userLevel)); - QString userLevelText; - if (userLevel & ServerInfo_User::IsAdmin) - userLevelText = tr("Administrator"); - else if (userLevel & ServerInfo_User::IsJudge) - userLevelText = tr("Judge"); - else if (userLevel & ServerInfo_User::IsRegistered) - userLevelText = tr("Registered user"); - else - userLevelText = tr("Unregistered user"); - userLevelLabel3->setText(userLevelText); -} - TabServer::TabServer(AbstractClient *_client, ServerInfo_User *userInfo, QWidget *parent) : Tab(parent), client(_client) { roomSelector = new RoomSelector(client); serverInfoBox = new QTextBrowser; - userInfoBox = new UserInfoBox(userInfo); - userList = new UserList(true); + userInfoBox = new UserInfoBox(_client, false); + userInfoBox->updateInfo(userInfo); + userList = new UserList(client, true); connect(roomSelector, SIGNAL(roomJoined(ServerInfo_Room *, bool)), this, SIGNAL(roomJoined(ServerInfo_Room *, bool))); connect(userList, SIGNAL(openMessageDialog(const QString &, bool)), this, SIGNAL(openMessageDialog(const QString &, bool))); diff --git a/cockatrice/src/tab_server.h b/cockatrice/src/tab_server.h index de5e384e..0bdf4570 100644 --- a/cockatrice/src/tab_server.h +++ b/cockatrice/src/tab_server.h @@ -11,6 +11,7 @@ class QTextEdit; class QLabel; class UserList; class QPushButton; +class UserInfoBox; class Event_ListRooms; class Event_ServerMessage; @@ -39,16 +40,6 @@ public: void retranslateUi(); }; -class UserInfoBox : public QWidget { - Q_OBJECT -private: - QLabel *avatarLabel, *nameLabel, *countryLabel1, *countryLabel2, *userLevelLabel1, *userLevelLabel2, *userLevelLabel3; - void updateInfo(ServerInfo_User *user); -public: - UserInfoBox(ServerInfo_User *userInfo, QWidget *parent = 0); - void retranslateUi(); -}; - class TabServer : public Tab { Q_OBJECT signals: diff --git a/cockatrice/src/userinfobox.cpp b/cockatrice/src/userinfobox.cpp new file mode 100644 index 00000000..40b4b012 --- /dev/null +++ b/cockatrice/src/userinfobox.cpp @@ -0,0 +1,91 @@ +#include "userinfobox.h" +#include "protocol_datastructures.h" +#include "pixmapgenerator.h" +#include "protocol_items.h" +#include "abstractclient.h" +#include +#include + +UserInfoBox::UserInfoBox(AbstractClient *_client, bool _fullInfo, QWidget *parent, Qt::WindowFlags flags) + : QWidget(parent, flags), client(_client), fullInfo(_fullInfo) +{ + avatarLabel = new QLabel; + nameLabel = new QLabel; + QFont nameFont = nameLabel->font(); + nameFont.setBold(true); + nameFont.setPointSize(nameFont.pointSize() * 1.5); + nameLabel->setFont(nameFont); + realNameLabel1 = new QLabel; + realNameLabel2 = new QLabel; + countryLabel1 = new QLabel; + countryLabel2 = new QLabel; + userLevelLabel1 = new QLabel; + userLevelLabel2 = new QLabel; + userLevelLabel3 = new QLabel; + + QGridLayout *mainLayout = new QGridLayout; + mainLayout->addWidget(avatarLabel, 0, 0, 1, 3, Qt::AlignCenter); + mainLayout->addWidget(nameLabel, 1, 0, 1, 3); + mainLayout->addWidget(realNameLabel1, 2, 0, 1, 1); + mainLayout->addWidget(realNameLabel2, 2, 1, 1, 2); + mainLayout->addWidget(countryLabel1, 3, 0, 1, 1); + mainLayout->addWidget(countryLabel2, 3, 1, 1, 2); + mainLayout->addWidget(userLevelLabel1, 4, 0, 1, 1); + mainLayout->addWidget(userLevelLabel2, 4, 1, 1, 1); + mainLayout->addWidget(userLevelLabel3, 4, 2, 1, 1); + mainLayout->setColumnStretch(2, 10); + + setWindowTitle(tr("User information")); + setLayout(mainLayout); + retranslateUi(); +} + +void UserInfoBox::retranslateUi() +{ + realNameLabel1->setText(tr("Real name:")); + countryLabel1->setText(tr("Location:")); + userLevelLabel1->setText(tr("User level:")); +} + +void UserInfoBox::updateInfo(ServerInfo_User *user) +{ + int userLevel = user->getUserLevel(); + + QPixmap avatarPixmap; + if (!avatarPixmap.loadFromData(user->getAvatarBmp())) + avatarPixmap = UserLevelPixmapGenerator::generatePixmap(64, userLevel); + avatarLabel->setPixmap(avatarPixmap); + + nameLabel->setText(user->getName()); + realNameLabel2->setText(user->getRealName()); + countryLabel2->setPixmap(CountryPixmapGenerator::generatePixmap(15, user->getCountry())); + userLevelLabel2->setPixmap(UserLevelPixmapGenerator::generatePixmap(15, userLevel)); + QString userLevelText; + if (userLevel & ServerInfo_User::IsAdmin) + userLevelText = tr("Administrator"); + else if (userLevel & ServerInfo_User::IsJudge) + userLevelText = tr("Judge"); + else if (userLevel & ServerInfo_User::IsRegistered) + userLevelText = tr("Registered user"); + else + userLevelText = tr("Unregistered user"); + userLevelLabel3->setText(userLevelText); +} + +void UserInfoBox::updateInfo(const QString &userName) +{ + Command_GetUserInfo *command = new Command_GetUserInfo(userName); + connect(command, SIGNAL(finished(ProtocolResponse *)), this, SLOT(processResponse(ProtocolResponse *))); + client->sendCommand(command); +} + +void UserInfoBox::processResponse(ProtocolResponse *r) +{ + Response_GetUserInfo *response = qobject_cast(r); + if (!response) + return; + + updateInfo(response->getUserInfo()); + setFixedSize(sizeHint()); + show(); +} \ No newline at end of file diff --git a/cockatrice/src/userinfobox.h b/cockatrice/src/userinfobox.h new file mode 100644 index 00000000..adf5f832 --- /dev/null +++ b/cockatrice/src/userinfobox.h @@ -0,0 +1,27 @@ +#ifndef USERINFOBOX_H +#define USERINFOBOX_H + +#include + +class QLabel; +class ServerInfo_User; +class AbstractClient; +class ProtocolResponse; + +class UserInfoBox : public QWidget { + Q_OBJECT +private: + AbstractClient *client; + bool fullInfo; + QLabel *avatarLabel, *nameLabel, *realNameLabel1, *realNameLabel2, *countryLabel1, *countryLabel2, *userLevelLabel1, *userLevelLabel2, *userLevelLabel3; +public: + UserInfoBox(AbstractClient *_client, bool fullInfo, QWidget *parent = 0, Qt::WindowFlags flags = 0); + void retranslateUi(); +private slots: + void processResponse(ProtocolResponse *r); +public slots: + void updateInfo(ServerInfo_User *user); + void updateInfo(const QString &userName); +}; + +#endif \ No newline at end of file diff --git a/cockatrice/src/userlist.cpp b/cockatrice/src/userlist.cpp index 54fb4703..4ff301da 100644 --- a/cockatrice/src/userlist.cpp +++ b/cockatrice/src/userlist.cpp @@ -1,8 +1,28 @@ #include "userlist.h" #include "abstractclient.h" #include "pixmapgenerator.h" +#include "userinfobox.h" #include #include +#include +#include + +UserListItemDelegate::UserListItemDelegate(QObject *const parent) + : QItemDelegate(parent) +{ +} + +bool UserListItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) +{ + if ((event->type() == QEvent::MouseButtonPress) && index.isValid()) { + QMouseEvent *const mouseEvent = static_cast(event); + if (mouseEvent->button() == Qt::RightButton) { + static_cast(parent())->showContextMenu(mouseEvent->globalPos(), index); + return true; + } + } + return QItemDelegate::editorEvent(event, model, option, index); +} UserListTWI::UserListTWI() : QTreeWidgetItem(Type) @@ -18,15 +38,18 @@ bool UserListTWI::operator<(const QTreeWidgetItem &other) const return data(0, Qt::UserRole).toInt() > other.data(0, Qt::UserRole).toInt(); } -UserList::UserList(bool _global, QWidget *parent) - : QGroupBox(parent), global(_global) +UserList::UserList(AbstractClient *_client, bool _global, QWidget *parent) + : QGroupBox(parent), client(_client), global(_global) { + itemDelegate = new UserListItemDelegate(this); + userTree = new QTreeWidget; userTree->setColumnCount(3); userTree->header()->setResizeMode(QHeaderView::ResizeToContents); userTree->setHeaderHidden(true); userTree->setRootIsDecorated(false); userTree->setIconSize(QSize(20, 12)); + userTree->setItemDelegate(itemDelegate); connect(userTree, SIGNAL(itemActivated(QTreeWidgetItem *, int)), this, SLOT(userClicked(QTreeWidgetItem *, int))); QVBoxLayout *vbox = new QVBoxLayout; @@ -87,6 +110,37 @@ void UserList::userClicked(QTreeWidgetItem *item, int /*column*/) emit openMessageDialog(item->data(2, Qt::UserRole).toString(), true); } +void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index) +{ + const QString &userName = index.sibling(index.row(), 2).data(Qt::UserRole).toString(); + + 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); + + QMenu *menu = new QMenu(this); + menu->addAction(aUserName); + menu->addSeparator(); + menu->addAction(aDetails); + menu->addAction(aChat); + + 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->setFixedSize(infoWidget->sizeHint()); + infoWidget->updateInfo(userName); + infoWidget->show(); + } else if (actionClicked == aChat) + emit openMessageDialog(userName, true); + + delete menu; + delete aUserName; + delete aDetails; + delete aChat; +} + void UserList::sortItems() { userTree->sortItems(1, Qt::AscendingOrder); diff --git a/cockatrice/src/userlist.h b/cockatrice/src/userlist.h index 0694eee0..86726d67 100644 --- a/cockatrice/src/userlist.h +++ b/cockatrice/src/userlist.h @@ -3,9 +3,17 @@ #include #include +#include class QTreeWidget; class ServerInfo_User; +class AbstractClient; + +class UserListItemDelegate : public QItemDelegate { +public: + UserListItemDelegate(QObject *const parent); + bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index); +}; class UserListTWI : public QTreeWidgetItem { public: @@ -16,7 +24,9 @@ public: class UserList : public QGroupBox { Q_OBJECT private: + AbstractClient *client; QTreeWidget *userTree; + UserListItemDelegate *itemDelegate; bool global; QString titleStr; void updateCount(); @@ -25,10 +35,11 @@ private slots: signals: void openMessageDialog(const QString &userName, bool focus); public: - UserList(bool _global, QWidget *parent = 0); + UserList(AbstractClient *_client, bool _global, QWidget *parent = 0); void retranslateUi(); void processUserInfo(ServerInfo_User *user); bool deleteUser(const QString &userName); + void showContextMenu(const QPoint &pos, const QModelIndex &index); void sortItems(); }; diff --git a/common/protocol_datastructures.cpp b/common/protocol_datastructures.cpp index ccf34bcb..20c85506 100644 --- a/common/protocol_datastructures.cpp +++ b/common/protocol_datastructures.cpp @@ -3,11 +3,12 @@ #include #include -ServerInfo_User::ServerInfo_User(const QString &_name, int _userLevel, const QString &_country, const QByteArray &_avatarBmp) +ServerInfo_User::ServerInfo_User(const QString &_name, int _userLevel, const QString &_realName, const QString &_country, const QByteArray &_avatarBmp) : SerializableItem_Map("user") { insertItem(new SerializableItem_String("name", _name)); insertItem(new SerializableItem_Int("userlevel", _userLevel)); + insertItem(new SerializableItem_String("real_name", _realName)); insertItem(new SerializableItem_String("country", _country)); insertItem(new SerializableItem_ByteArray("avatar_bmp", _avatarBmp)); } @@ -17,6 +18,7 @@ ServerInfo_User::ServerInfo_User(const ServerInfo_User *other, bool complete) { insertItem(new SerializableItem_String("name", other->getName())); insertItem(new SerializableItem_Int("userlevel", other->getUserLevel())); + insertItem(new SerializableItem_String("real_name", other->getRealName())); insertItem(new SerializableItem_String("country", other->getCountry())); insertItem(new SerializableItem_ByteArray("avatar_bmp", complete ? other->getAvatarBmp() : QByteArray())); } diff --git a/common/protocol_datastructures.h b/common/protocol_datastructures.h index 5f5649ec..5e2ab4d6 100644 --- a/common/protocol_datastructures.h +++ b/common/protocol_datastructures.h @@ -29,12 +29,13 @@ public: IsJudge = 0x04, IsAdmin = 0x08 }; - ServerInfo_User(const QString &_name = QString(), int _userLevel = IsNothing, const QString &_country = QString(), const QByteArray &_avatarBmp = QByteArray()); + ServerInfo_User(const QString &_name = QString(), int _userLevel = IsNothing, const QString &_realName = QString(), const QString &_country = QString(), const QByteArray &_avatarBmp = QByteArray()); ServerInfo_User(const ServerInfo_User *other, bool complete = true); static SerializableItem *newItem() { return new ServerInfo_User; } QString getName() const { return static_cast(itemMap.value("name"))->getData(); } int getUserLevel() const { return static_cast(itemMap.value("userlevel"))->getData(); } void setUserLevel(int _userLevel) { static_cast(itemMap.value("userlevel"))->setData(_userLevel); } + QString getRealName() const { return static_cast(itemMap.value("real_name"))->getData(); } QString getCountry() const { return static_cast(itemMap.value("country"))->getData(); } QByteArray getAvatarBmp() const { return static_cast(itemMap.value("avatar_bmp"))->getData(); } }; diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index d63fb981..460ed86b 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -266,9 +266,9 @@ ResponseCode Server_ProtocolHandler::cmdGetUserInfo(Command_GetUserInfo *cmd, Co Server_ProtocolHandler *handler = server->getUsers().value(cmd->getUserName()); if (!handler) return RespNameNotFound; - result = handler->getUserInfo(); + result = new ServerInfo_User(handler->getUserInfo()); } - + cont->setResponse(new Response_GetUserInfo(cont->getCmdId(), RespOk, result)); return RespNothing; } diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 2a77f506..9d4ed6bf 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -165,15 +165,16 @@ ServerInfo_User *Servatrice::getUserData(const QString &name) checkSql(); QSqlQuery query; - query.prepare("select admin, country, avatar_bmp from " + dbPrefix + "_users where name = :name and active = 1"); + query.prepare("select admin, realname, country, avatar_bmp from " + dbPrefix + "_users where name = :name and active = 1"); query.bindValue(":name", name); if (!execSqlQuery(query)) return new ServerInfo_User(name, ServerInfo_User::IsUser); if (query.next()) { bool is_admin = query.value(0).toInt(); - QString country = query.value(1).toString(); - QByteArray avatarBmp = query.value(2).toByteArray(); + QString realName = query.value(1).toString(); + QString country = query.value(2).toString(); + QByteArray avatarBmp = query.value(3).toByteArray(); int userLevel = ServerInfo_User::IsUser | ServerInfo_User::IsRegistered; if (is_admin) @@ -182,6 +183,7 @@ ServerInfo_User *Servatrice::getUserData(const QString &name) return new ServerInfo_User( name, userLevel, + realName, country, avatarBmp );