QTfrontend/pageroomslist.cpp
author nemo
Mon, 12 Sep 2011 19:30:18 -0400
changeset 5883 a6d764786905
parent 5602 c89b81817ee4
child 6009 14f6fc9869f2
permissions -rw-r--r--
Disable GL SetAttributes for Windows due to many testers with problems. This restores .15 behaviour. If we can find willing testers, perhaps we can narrow down which attribute was the problem. Also reenable F12 bind for Windows.

/*
 * Hedgewars, a free turn based strategy game
 * Copyright (c) 2006-2011 Andrey Korotaev <unC0Rr@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */

#include <QGridLayout>
#include <QPushButton>
#include <QComboBox>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QHeaderView>
#include <QTableWidget>

#include "ammoSchemeModel.h"
#include "pageroomslist.h"
#include "hwconsts.h"
#include "chatwidget.h"

PageRoomsList::PageRoomsList(QWidget* parent, QSettings * gameSettings, SDLInteraction * sdli) :
  AbstractPage(parent)
{
    QGridLayout * pageLayout = new QGridLayout(this);

    QHBoxLayout * newRoomLayout = new QHBoxLayout();
    QLabel * roomNameLabel = new QLabel(this);
    roomNameLabel->setText(tr("Room Name:"));
    roomName = new QLineEdit(this);
    roomName->setMaxLength(60);
    newRoomLayout->addWidget(roomNameLabel);
    newRoomLayout->addWidget(roomName);
    pageLayout->addLayout(newRoomLayout, 0, 0, 1, 2);

    roomsList = new QTableWidget(this);
    roomsList->setSelectionBehavior(QAbstractItemView::SelectRows);
    roomsList->verticalHeader()->setVisible(false);
    roomsList->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
    roomsList->setAlternatingRowColors(true);
    roomsList->setShowGrid(false);
    roomsList->setSelectionMode(QAbstractItemView::SingleSelection);
    pageLayout->addWidget(roomsList, 1, 0, 3, 2);
    pageLayout->setRowStretch(2, 100);
    
    QHBoxLayout * filterLayout = new QHBoxLayout();
    
    QLabel * stateLabel = new QLabel(this);
    stateLabel->setText(tr("State:"));
    CBState = new QComboBox(this);
    CBState->addItem(QComboBox::tr("Any"));
    CBState->addItem(QComboBox::tr("In lobby"));
    CBState->addItem(QComboBox::tr("In progress"));
    filterLayout->addWidget(stateLabel);
    filterLayout->addWidget(CBState);
    filterLayout->addSpacing(30);
    
    QLabel * ruleLabel = new QLabel(this);
    ruleLabel->setText(tr("Rules:"));
    CBRules = new QComboBox(this);
    CBRules->addItem(QComboBox::tr("Any"));
    // not the most elegant solution but it works
    ammoSchemeModel = new AmmoSchemeModel(this, NULL);
    for (int i = 0; i < ammoSchemeModel->predefSchemesNames.count(); i++)
        CBRules->addItem(ammoSchemeModel->predefSchemesNames.at(i).toAscii().constData());
    filterLayout->addWidget(ruleLabel);
    filterLayout->addWidget(CBRules);
    filterLayout->addSpacing(30);
    
    QLabel * weaponLabel = new QLabel(this);
    weaponLabel->setText(tr("Weapons:"));
    CBWeapons = new QComboBox(this);
    CBWeapons->addItem(QComboBox::tr("Any"));
    for (int i = 0; i < cDefaultAmmos.count(); i++) {
        QPair<QString,QString> ammo = cDefaultAmmos.at(i);
        CBWeapons->addItem(ammo.first.toAscii().constData());
    }
    filterLayout->addWidget(weaponLabel);
    filterLayout->addWidget(CBWeapons);
    filterLayout->addSpacing(30);

    QLabel * searchLabel = new QLabel(this);
    searchLabel->setText(tr("Search:"));
    searchText = new QLineEdit(this);
    searchText->setMaxLength(60);
    filterLayout->addWidget(searchLabel);
    filterLayout->addWidget(searchText);

    pageLayout->addLayout(filterLayout, 4, 0, 1, 2);

    chatWidget = new HWChatWidget(this, gameSettings, sdli, false);
    pageLayout->addWidget(chatWidget, 5, 0, 1, 3);
    pageLayout->setRowStretch(5, 350);

    BtnCreate = addButton(tr("Create"), pageLayout, 0, 2);
    BtnJoin = addButton(tr("Join"), pageLayout, 1, 2);
    BtnRefresh = addButton(tr("Refresh"), pageLayout, 3, 2);
    BtnClear = addButton(tr("Clear"), pageLayout, 4, 2);

    BtnBack = addButton(":/res/Exit.png", pageLayout, 6, 0, true);

    lblCount = new QLabel(this);
    pageLayout->addWidget(lblCount, 6, 1, Qt::AlignHCenter);
    lblCount->setText("?");
    lblCount->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);

    connect(chatWidget, SIGNAL(nickCountUpdate(const int)), this, SLOT(updateNickCounter(const int)));

    BtnAdmin = addButton(tr("Admin features"), pageLayout, 6, 2);

    connect(BtnCreate, SIGNAL(clicked()), this, SLOT(onCreateClick()));
    connect(BtnJoin, SIGNAL(clicked()), this, SLOT(onJoinClick()));
    connect(BtnRefresh, SIGNAL(clicked()), this, SLOT(onRefreshClick()));
    connect(BtnClear, SIGNAL(clicked()), this, SLOT(onClearClick()));
    connect(roomsList, SIGNAL(doubleClicked (const QModelIndex &)), this, SLOT(onJoinClick()));
    connect(CBState, SIGNAL(currentIndexChanged (int)), this, SLOT(onRefreshClick()));
    connect(CBRules, SIGNAL(currentIndexChanged (int)), this, SLOT(onRefreshClick()));
    connect(CBWeapons, SIGNAL(currentIndexChanged (int)), this, SLOT(onRefreshClick()));
    connect(searchText, SIGNAL(textChanged (const QString &)), this, SLOT(onRefreshClick()));
    connect(this, SIGNAL(askJoinConfirmation (const QString &)), this, SLOT(onJoinConfirmation(const QString &)), Qt::QueuedConnection);
    
    gameInLobby = false;
}

void PageRoomsList::setAdmin(bool flag)
{
    BtnAdmin->setVisible(flag);
}

void PageRoomsList::setRoomsList(const QStringList & list)
{
    QBrush red(QColor(255, 0, 0));
    QBrush orange(QColor(127, 127, 0));
    QBrush yellow(QColor(255, 255, 0));
    QBrush green(QColor(0, 255, 0));

    listFromServer = list;
    
    QString selection = "";
    
    if(QTableWidgetItem *item = roomsList->item(roomsList->currentRow(), 0))
        selection = item->text();
    
    roomsList->clear();
    roomsList->setColumnCount(7);
    roomsList->setHorizontalHeaderLabels(
            QStringList() <<
            QTableWidget::tr("Room Name") <<
            QTableWidget::tr("C") <<
            QTableWidget::tr("T") <<
            QTableWidget::tr("Owner") <<
            QTableWidget::tr("Map") <<
            QTableWidget::tr("Rules") <<
            QTableWidget::tr("Weapons")
            );

    // set minimum sizes
//  roomsList->horizontalHeader()->resizeSection(0, 200);
//  roomsList->horizontalHeader()->resizeSection(1, 50);
//  roomsList->horizontalHeader()->resizeSection(2, 50);
//  roomsList->horizontalHeader()->resizeSection(3, 100);
//  roomsList->horizontalHeader()->resizeSection(4, 100);
//  roomsList->horizontalHeader()->resizeSection(5, 100);
//  roomsList->horizontalHeader()->resizeSection(6, 100);

    // set resize modes
//  roomsList->horizontalHeader()->setResizeMode(QHeaderView::Interactive);

    bool gameCanBeJoined = true;

    if (list.size() % 8)
        return;

    roomsList->setRowCount(list.size() / 8);
    for(int i = 0, r = 0; i < list.size(); i += 8, r++)
    {
        // if we are joining a game
        // TODO: Should NOT be done here
        if (gameInLobby) {
            if (gameInLobbyName == list[i + 1]) {
                gameCanBeJoined = list[i].compare("True");
            }
        }
        
        // check filter settings
        #define NO_FILTER_MATCH roomsList->setRowCount(roomsList->rowCount() - 1); --r; continue
        
        if (list[i].compare("True") && CBState->currentIndex() == 2) { NO_FILTER_MATCH; }
        if (list[i].compare("False") && CBState->currentIndex() == 1) { NO_FILTER_MATCH; }
        if (CBRules->currentIndex() != 0 && list[i + 6].compare(CBRules->currentText())) { NO_FILTER_MATCH; }
        if (CBWeapons->currentIndex() != 0 && list[i + 7].compare(CBWeapons->currentText())) { NO_FILTER_MATCH; }
        bool found = list[i + 1].contains(searchText->text(), Qt::CaseInsensitive);
        if (!found) {
            for (int a = 4; a <= 7; ++a) {
                QString compString = list[i + a];
                if (a == 5 && compString == "+rnd+") {
                    compString = "Random Map";
                } else if (a == 5 && compString == "+maze+") {
                    compString = "Random Maze";
                } else if (a == 5 && compString == "+drawn+") {
                    compString = "Drawn Map";
                }
                if (compString.contains(searchText->text(), Qt::CaseInsensitive)) {
                    found = true;
                    break;
                }
            }
        }
        if (!searchText->text().isEmpty() && !found) { NO_FILTER_MATCH; }
        
        QTableWidgetItem * item;
        item = new QTableWidgetItem(list[i + 1]); // room name
        item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
        
        // pick appropriate room icon and tooltip (game in progress yes/no; later maybe locked rooms etc.)
        if(list[i].compare("True"))
        {
            item->setIcon(QIcon(":/res/iconTime.png"));// game is in lobby
            item->setToolTip(tr("This game is in lobby.\nYou may join and start playing once the game starts."));
        }
        else
        {
            item->setIcon(QIcon(":/res/iconDamage.png"));// game has started
            item->setToolTip(tr("This game is in progress.\nYou may join and spectate now but you'll have to wait for the game to end to start playing."));
        }

        roomsList->setItem(r, 0, item);

        item = new QTableWidgetItem(list[i + 2]); // number of clients
        item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
        item->setTextAlignment(Qt::AlignCenter);
        item->setToolTip(tr("There are %1 clients connected to this room.", "", list[i + 2].toInt()).arg(list[i + 2]));
        roomsList->setItem(r, 1, item);

        item = new QTableWidgetItem(list[i + 3]); // number of teams
        item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
        item->setTextAlignment(Qt::AlignCenter);
        item->setToolTip(tr("There are %1 teams participating in this room.", "", list[i + 3].toInt()).arg(list[i + 3]));
        //Should we highlight "full" games? Might get misinterpreted
        //if(list[i + 3].toInt() >= cMaxTeams)
        //    item->setForeground(red);
        roomsList->setItem(r, 2, item);

        item = new QTableWidgetItem(list[i + 4].left(15)); // name of host
        item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
        item->setToolTip(tr("%1 is the host. He may adjust settings and start the game.").arg(list[i + 4]));
        roomsList->setItem(r, 3, item);

        if(list[i + 5] == "+rnd+")
        {
            item = new QTableWidgetItem(tr("Random Map")); // selected map (is randomized)
// FIXME - need real icons. Disabling until then
//            item->setIcon(QIcon(":/res/mapRandom.png"));
        }
        else if (list[i+5] == "+maze+")
        {
            item = new QTableWidgetItem(tr("Random Maze"));
// FIXME - need real icons. Disabling until then
//            item->setIcon(QIcon(":/res/mapMaze.png"));
        }
        else
        {
            item = new QTableWidgetItem(list[i + 5]); // selected map
            
            // check to see if we've got this map
            // not perfect but a start
            if(!mapList->contains(list[i + 5]))
            {
                item->setForeground(red);
                item->setIcon(QIcon(":/res/mapMissing.png"));
            }
            else
            {
               // todo: mission icon?
// FIXME - need real icons. Disabling until then
//               item->setIcon(QIcon(":/res/mapCustom.png"));
            }
        }
        
        item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
        item->setToolTip(tr("Games may be played on precreated or randomized maps."));
        roomsList->setItem(r, 4, item);

        item = new QTableWidgetItem(list[i + 6].left(24)); // selected game scheme
        item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
        item->setToolTip(tr("The Game Scheme defines general options and preferences like Round Time, Sudden Death or Vampirism."));
        roomsList->setItem(r, 5, item);

        item = new QTableWidgetItem(list[i + 7].left(24)); // selected weapon scheme
        item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
        item->setToolTip(tr("The Weapon Scheme defines available weapons and their ammunition count."));
        roomsList->setItem(r, 6, item);

        if(!list[i + 1].compare(selection) && !selection.isEmpty())
            roomsList->selectionModel()->setCurrentIndex(roomsList->model()->index(r, 0), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
    }

    roomsList->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
    roomsList->horizontalHeader()->setResizeMode(1, QHeaderView::ResizeToContents);
    roomsList->horizontalHeader()->setResizeMode(2, QHeaderView::ResizeToContents);
    roomsList->horizontalHeader()->setResizeMode(3, QHeaderView::ResizeToContents);
    roomsList->horizontalHeader()->setResizeMode(4, QHeaderView::ResizeToContents);
    roomsList->horizontalHeader()->setResizeMode(5, QHeaderView::ResizeToContents);
    roomsList->horizontalHeader()->setResizeMode(6, QHeaderView::ResizeToContents);

    // TODO: Should NOT be done here
    if (gameInLobby) {
        gameInLobby = false;
        if (gameCanBeJoined) {
            emit askForJoinRoom(gameInLobbyName);
        } else {
            emit askJoinConfirmation(gameInLobbyName);
        }
    }

//  roomsList->resizeColumnsToContents();
}

void PageRoomsList::onCreateClick()
{
    if (roomName->text().size())
        emit askForCreateRoom(roomName->text());
    else
        QMessageBox::critical(this,
                tr("Error"),
                tr("Please enter room name"),
                tr("OK"));
}

void PageRoomsList::onJoinClick()
{
    QTableWidgetItem * curritem = roomsList->item(roomsList->currentRow(), 0);
    if (!curritem)
    {
        QMessageBox::critical(this,
                tr("Error"),
                tr("Please select room from the list"),
                tr("OK"));
        return;
    }

    for (int i = 0; i < listFromServer.size(); i += 8) {
        if (listFromServer[i + 1] == curritem->data(Qt::DisplayRole).toString()) {
            gameInLobby = listFromServer[i].compare("True");
            break;
        }
    }
    
    if (gameInLobby) {
        gameInLobbyName = curritem->data(Qt::DisplayRole).toString();
        emit askForRoomList();
    } else {
        emit askForJoinRoom(curritem->data(Qt::DisplayRole).toString());
    }
}

void PageRoomsList::onRefreshClick()
{
    emit askForRoomList();
}

void PageRoomsList::onClearClick()
{
    CBState->setCurrentIndex(0);
    CBRules->setCurrentIndex(0);
    CBWeapons->setCurrentIndex(0);
    searchText->clear();
}

void PageRoomsList::onJoinConfirmation(const QString & room)
{
    if (QMessageBox::warning(this,
        tr("Warning"),
        tr("The game you are trying to join has started.\nDo you still want to join the room?"),
        QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
    {
        emit askForJoinRoom(room);
    }
}

void PageRoomsList::updateNickCounter(int cnt)
{
    lblCount->setText(tr("%1 players online", 0, cnt).arg(cnt));
}