Arbitration mode: allow editing the rack manually

This commit is contained in:
Olivier Teulière 2012-03-11 00:19:36 +01:00
parent 25a36ec9cd
commit 0fa7bc91c6
8 changed files with 120 additions and 27 deletions

View file

@ -64,7 +64,7 @@ void Arbitration::setRackManual(const wstring &iLetters)
wstring upperLetters = iLetters; wstring upperLetters = iLetters;
std::transform(upperLetters.begin(), upperLetters.end(), std::transform(upperLetters.begin(), upperLetters.end(),
upperLetters.begin(), towupper); upperLetters.begin(), towupper);
const PlayedRack &newRack = helperSetRackManual(true, upperLetters); const PlayedRack &newRack = helperSetRackManual(false, upperLetters);
setGameAndPlayersRack(newRack); setGameAndPlayersRack(newRack);
// Clear the results if everything went well // Clear the results if everything went well

View file

@ -68,6 +68,15 @@ ArbitrationWidget::ArbitrationWidget(QWidget *parent,
splitter->setStretchFactor(1, 2); splitter->setStretchFactor(1, 2);
// FIXME arbitration end // FIXME arbitration end
blackPalette = lineEditRack->palette();
redPalette = lineEditRack->palette();
redPalette.setColor(QPalette::Text, Qt::red);
// Define validators
QValidator * val =
ValidatorFactory::newRackValidator(this, m_game->getBag(),
true, &m_game->getHistory());
lineEditRack->setValidator(val);
lineEditCoords->setValidator(ValidatorFactory::newCoordsValidator(this)); lineEditCoords->setValidator(ValidatorFactory::newCoordsValidator(this));
// Associate a model to the players view. // Associate a model to the players view.
@ -117,6 +126,9 @@ ArbitrationWidget::ArbitrationWidget(QWidget *parent,
treeViewResults->setColumnWidth(1, 40); treeViewResults->setColumnWidth(1, 40);
treeViewResults->setColumnWidth(2, 70); treeViewResults->setColumnWidth(2, 70);
// Validate manual rack changes
QObject::connect(lineEditRack, SIGNAL(textEdited(const QString&)),
this, SLOT(rackEdited(const QString&)));
// Propagate the information on rack change // Propagate the information on rack change
QObject::connect(lineEditRack, SIGNAL(textChanged(const QString&)), QObject::connect(lineEditRack, SIGNAL(textChanged(const QString&)),
this, SIGNAL(rackUpdated(const QString&))); this, SIGNAL(rackUpdated(const QString&)));
@ -390,7 +402,8 @@ int ArbitrationWidget::addSingleMove(const Move &iMove, int moveType,
void ArbitrationWidget::setRackRandom() void ArbitrationWidget::setRackRandom()
{ {
ASSERT(m_game->isLastTurn(), "The Random button should have been disabled"); ASSERT(m_game->isLastTurn(),
"The Random button should only be active in the last turn");
// Warn if some players have already played // Warn if some players have already played
bool someoneHasPlayed = false; bool someoneHasPlayed = false;
@ -421,6 +434,57 @@ void ArbitrationWidget::setRackRandom()
} }
void ArbitrationWidget::rackEdited(const QString &iText)
{
ASSERT(m_game->isLastTurn(),
"Rack edition button should only be active in the last turn");
// Warn if some players have already played
bool someoneHasPlayed = false;
for (unsigned int i = 0; i < m_game->getNbPlayers(); ++i)
{
if (m_game->hasPlayed(i))
someoneHasPlayed = true;
}
if (someoneHasPlayed)
{
QString msg = _q("Some player(s) already have an assigned move. "
"These moves will be lost if you change the rack.");
QString question = _q("Do you really want to change the rack?");
if (!QtCommon::requestConfirmation(msg, question))
{
// Restore the rack (visually)
const PlayedRack &pldRack = m_game->getHistory().getCurrentRack();
QString qrack = qfw(pldRack.toString(PlayedRack::RACK_SIMPLE));
lineEditRack->setText(qrack);
return;
}
}
m_game->removeTestRound();
if (!lineEditRack->hasAcceptableInput())
{
lineEditRack->setPalette(redPalette);
return;
}
try
{
lineEditRack->setPalette(blackPalette);
const wstring &input = m_game->getDic().convertFromInput(wfq(iText));
m_game->arbitrationSetRackManual(input);
buttonSearch->setEnabled(m_resultsModel->rowCount() == 0 &&
lineEditRack->text() != "");
emit gameUpdated();
}
catch (std::exception &e)
{
lineEditRack->setPalette(redPalette);
emit notifyProblem(_q("Warning: Cannot set the rack to '%1':\n%2").arg(iText).arg(e.what()));
}
}
void ArbitrationWidget::resultsFilterChanged(const QString &iFilter) void ArbitrationWidget::resultsFilterChanged(const QString &iFilter)
{ {
treeViewResults->clearSelection(); treeViewResults->clearSelection();

View file

@ -58,6 +58,7 @@ public slots:
private slots: private slots:
void setRackRandom(); void setRackRandom();
void rackEdited(const QString &);
void on_buttonSearch_clicked(); void on_buttonSearch_clicked();
void on_checkBoxHideAssigned_toggled(bool); void on_checkBoxHideAssigned_toggled(bool);
void resultsFilterChanged(const QString &); void resultsFilterChanged(const QString &);
@ -100,6 +101,12 @@ private:
/// Container for the moves manually entered in the interface /// Container for the moves manually entered in the interface
QVector<Move> m_addedMoves; QVector<Move> m_addedMoves;
/// Palette to write text in black
QPalette blackPalette;
/// Palette to write text in red
QPalette redPalette;
/// Force synchronizing the model with the search results /// Force synchronizing the model with the search results
void updateResultsModel(); void updateResultsModel();
/// Force synchronizing the model with the players /// Force synchronizing the model with the players

View file

@ -49,10 +49,9 @@ TrainingWidget::TrainingWidget(QWidget *parent, CoordModel &iCoordModel, PublicG
setupUi(this); setupUi(this);
treeViewResults->setAlternatingRowColors(true); treeViewResults->setAlternatingRowColors(true);
blackPalette = lineEditRack->palette();
redPalette = lineEditRack->palette(); redPalette = lineEditRack->palette();
redPalette.setColor(QPalette::Text, Qt::red); redPalette.setColor(QPalette::Text, Qt::red);
blackPalette = lineEditRack->palette();
blackPalette.setColor(QPalette::Text, Qt::black);
// Use the mediator // Use the mediator
m_mediator = new PlayWordMediator(this, *lineEditPlay, *lineEditCoords, m_mediator = new PlayWordMediator(this, *lineEditPlay, *lineEditCoords,
@ -109,7 +108,7 @@ TrainingWidget::TrainingWidget(QWidget *parent, CoordModel &iCoordModel, PublicG
if (m_game) if (m_game)
{ {
QValidator * val = ValidatorFactory::newRackValidator(this, &m_game->getBag()); QValidator * val = ValidatorFactory::newRackValidator(this, m_game->getBag());
lineEditRack->setValidator(val); lineEditRack->setValidator(val);
} }
@ -273,7 +272,6 @@ void TrainingWidget::lockSizesChanged(bool checked)
void TrainingWidget::on_lineEditRack_textEdited(const QString &iText) void TrainingWidget::on_lineEditRack_textEdited(const QString &iText)
{ {
// FIXME: first parameter is hardcoded
m_game->removeTestRound(); m_game->removeTestRound();
if (!lineEditRack->hasAcceptableInput()) if (!lineEditRack->hasAcceptableInput())
{ {
@ -292,7 +290,7 @@ void TrainingWidget::on_lineEditRack_textEdited(const QString &iText)
catch (std::exception &e) catch (std::exception &e)
{ {
lineEditRack->setPalette(redPalette); lineEditRack->setPalette(redPalette);
emit notifyProblem(_q("Warning: Cannot set the rack to '%1'").arg(iText)); emit notifyProblem(_q("Warning: Cannot set the rack to '%1'\n%2").arg(iText).arg(e.what()));
} }
} }

View file

@ -84,12 +84,12 @@ private:
/// Mediator for the "play word" controls /// Mediator for the "play word" controls
PlayWordMediator *m_mediator; PlayWordMediator *m_mediator;
/// Palette to write text in red
QPalette redPalette;
/// Palette to write text in black /// Palette to write text in black
QPalette blackPalette; QPalette blackPalette;
/// Palette to write text in red
QPalette redPalette;
/// Popup menu for words definition /// Popup menu for words definition
CustomPopup *m_customPopup; CustomPopup *m_customPopup;

View file

@ -16,7 +16,7 @@
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<widget class="QWidget" name=""> <widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout_5"> <layout class="QVBoxLayout" name="verticalLayout_5">
<item> <item>
<widget class="QGroupBox" name="groupBox_3"> <widget class="QGroupBox" name="groupBox_3">
@ -39,9 +39,6 @@
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item> <item>

View file

@ -27,6 +27,8 @@
#include "dic.h" #include "dic.h"
#include "bag.h" #include "bag.h"
#include "coord.h" #include "coord.h"
#include "history.h"
#include "pldrack.h"
// TODO: There is probably a good potential for code factorization in this file // TODO: There is probably a good potential for code factorization in this file
@ -103,30 +105,33 @@ QValidator *ValidatorFactory::newChangeValidator(QObject *parent,
class RackValidator: public QValidator class RackValidator: public QValidator
{ {
public: public:
explicit RackValidator(QObject *parent, const Bag *iBag); RackValidator(QObject *parent, const Bag &iBag,
const History *iHistory, bool checkDuplicate);
virtual State validate(QString &input, int &pos) const; virtual State validate(QString &input, int &pos) const;
private: private:
const Bag *m_bag; const Bag &m_bag;
const History *m_history;
bool m_checkDuplicate;
}; };
RackValidator::RackValidator(QObject *parent, const Bag *iBag) RackValidator::RackValidator(QObject *parent, const Bag &iBag,
: QValidator(parent), m_bag(iBag) const History *iHistory, bool checkDuplicate)
: QValidator(parent), m_bag(iBag),
m_history(iHistory), m_checkDuplicate(checkDuplicate)
{ {
} }
QValidator::State RackValidator::validate(QString &input, int &) const QValidator::State RackValidator::validate(QString &input, int &) const
{ {
// This should never happen, since the control should be disabled in if (input == "")
// such a case, but checking doesn't hurt... return Intermediate;
if (m_bag == NULL)
return Invalid;
input = input.toUpper(); input = input.toUpper();
const Dictionary &dic = m_bag->getDic(); const Dictionary &dic = m_bag.getDic();
// The string is invalid if it contains invalid input characters // The string is invalid if it contains invalid input characters
const wistring &winput = wfq(input); const wistring &winput = wfq(input);
@ -145,19 +150,38 @@ QValidator::State RackValidator::validate(QString &input, int &) const
for (int i = 0; i < qinput.size(); ++i) for (int i = 0; i < qinput.size(); ++i)
{ {
if ((unsigned int)qinput.count(qinput[i], Qt::CaseInsensitive) > if ((unsigned int)qinput.count(qinput[i], Qt::CaseInsensitive) >
m_bag->in(intInput[i])) m_bag.in(intInput[i]))
{ {
return Invalid; return Invalid;
} }
} }
// Check that the rack has 2 consonants and 2 vocals
if (m_checkDuplicate)
{
PlayedRack pld;
pld.setManual(intInput);
int min;
if (m_bag.getNbVowels() > 1 && m_bag.getNbConsonants() > 1
&& m_history->getSize() < 15)
min = 2;
else
min = 1;
if (!pld.checkRack(min, min))
return Intermediate;
}
return Acceptable; return Acceptable;
} }
QValidator *ValidatorFactory::newRackValidator(QObject *parent, QValidator *ValidatorFactory::newRackValidator(QObject *parent,
const Bag *iBag) const Bag &iBag,
bool checkDuplicate,
const History *iHistory)
{ {
return new RackValidator(parent, iBag); return new RackValidator(parent, iBag, iHistory, checkDuplicate);
} }
// }}} // }}}

View file

@ -28,6 +28,7 @@ class QValidator;
class QLineEdit; class QLineEdit;
class Dictionary; class Dictionary;
class Bag; class Bag;
class History;
class ValidatorFactory: public QObject class ValidatorFactory: public QObject
@ -48,7 +49,9 @@ public:
* Create a validator suitable for setting rack letters. * Create a validator suitable for setting rack letters.
*/ */
static QValidator *newRackValidator(QObject *parent, static QValidator *newRackValidator(QObject *parent,
const Bag *iBag); const Bag &iBag,
bool checkDuplicate = false,
const History *iHistory = 0);
/** /**
* Create a validator suitable for setting rack letters * Create a validator suitable for setting rack letters