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<int, GameTypeMap> gameTypeMap;
    QMap<int, QString> 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, false, false);
    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->setMinimumWidth(800);
    selector->setAttribute(Qt::WA_DeleteOnClose);
    selector->show();
}
Response::ResponseCode Server_ProtocolHandler::processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
{
	Response::ResponseCode finalResponseCode = Response::RespOk;
	for (int i = cont.session_command_size() - 1; i >= 0; --i) {
		Response::ResponseCode resp = Response::RespInvalidCommand;
		const SessionCommand &sc = cont.session_command(i);
		const int num = getPbExtension(sc);
		if (num != SessionCommand::PING) { // don't log ping commands
			if (num == SessionCommand::LOGIN) { // log login commands, but hide passwords
				SessionCommand debugSc(sc);
				debugSc.MutableExtension(Command_Login::ext)->clear_password();
				logDebugMessage(QString::fromStdString(debugSc.ShortDebugString()));
			} else
				logDebugMessage(QString::fromStdString(sc.ShortDebugString()));
		}
		switch ((SessionCommand::SessionCommandType) num) {
			case SessionCommand::PING: resp = cmdPing(sc.GetExtension(Command_Ping::ext), rc); break;
			case SessionCommand::LOGIN: resp = cmdLogin(sc.GetExtension(Command_Login::ext), rc); break;
			case SessionCommand::MESSAGE: resp = cmdMessage(sc.GetExtension(Command_Message::ext), rc); break;
			case SessionCommand::GET_GAMES_OF_USER: resp = cmdGetGamesOfUser(sc.GetExtension(Command_GetGamesOfUser::ext), rc); break;
			case SessionCommand::GET_USER_INFO: resp = cmdGetUserInfo(sc.GetExtension(Command_GetUserInfo::ext), rc); break;
			case SessionCommand::LIST_ROOMS: resp = cmdListRooms(sc.GetExtension(Command_ListRooms::ext), rc); break;
			case SessionCommand::JOIN_ROOM: resp = cmdJoinRoom(sc.GetExtension(Command_JoinRoom::ext), rc); break;
			case SessionCommand::LIST_USERS: resp = cmdListUsers(sc.GetExtension(Command_ListUsers::ext), rc); break;
			default: resp = processExtendedSessionCommand(num, sc, rc);
		}
		if (resp != Response::RespOk)
			finalResponseCode = resp;
	}
	return finalResponseCode;
}
void TabDeckStorage::newFolderFinished(const Response &response, const CommandContainer &commandContainer)
{
    if (response.response_code() != Response::RespOk)
        return;
    
    const Command_DeckNewDir &cmd = commandContainer.session_command(0).GetExtension(Command_DeckNewDir::ext);
    serverDirView->addFolderToTree(QString::fromStdString(cmd.dir_name()), serverDirView->getNodeByPath(QString::fromStdString(cmd.path())));
}
void TabReplays::deleteRemoteReplayFinished(const Response &r, const CommandContainer &commandContainer)
{
    if (r.response_code() != Response::RespOk)
        return;
    
    const Command_ReplayDeleteMatch &cmd = commandContainer.session_command(0).GetExtension(Command_ReplayDeleteMatch::ext);
    serverDirView->removeMatchInfo(cmd.game_id());
}
void TabDeckStorage::deleteFolderFinished(const Response &response, const CommandContainer &commandContainer)
{
    if (response.response_code() != Response::RespOk)
        return;
    
    const Command_DeckDelDir &cmd = commandContainer.session_command(0).GetExtension(Command_DeckDelDir::ext);
    RemoteDeckList_TreeModel::Node *toDelete = serverDirView->getNodeByPath(QString::fromStdString(cmd.path()));
    if (toDelete)
        serverDirView->removeNode(toDelete);
}
void TabDeckStorage::deleteDeckFinished(const Response &response, const CommandContainer &commandContainer)
{
    if (response.response_code() != Response::RespOk)
        return;
    
    const Command_DeckDel &cmd = commandContainer.session_command(0).GetExtension(Command_DeckDel::ext);
    RemoteDeckList_TreeModel::Node *toDelete = serverDirView->getNodeById(cmd.deck_id());
    if (toDelete)
        serverDirView->removeNode(toDelete);
}
void TabDeckStorage::uploadFinished(const Response &r, const CommandContainer &commandContainer)
{
    if (r.response_code() != Response::RespOk)
        return;
    
    const Response_DeckUpload &resp = r.GetExtension(Response_DeckUpload::ext);
    const Command_DeckUpload &cmd = commandContainer.session_command(0).GetExtension(Command_DeckUpload::ext);
    
    serverDirView->addFileToTree(resp.new_file(), serverDirView->getNodeByPath(QString::fromStdString(cmd.path())));
}
void TabReplays::keepRemoteReplayFinished(const Response &r, const CommandContainer &commandContainer)
{
    if (r.response_code() != Response::RespOk)
        return;
    
    const Command_ReplayModifyMatch &cmd = commandContainer.session_command(0).GetExtension(Command_ReplayModifyMatch::ext);
    
    ServerInfo_ReplayMatch temp;
    temp.set_do_not_hide(cmd.do_not_hide());
                    
    serverDirView->updateMatchInfo(cmd.game_id(), temp);
}
void TabDeckStorage::openRemoteDeckFinished(const Response &r, const CommandContainer &commandContainer)
{
    if (r.response_code() != Response::RespOk)
        return;
    
    const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext);
    const Command_DeckDownload &cmd = commandContainer.session_command(0).GetExtension(Command_DeckDownload::ext);
    
    DeckLoader loader;
    if (!loader.loadFromRemote(QString::fromStdString(resp.deck()), cmd.deck_id()))
        return;
    
    emit openDeckEditor(&loader);
}