2008-01-20 19:40:12 +01:00
|
|
|
/*****************************************************************************
|
|
|
|
* Eliot
|
2012-10-07 16:25:41 +02:00
|
|
|
* Copyright (C) 2008-2012 Olivier Teulière
|
2008-01-20 19:40:12 +01:00
|
|
|
* Authors: Olivier Teulière <ipkiss @@ 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; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
|
2013-09-25 22:23:01 +02:00
|
|
|
#include <QHBoxLayout>
|
|
|
|
#include <QStringList>
|
2008-01-20 19:40:12 +01:00
|
|
|
|
|
|
|
#include "player_widget.h"
|
2009-02-19 19:25:17 +01:00
|
|
|
#include "play_word_mediator.h"
|
2012-01-19 15:19:11 +01:00
|
|
|
#include "validator_factory.h"
|
2008-01-20 19:40:12 +01:00
|
|
|
#include "qtcommon.h"
|
2008-11-30 21:53:44 +01:00
|
|
|
#include "public_game.h"
|
2008-01-20 19:40:12 +01:00
|
|
|
#include "player.h"
|
|
|
|
#include "pldrack.h"
|
|
|
|
#include "coord.h"
|
2012-12-18 00:48:14 +01:00
|
|
|
#include "play_model.h"
|
2008-01-20 19:40:12 +01:00
|
|
|
#include "dic.h"
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
#include "encoding.h"
|
|
|
|
|
|
|
|
|
2012-02-18 22:26:52 +01:00
|
|
|
INIT_LOGGER(qt, PlayerWidget);
|
|
|
|
|
|
|
|
|
2012-12-18 00:48:14 +01:00
|
|
|
PlayerWidget::PlayerWidget(QWidget *parent, PlayModel &iPlayModel,
|
2009-02-19 19:25:17 +01:00
|
|
|
unsigned int iPlayerNb, PublicGame *iGame)
|
2008-01-20 19:40:12 +01:00
|
|
|
: QWidget(parent), m_game(iGame), m_player(iPlayerNb)
|
|
|
|
{
|
|
|
|
setupUi(this);
|
2009-02-19 19:25:17 +01:00
|
|
|
|
|
|
|
// Use the mediator
|
|
|
|
m_mediator = new PlayWordMediator(this, *lineEditPlay, *lineEditCoords,
|
2013-01-14 01:16:20 +01:00
|
|
|
lineEditPoints, *pushButtonPlay,
|
2012-12-18 00:48:14 +01:00
|
|
|
iPlayModel, iGame);
|
2009-02-19 19:25:17 +01:00
|
|
|
QObject::connect(m_mediator, SIGNAL(gameUpdated()),
|
|
|
|
this, SIGNAL(gameUpdated()));
|
|
|
|
QObject::connect(m_mediator, SIGNAL(notifyProblem(QString)),
|
|
|
|
this, SIGNAL(notifyProblem(QString)));
|
2008-01-20 19:40:12 +01:00
|
|
|
|
2012-10-06 12:16:36 +02:00
|
|
|
QObject::connect(pushButtonShuffle, SIGNAL(clicked()),
|
|
|
|
this, SLOT(shuffle()));
|
|
|
|
QObject::connect(pushButtonPass, SIGNAL(clicked()),
|
|
|
|
this, SLOT(pass()));
|
|
|
|
QObject::connect(pushButtonChange, SIGNAL(clicked()),
|
|
|
|
this, SLOT(changeLetters()));
|
|
|
|
QObject::connect(lineEditChange, SIGNAL(returnPressed()),
|
|
|
|
this, SLOT(changeLetters()));
|
|
|
|
QObject::connect(lineEditChange, SIGNAL(textChanged(const QString&)),
|
|
|
|
this, SLOT(enableChangeButton()));
|
|
|
|
|
2012-01-19 11:07:05 +01:00
|
|
|
lineEditRack->setReadOnly(true);
|
|
|
|
|
2008-01-20 19:40:12 +01:00
|
|
|
if (m_game)
|
|
|
|
{
|
|
|
|
// Do not allow messing with AI players
|
|
|
|
if (!m_game->getPlayer(m_player).isHuman())
|
|
|
|
setEnabled(false);
|
|
|
|
}
|
2008-11-30 21:53:44 +01:00
|
|
|
if (m_game == NULL || m_game->getMode() != PublicGame::kFREEGAME)
|
2008-01-20 19:40:12 +01:00
|
|
|
{
|
|
|
|
// Hide the freegame-specific controls
|
|
|
|
labelChange->hide();
|
|
|
|
lineEditChange->hide();
|
|
|
|
pushButtonChange->hide();
|
|
|
|
pushButtonPass->hide();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-01-19 15:19:11 +01:00
|
|
|
QValidator * val = ValidatorFactory::newChangeValidator(this, *lineEditRack, m_game->getDic());
|
|
|
|
lineEditChange->setValidator(val);
|
2008-01-20 19:40:12 +01:00
|
|
|
}
|
|
|
|
|
2012-10-06 13:28:48 +02:00
|
|
|
// When the widget gains the focus, transfer it
|
|
|
|
// to the "main" line edit by default
|
|
|
|
setFocusProxy(lineEditPlay);
|
|
|
|
|
2008-01-20 19:40:12 +01:00
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QSize PlayerWidget::sizeHint() const
|
|
|
|
{
|
|
|
|
return QSize(100, 100);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PlayerWidget::refresh()
|
|
|
|
{
|
|
|
|
if (m_game == NULL)
|
|
|
|
{
|
|
|
|
lineEditRack->clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const PlayedRack &pld = m_game->getPlayer(m_player).getCurrentRack();
|
|
|
|
lineEditRack->setText(qfw(pld.toString(PlayedRack::RACK_EXTRA)));
|
|
|
|
lineEditPlay->clear();
|
2008-09-07 23:06:17 +02:00
|
|
|
lineEditCoords->clear();
|
2008-01-20 19:40:12 +01:00
|
|
|
lineEditChange->clear();
|
2008-09-14 19:56:18 +02:00
|
|
|
|
2013-01-29 22:55:20 +01:00
|
|
|
if (!m_game->isLastTurn() || m_game->isFinished())
|
2008-11-30 22:08:29 +01:00
|
|
|
{
|
|
|
|
// Do not allow entering a move when displaying an old turn
|
|
|
|
setEnabled(false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Do not allow messing with AI players or with players
|
|
|
|
// who already played
|
|
|
|
setEnabled(!m_game->hasPlayed(m_player) &&
|
|
|
|
m_game->getPlayer(m_player).isHuman());
|
|
|
|
}
|
2008-01-20 19:40:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-06 12:16:36 +02:00
|
|
|
void PlayerWidget::shuffle()
|
2008-01-20 19:40:12 +01:00
|
|
|
{
|
2008-09-14 19:56:18 +02:00
|
|
|
m_game->shuffleRack();
|
|
|
|
emit gameUpdated();
|
2012-10-06 13:28:48 +02:00
|
|
|
m_mediator->setCleverFocus();
|
2008-01-20 19:40:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-06 12:16:36 +02:00
|
|
|
void PlayerWidget::enableChangeButton()
|
2008-01-20 19:40:12 +01:00
|
|
|
{
|
|
|
|
pushButtonChange->setEnabled(lineEditChange->hasAcceptableInput() &&
|
|
|
|
lineEditChange->text() != "");
|
2011-07-17 01:31:17 +02:00
|
|
|
// Force the letters to be in upper case
|
2011-01-15 17:42:20 +01:00
|
|
|
lineEditChange->setText(lineEditChange->text().toUpper());
|
2008-01-20 19:40:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-06 12:16:36 +02:00
|
|
|
void PlayerWidget::changeLetters()
|
2008-01-20 19:40:12 +01:00
|
|
|
{
|
2008-11-30 21:53:44 +01:00
|
|
|
ASSERT(m_game->getMode() == PublicGame::kFREEGAME,
|
2011-01-15 17:33:02 +01:00
|
|
|
"Trying to change letters while not in free game mode");
|
2008-01-25 19:42:59 +01:00
|
|
|
|
2012-10-06 12:16:36 +02:00
|
|
|
helperChangePass(lineEditChange->text());
|
2011-01-15 17:33:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-06 12:16:36 +02:00
|
|
|
void PlayerWidget::pass()
|
2011-01-15 17:33:02 +01:00
|
|
|
{
|
|
|
|
ASSERT(m_game->getMode() == PublicGame::kFREEGAME,
|
|
|
|
"Trying to pass while not in free game mode");
|
|
|
|
|
2012-10-06 12:16:36 +02:00
|
|
|
helperChangePass("");
|
2011-01-15 17:33:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-06 12:16:36 +02:00
|
|
|
void PlayerWidget::helperChangePass(QString inputLetters)
|
2011-01-15 17:33:02 +01:00
|
|
|
{
|
2009-06-27 20:09:44 +02:00
|
|
|
// Convert the input string into an internal one
|
|
|
|
const wstring &letters =
|
2011-07-30 21:45:18 +02:00
|
|
|
m_game->getDic().convertFromInput(wfq(inputLetters));
|
2011-01-15 17:33:02 +01:00
|
|
|
|
2008-01-25 19:42:59 +01:00
|
|
|
// Pass the turn (and possibly change letters)
|
2009-06-27 20:09:44 +02:00
|
|
|
int res = m_game->freeGamePass(letters);
|
2008-01-25 19:42:59 +01:00
|
|
|
if (res == 0)
|
2012-10-06 13:28:48 +02:00
|
|
|
{
|
2008-01-25 19:42:59 +01:00
|
|
|
emit gameUpdated();
|
2012-10-06 13:28:48 +02:00
|
|
|
m_mediator->setCleverFocus();
|
|
|
|
}
|
2008-01-25 19:42:59 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
QString msg;
|
2009-06-27 20:09:44 +02:00
|
|
|
if (inputLetters == "")
|
2011-01-10 23:06:10 +01:00
|
|
|
msg = _q("Cannot pass turn:\n%1");
|
2008-01-25 19:42:59 +01:00
|
|
|
else
|
2011-01-10 23:06:10 +01:00
|
|
|
msg = _q("Cannot change letters '%1':\n%2").arg(inputLetters);
|
|
|
|
if (res == 1)
|
|
|
|
msg = msg.arg(_q("Changing letters is not allowed when there are less than 7 tiles left in the bag"));
|
|
|
|
else if (res == 2)
|
|
|
|
msg = msg.arg(_q("The rack of the current player does not contain all the listed letters"));
|
|
|
|
else if (res == 3)
|
|
|
|
msg = msg.arg(_q("The game is already finished!"));
|
2012-10-06 11:52:31 +02:00
|
|
|
else if (res == 4)
|
2011-01-10 23:06:10 +01:00
|
|
|
msg = msg.arg(_q("Some letters are invalid for the current dictionary"));
|
|
|
|
else
|
2011-01-15 17:35:36 +01:00
|
|
|
msg = msg.arg(_q("Unknown error"));
|
2008-01-25 19:42:59 +01:00
|
|
|
emit notifyProblem(msg);
|
|
|
|
}
|
2008-01-20 19:40:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-12-18 00:48:14 +01:00
|
|
|
PlayerTabWidget::PlayerTabWidget(PlayModel &iPlayModel, QWidget *parent)
|
|
|
|
: QTabWidget(parent), m_game(NULL), m_playModel(iPlayModel)
|
2008-01-22 16:30:20 +01:00
|
|
|
{
|
2008-09-14 19:56:18 +02:00
|
|
|
QObject::connect(this, SIGNAL(currentChanged(int)),
|
|
|
|
this, SLOT(changeCurrentPlayer(int)));
|
2008-01-22 16:30:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-30 21:53:44 +01:00
|
|
|
void PlayerTabWidget::setGame(PublicGame *iGame)
|
2008-01-22 16:30:20 +01:00
|
|
|
{
|
2008-09-14 19:56:18 +02:00
|
|
|
m_game = iGame;
|
|
|
|
|
2008-01-24 21:18:00 +01:00
|
|
|
// Remove all the tabs
|
|
|
|
int nbTabs = count();
|
2013-01-09 17:55:35 +01:00
|
|
|
blockSignals(true);
|
2008-01-24 21:18:00 +01:00
|
|
|
for (int i = 0; i < nbTabs; ++i)
|
2008-01-25 19:42:59 +01:00
|
|
|
{
|
2008-01-26 17:58:46 +01:00
|
|
|
setCurrentIndex(0);
|
2008-01-25 19:42:59 +01:00
|
|
|
// Cut all the connections with the page (needed because removeTab()
|
|
|
|
// doesn't really destroy the widget)
|
|
|
|
disconnect(currentWidget());
|
2008-01-24 21:18:00 +01:00
|
|
|
removeTab(0);
|
2008-01-25 19:42:59 +01:00
|
|
|
}
|
2013-01-09 17:55:35 +01:00
|
|
|
blockSignals(false);
|
2008-01-22 16:30:20 +01:00
|
|
|
|
2008-01-24 21:18:00 +01:00
|
|
|
if (iGame != NULL)
|
2008-01-22 16:30:20 +01:00
|
|
|
{
|
2013-01-09 17:55:35 +01:00
|
|
|
blockSignals(true);
|
2012-01-19 11:07:05 +01:00
|
|
|
// Add one tab per player
|
|
|
|
for (unsigned int i = 0; i < iGame->getNbPlayers(); ++i)
|
2008-01-22 16:30:20 +01:00
|
|
|
{
|
2012-01-19 11:07:05 +01:00
|
|
|
const Player &player = iGame->getPlayer(i);
|
2012-12-18 00:48:14 +01:00
|
|
|
PlayerWidget *p = new PlayerWidget(NULL, m_playModel, i, iGame);
|
2012-01-19 11:07:05 +01:00
|
|
|
QObject::connect(this, SIGNAL(refreshSignal()), p, SLOT(refresh()));
|
2008-01-27 00:03:32 +01:00
|
|
|
// Forward signals to the outside
|
2012-01-19 11:07:05 +01:00
|
|
|
QObject::connect(p, SIGNAL(notifyProblem(QString)),
|
2008-01-27 00:03:32 +01:00
|
|
|
this, SIGNAL(notifyProblem(QString)));
|
2012-01-19 11:07:05 +01:00
|
|
|
QObject::connect(p, SIGNAL(gameUpdated()),
|
2008-01-24 21:18:00 +01:00
|
|
|
this, SIGNAL(gameUpdated()));
|
2012-01-19 11:07:05 +01:00
|
|
|
addTab(p, qfw(player.getName()));
|
|
|
|
// Switching to a tab corresponding to an AI player
|
|
|
|
// is forbidden
|
|
|
|
if (!player.isHuman())
|
|
|
|
setTabEnabled(i, false);
|
2008-01-22 16:30:20 +01:00
|
|
|
}
|
2012-01-19 11:07:05 +01:00
|
|
|
setCurrentIndex(iGame->getCurrentPlayer().getId());
|
2013-01-09 17:55:35 +01:00
|
|
|
blockSignals(false);
|
2008-01-22 16:30:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PlayerTabWidget::refresh()
|
|
|
|
{
|
2008-09-14 19:56:18 +02:00
|
|
|
if (m_game)
|
2008-11-30 21:53:44 +01:00
|
|
|
setCurrentIndex(m_game->getCurrentPlayer().getId());
|
2008-01-22 16:30:20 +01:00
|
|
|
emit refreshSignal();
|
2012-10-06 13:28:48 +02:00
|
|
|
|
|
|
|
// Give the focus to the current widget. Without this, the widget does
|
|
|
|
// not get focus in some cases
|
|
|
|
currentWidget()->setFocus();
|
2008-01-22 16:30:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-14 19:56:18 +02:00
|
|
|
void PlayerTabWidget::changeCurrentPlayer(int p)
|
|
|
|
{
|
2013-01-09 17:55:35 +01:00
|
|
|
#if 0
|
2008-11-30 21:54:57 +01:00
|
|
|
// This method is triggered somehow when creating a Duplicate game
|
|
|
|
// after a FreeGame one. The next line avoids crashing in this case...
|
|
|
|
if (m_game == NULL)
|
|
|
|
return;
|
2013-01-09 17:55:35 +01:00
|
|
|
#endif
|
2008-11-30 21:54:57 +01:00
|
|
|
|
2012-12-18 00:48:14 +01:00
|
|
|
m_playModel.clear();
|
2009-02-19 19:25:17 +01:00
|
|
|
|
2008-09-14 19:56:18 +02:00
|
|
|
// Change the active player when the active tab changes
|
|
|
|
// (only in duplicate mode)
|
2008-11-30 21:53:44 +01:00
|
|
|
if (m_game->getMode() == PublicGame::kDUPLICATE &&
|
|
|
|
widget(p)->isEnabled())
|
2008-09-14 19:56:18 +02:00
|
|
|
{
|
2008-11-30 21:53:44 +01:00
|
|
|
m_game->duplicateSetPlayer(p);
|
2013-01-09 17:55:35 +01:00
|
|
|
emit gameUpdated();
|
2008-09-14 19:56:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|