2008-01-24 21:18:00 +01:00
|
|
|
/*****************************************************************************
|
|
|
|
* Eliot
|
2011-07-28 22:55:48 +02:00
|
|
|
* Copyright (C) 2010-2011 Olivier Teulière
|
2008-01-24 21:18:00 +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
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include <QtGui/QStandardItemModel>
|
|
|
|
#include <QtGui/QValidator>
|
2011-07-30 15:15:52 +02:00
|
|
|
#include <QtGui/QHeaderView>
|
2008-01-24 21:18:00 +01:00
|
|
|
|
|
|
|
#include "training_widget.h"
|
|
|
|
#include "qtcommon.h"
|
2009-02-19 19:25:17 +01:00
|
|
|
#include "play_word_mediator.h"
|
2011-07-28 22:55:48 +02:00
|
|
|
#include "custom_popup.h"
|
2009-02-19 19:25:17 +01:00
|
|
|
|
2008-01-27 00:03:32 +01:00
|
|
|
#include "dic.h"
|
2008-11-30 21:53:44 +01:00
|
|
|
#include "bag.h"
|
|
|
|
#include "public_game.h"
|
2008-11-22 14:09:28 +01:00
|
|
|
#include "game_exception.h"
|
2008-01-24 21:18:00 +01:00
|
|
|
#include "player.h"
|
|
|
|
#include "results.h"
|
2012-01-12 17:43:57 +01:00
|
|
|
#include "debug.h"
|
2008-01-24 21:18:00 +01:00
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
2010-07-11 22:58:41 +02:00
|
|
|
static const int HIDDEN_COLUMN = 6;
|
|
|
|
|
2008-01-24 21:18:00 +01:00
|
|
|
/// Validator used for the rack line edit
|
|
|
|
class RackValidator: public QValidator
|
|
|
|
{
|
|
|
|
public:
|
2009-02-19 19:25:17 +01:00
|
|
|
explicit RackValidator(QObject *parent, const Bag *iBag);
|
2008-01-24 21:18:00 +01:00
|
|
|
virtual State validate(QString &input, int &pos) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
const Bag *m_bag;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2009-02-19 19:25:17 +01:00
|
|
|
TrainingWidget::TrainingWidget(QWidget *parent, CoordModel &iCoordModel, PublicGame *iGame)
|
2011-07-17 11:09:47 +02:00
|
|
|
: QWidget(parent), m_game(iGame), m_autoResizeColumns(true)
|
2008-01-24 21:18:00 +01:00
|
|
|
{
|
|
|
|
setupUi(this);
|
2010-07-11 22:59:05 +02:00
|
|
|
treeViewResults->setAlternatingRowColors(true);
|
2008-01-24 21:18:00 +01:00
|
|
|
|
2009-06-27 20:09:44 +02:00
|
|
|
redPalette = lineEditRack->palette();
|
|
|
|
redPalette.setColor(QPalette::Text, Qt::red);
|
|
|
|
blackPalette = lineEditRack->palette();
|
|
|
|
blackPalette.setColor(QPalette::Text, Qt::black);
|
|
|
|
|
2009-02-19 19:25:17 +01:00
|
|
|
// Use the mediator
|
|
|
|
m_mediator = new PlayWordMediator(this, *lineEditPlay, *lineEditCoords,
|
2011-07-17 01:31:17 +02:00
|
|
|
*lineEditPoints, *pushButtonPlay,
|
|
|
|
iCoordModel, m_game);
|
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-24 21:18:00 +01:00
|
|
|
// Associate the model to the view
|
|
|
|
m_model = new QStandardItemModel(this);
|
|
|
|
treeViewResults->setModel(m_model);
|
2010-07-11 22:58:41 +02:00
|
|
|
m_model->setColumnCount(7);
|
2008-01-24 21:18:00 +01:00
|
|
|
m_model->setHeaderData(0, Qt::Horizontal, _q("Word"), Qt::DisplayRole);
|
|
|
|
m_model->setHeaderData(1, Qt::Horizontal, _q("Ref"), Qt::DisplayRole);
|
|
|
|
m_model->setHeaderData(2, Qt::Horizontal, _q("Points"), Qt::DisplayRole);
|
|
|
|
m_model->setHeaderData(3, Qt::Horizontal, "*", Qt::DisplayRole);
|
|
|
|
m_model->setHeaderData(4, Qt::Horizontal, "", Qt::DisplayRole);
|
2008-01-27 00:03:32 +01:00
|
|
|
m_model->setHeaderData(5, Qt::Horizontal, "", Qt::DisplayRole);
|
2010-07-11 22:58:41 +02:00
|
|
|
// Hidden column, used to store internal data
|
|
|
|
m_model->setHeaderData(HIDDEN_COLUMN, Qt::Horizontal, "", Qt::DisplayRole);
|
|
|
|
treeViewResults->setColumnHidden(HIDDEN_COLUMN, true);
|
2008-01-24 21:18:00 +01:00
|
|
|
|
2011-07-17 11:09:47 +02:00
|
|
|
// Add a context menu to the tree header
|
|
|
|
QAction *lockSizesAction = new QAction(_q("Lock columns sizes"), this);
|
|
|
|
lockSizesAction->setCheckable(true);
|
|
|
|
lockSizesAction->setStatusTip(_q("Disable auto-resizing of the columns"));
|
|
|
|
treeViewResults->header()->addAction(lockSizesAction);
|
|
|
|
treeViewResults->header()->setContextMenuPolicy(Qt::ActionsContextMenu);
|
|
|
|
QObject::connect(lockSizesAction, SIGNAL(toggled(bool)),
|
|
|
|
this, SLOT(lockSizesChanged(bool)));
|
|
|
|
|
2011-07-28 22:55:48 +02:00
|
|
|
// Add another context menu for the results
|
|
|
|
m_customPopup = new CustomPopup(treeViewResults);
|
|
|
|
QObject::connect(m_customPopup, SIGNAL(popupCreated(QMenu&, const QPoint&)),
|
|
|
|
this, SLOT(populateMenu(QMenu&, const QPoint&)));
|
|
|
|
QObject::connect(m_customPopup, SIGNAL(requestDefinition(QString)),
|
|
|
|
this, SIGNAL(requestDefinition(QString)));
|
|
|
|
|
2011-07-17 11:16:52 +02:00
|
|
|
// Allow very thin columns
|
|
|
|
treeViewResults->header()->setMinimumSectionSize(1);
|
|
|
|
|
2008-01-24 21:18:00 +01:00
|
|
|
// Enable the Play button only when there is a selection in the tree
|
|
|
|
QObject::connect(treeViewResults->selectionModel(),
|
|
|
|
SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
|
|
|
|
this,
|
|
|
|
SLOT(enablePlayButton(const QItemSelection&, const QItemSelection&)));
|
|
|
|
// Display a preview of the selected word on the board
|
|
|
|
QObject::connect(treeViewResults->selectionModel(),
|
|
|
|
SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
|
|
|
|
this,
|
|
|
|
SLOT(showPreview(const QItemSelection&, const QItemSelection&)));
|
|
|
|
|
2009-02-19 19:25:17 +01:00
|
|
|
if (m_game)
|
|
|
|
lineEditRack->setValidator(new RackValidator(this, &m_game->getBag()));
|
|
|
|
|
2008-12-14 14:20:38 +01:00
|
|
|
// Notify that the rack changed
|
|
|
|
QObject::connect(lineEditRack, SIGNAL(textChanged(const QString&)),
|
|
|
|
this, SIGNAL(rackUpdated(const QString&)));
|
2008-01-24 21:18:00 +01:00
|
|
|
|
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TrainingWidget::refresh()
|
|
|
|
{
|
|
|
|
updateModel();
|
|
|
|
if (m_game == NULL)
|
|
|
|
{
|
|
|
|
lineEditRack->setText("");
|
|
|
|
lineEditRack->setEnabled(false);
|
|
|
|
pushButtonRack->setEnabled(false);
|
|
|
|
pushButtonComplement->setEnabled(false);
|
|
|
|
pushButtonSearch->setEnabled(false);
|
|
|
|
pushButtonPlay->setEnabled(false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wstring rack = m_game->getPlayer(0).getCurrentRack().toString(PlayedRack::RACK_SIMPLE);
|
2008-11-04 22:31:13 +01:00
|
|
|
// Update the rack only if it is needed, to avoid losing cursor position
|
2008-01-24 21:18:00 +01:00
|
|
|
if (qfw(rack) != lineEditRack->text())
|
|
|
|
lineEditRack->setText(qfw(rack));
|
2009-02-19 19:25:17 +01:00
|
|
|
lineEditPlay->clear();
|
|
|
|
lineEditCoords->clear();
|
2008-01-24 21:18:00 +01:00
|
|
|
lineEditRack->setEnabled(true);
|
|
|
|
pushButtonRack->setEnabled(true);
|
|
|
|
pushButtonComplement->setEnabled(true);
|
|
|
|
pushButtonSearch->setEnabled(m_model->rowCount() == 0 &&
|
|
|
|
lineEditRack->text() != "");
|
2008-11-30 22:08:29 +01:00
|
|
|
// Do not allow entering a move when displaying an old turn
|
|
|
|
setEnabled(m_game->isLastTurn());
|
2008-01-24 21:18:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TrainingWidget::updateModel()
|
|
|
|
{
|
|
|
|
// Consider that there is nothing to do if the number of lines is correct
|
|
|
|
// This avoids problems when the game is updated for a test play
|
|
|
|
if (m_game != NULL &&
|
2010-03-06 17:54:20 +01:00
|
|
|
m_game->trainingGetResults().size() == static_cast<unsigned int>(m_model->rowCount()))
|
2008-01-24 21:18:00 +01:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-07-11 22:58:21 +02:00
|
|
|
// Clear the results
|
2008-01-24 21:18:00 +01:00
|
|
|
m_model->removeRows(0, m_model->rowCount());
|
|
|
|
|
2010-07-11 22:58:21 +02:00
|
|
|
// Force the sort column
|
|
|
|
treeViewResults->sortByColumn(2);
|
|
|
|
|
2008-01-24 21:18:00 +01:00
|
|
|
if (m_game == NULL)
|
|
|
|
return;
|
|
|
|
|
2008-11-30 21:53:44 +01:00
|
|
|
const Results &results = m_game->trainingGetResults();
|
2010-07-11 22:58:03 +02:00
|
|
|
// Find the highest score
|
|
|
|
int bestScore = -1;
|
|
|
|
if (results.size() != 0)
|
|
|
|
bestScore = results.get(0).getPoints();
|
2008-11-30 21:53:44 +01:00
|
|
|
for (unsigned int i = 0; i < results.size(); ++i)
|
2008-01-24 21:18:00 +01:00
|
|
|
{
|
2008-11-30 21:53:44 +01:00
|
|
|
const Round &r = results.get(i);
|
2008-01-24 21:18:00 +01:00
|
|
|
int rowNum = m_model->rowCount();
|
|
|
|
m_model->insertRow(rowNum);
|
|
|
|
m_model->setData(m_model->index(rowNum, 0), qfw(r.getWord()));
|
|
|
|
m_model->setData(m_model->index(rowNum, 1),
|
|
|
|
qfw(r.getCoord().toString()));
|
|
|
|
m_model->setData(m_model->index(rowNum, 2), r.getPoints());
|
|
|
|
m_model->setData(m_model->index(rowNum, 3),
|
|
|
|
r.getBonus() ? "*": "");
|
2010-07-11 22:58:03 +02:00
|
|
|
if (r.getPoints() == bestScore)
|
|
|
|
{
|
2010-07-11 22:58:41 +02:00
|
|
|
// Color the line in red if this is the top score
|
2010-07-11 22:58:03 +02:00
|
|
|
const QBrush redBrush(Qt::red);
|
2010-07-11 22:58:41 +02:00
|
|
|
for (int j = 0; j < HIDDEN_COLUMN; ++j)
|
2010-07-11 22:58:03 +02:00
|
|
|
{
|
|
|
|
m_model->setData(m_model->index(rowNum, j),
|
|
|
|
redBrush, Qt::ForegroundRole);
|
|
|
|
}
|
|
|
|
}
|
2010-07-11 22:58:41 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// Otherwise indicate the difference with the best score
|
|
|
|
m_model->setData(m_model->index(rowNum, 4),
|
|
|
|
r.getPoints() - bestScore);
|
|
|
|
}
|
|
|
|
|
2008-01-27 00:03:32 +01:00
|
|
|
// Hidden data, used to handle proper sorting in the tree view
|
2010-07-11 22:58:41 +02:00
|
|
|
m_model->setData(m_model->index(rowNum, HIDDEN_COLUMN), i);
|
2008-01-24 21:18:00 +01:00
|
|
|
}
|
2008-11-04 22:31:13 +01:00
|
|
|
|
|
|
|
// Clear the status bar when there is no search result
|
|
|
|
if (m_model->rowCount() == 0)
|
|
|
|
emit notifyInfo("");
|
|
|
|
|
2011-07-17 11:09:47 +02:00
|
|
|
if (m_autoResizeColumns)
|
|
|
|
{
|
|
|
|
treeViewResults->resizeColumnToContents(0);
|
|
|
|
treeViewResults->resizeColumnToContents(1);
|
|
|
|
treeViewResults->resizeColumnToContents(2);
|
|
|
|
treeViewResults->resizeColumnToContents(3);
|
|
|
|
treeViewResults->resizeColumnToContents(4);
|
|
|
|
}
|
2008-01-24 21:18:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TrainingWidget::enablePlayButton(const QItemSelection &iSelected,
|
|
|
|
const QItemSelection &)
|
|
|
|
{
|
2009-02-19 19:25:17 +01:00
|
|
|
// Enable the "Play selected" button iff at least one line
|
|
|
|
// in the tree view is selected
|
|
|
|
pushButtonPlaySelected->setEnabled(!iSelected.indexes().empty());
|
2008-01-24 21:18:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TrainingWidget::showPreview(const QItemSelection &iSelected,
|
|
|
|
const QItemSelection &)
|
|
|
|
{
|
2012-01-12 17:43:57 +01:00
|
|
|
m_game->removeTestRound();
|
2008-01-24 21:18:00 +01:00
|
|
|
if (!iSelected.indexes().empty())
|
|
|
|
{
|
2008-01-27 00:03:32 +01:00
|
|
|
// Use the hidden column to get the result number
|
|
|
|
const QModelIndex &index =
|
2010-07-11 22:58:41 +02:00
|
|
|
m_model->index(iSelected.indexes().first().row(), HIDDEN_COLUMN);
|
2012-01-12 17:43:57 +01:00
|
|
|
unsigned int resNb = m_model->data(index).toUInt();
|
|
|
|
|
|
|
|
const Results &results = m_game->trainingGetResults();
|
|
|
|
ASSERT(resNb < results.size(), "Wrong result number");
|
|
|
|
m_game->setTestRound(results.get(resNb));
|
2008-01-24 21:18:00 +01:00
|
|
|
emit gameUpdated();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-28 22:55:48 +02:00
|
|
|
void TrainingWidget::populateMenu(QMenu &iMenu, const QPoint &iPoint)
|
|
|
|
{
|
|
|
|
const QModelIndex &index = treeViewResults->indexAt(iPoint);
|
|
|
|
if (!index.isValid())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Find the selected word
|
|
|
|
const QModelIndex &wordIndex = m_model->index(index.row(), 0);
|
|
|
|
QString selectedWord = m_model->data(wordIndex).toString();
|
|
|
|
|
|
|
|
m_customPopup->addShowDefinitionEntry(iMenu, selectedWord);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-17 11:09:47 +02:00
|
|
|
void TrainingWidget::lockSizesChanged(bool checked)
|
|
|
|
{
|
|
|
|
m_autoResizeColumns = !checked;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-24 21:18:00 +01:00
|
|
|
void TrainingWidget::on_lineEditRack_textEdited(const QString &iText)
|
|
|
|
{
|
|
|
|
// FIXME: first parameter is hardcoded
|
2012-01-12 17:43:57 +01:00
|
|
|
m_game->removeTestRound();
|
2009-06-27 20:09:44 +02:00
|
|
|
if (!lineEditRack->hasAcceptableInput())
|
|
|
|
{
|
|
|
|
lineEditRack->setPalette(redPalette);
|
|
|
|
return;
|
|
|
|
}
|
2009-01-24 11:28:20 +01:00
|
|
|
try
|
2008-01-27 00:03:32 +01:00
|
|
|
{
|
2009-06-27 20:09:44 +02:00
|
|
|
lineEditRack->setPalette(blackPalette);
|
2011-07-30 21:45:18 +02:00
|
|
|
const wstring &input = m_game->getDic().convertFromInput(wfq(iText));
|
2009-06-27 20:09:44 +02:00
|
|
|
m_game->trainingSetRackManual(false, input);
|
2008-01-27 00:03:32 +01:00
|
|
|
pushButtonSearch->setEnabled(m_model->rowCount() == 0 &&
|
|
|
|
lineEditRack->text() != "");
|
|
|
|
emit gameUpdated();
|
|
|
|
}
|
2010-01-24 00:34:23 +01:00
|
|
|
catch (std::exception &e)
|
2009-01-24 11:28:20 +01:00
|
|
|
{
|
2009-06-27 20:09:44 +02:00
|
|
|
lineEditRack->setPalette(redPalette);
|
2008-01-27 00:03:32 +01:00
|
|
|
emit notifyProblem(_q("Warning: Cannot set the rack to '%1'").arg(iText));
|
2009-01-24 11:28:20 +01:00
|
|
|
}
|
2008-01-24 21:18:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TrainingWidget::on_pushButtonRack_clicked()
|
|
|
|
{
|
2012-01-12 17:43:57 +01:00
|
|
|
m_game->removeTestRound();
|
2008-11-22 14:09:28 +01:00
|
|
|
try
|
|
|
|
{
|
2009-06-27 20:09:44 +02:00
|
|
|
// FIXME: first parameter is hardcoded
|
2008-11-30 21:53:44 +01:00
|
|
|
m_game->trainingSetRackRandom(true, PublicGame::kRACK_ALL);
|
2008-11-22 14:09:28 +01:00
|
|
|
emit gameUpdated();
|
|
|
|
}
|
2010-01-24 00:34:23 +01:00
|
|
|
catch (std::exception &e)
|
2008-11-22 14:09:28 +01:00
|
|
|
{
|
2009-02-28 10:24:27 +01:00
|
|
|
emit notifyProblem(_q(e.what()));
|
2008-11-22 14:09:28 +01:00
|
|
|
}
|
2008-01-24 21:18:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TrainingWidget::on_pushButtonComplement_clicked()
|
|
|
|
{
|
2012-01-12 17:43:57 +01:00
|
|
|
m_game->removeTestRound();
|
2008-11-22 14:09:28 +01:00
|
|
|
try
|
|
|
|
{
|
2009-06-27 20:09:44 +02:00
|
|
|
// FIXME: first parameter is hardcoded
|
2008-11-30 21:53:44 +01:00
|
|
|
m_game->trainingSetRackRandom(true, PublicGame::kRACK_NEW);
|
2008-11-22 14:09:28 +01:00
|
|
|
emit gameUpdated();
|
|
|
|
}
|
2010-01-24 00:34:23 +01:00
|
|
|
catch (std::exception &e)
|
2008-11-22 14:09:28 +01:00
|
|
|
{
|
2009-02-28 10:24:27 +01:00
|
|
|
emit notifyProblem(_q(e.what()));
|
2008-11-22 14:09:28 +01:00
|
|
|
}
|
2008-01-24 21:18:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TrainingWidget::on_pushButtonSearch_clicked()
|
|
|
|
{
|
2012-01-12 17:43:57 +01:00
|
|
|
m_game->removeTestRound();
|
2008-11-04 22:31:13 +01:00
|
|
|
emit notifyInfo(_q("Searching with rack '%1'...").arg(lineEditRack->text()));
|
2008-11-30 21:53:44 +01:00
|
|
|
m_game->trainingSearch();
|
2008-11-04 22:31:13 +01:00
|
|
|
emit notifyInfo(_q("Search done"));
|
2008-01-24 21:18:00 +01:00
|
|
|
emit gameUpdated();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-19 19:25:17 +01:00
|
|
|
void TrainingWidget::on_pushButtonPlaySelected_clicked()
|
2008-01-24 21:18:00 +01:00
|
|
|
{
|
|
|
|
QModelIndexList indexList = treeViewResults->selectionModel()->selectedIndexes();
|
|
|
|
if (indexList.empty())
|
|
|
|
return;
|
|
|
|
// Forward the work to another slot
|
|
|
|
on_treeViewResults_doubleClicked(indexList.front());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TrainingWidget::on_treeViewResults_doubleClicked(const QModelIndex &iIndex)
|
|
|
|
{
|
|
|
|
if (!iIndex.isValid())
|
|
|
|
return;
|
2012-01-12 17:43:57 +01:00
|
|
|
m_game->removeTestRound();
|
2008-01-27 00:03:32 +01:00
|
|
|
// Use the hidden column to get the result number
|
2010-07-11 22:58:41 +02:00
|
|
|
const QModelIndex &index = m_model->index(iIndex.row(), HIDDEN_COLUMN);
|
2008-11-30 21:53:44 +01:00
|
|
|
m_game->trainingPlayResult(m_model->data(index).toUInt());
|
2008-01-24 21:18:00 +01:00
|
|
|
emit gameUpdated();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QSize TrainingWidget::sizeHint() const
|
|
|
|
{
|
|
|
|
return QSize(160, 300);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-02-19 19:25:17 +01:00
|
|
|
RackValidator::RackValidator(QObject *parent, const Bag *iBag)
|
|
|
|
: QValidator(parent), m_bag(iBag)
|
2008-01-24 21:18:00 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QValidator::State RackValidator::validate(QString &input, int &) const
|
|
|
|
{
|
|
|
|
// This should never happen, since the control should be disabled in
|
|
|
|
// such a case, but checking doesn't hurt...
|
|
|
|
if (m_bag == NULL)
|
|
|
|
return Invalid;
|
|
|
|
|
2008-10-15 21:43:23 +02:00
|
|
|
input = input.toUpper();
|
|
|
|
|
2009-06-27 20:09:44 +02:00
|
|
|
const Dictionary &dic = m_bag->getDic();
|
|
|
|
|
|
|
|
// The string is invalid if it contains invalid input characters
|
2011-07-30 21:45:18 +02:00
|
|
|
const wistring &winput = wfq(input);
|
2009-06-27 20:09:44 +02:00
|
|
|
if (!dic.validateInputChars(winput))
|
2008-01-27 00:03:32 +01:00
|
|
|
return Invalid;
|
|
|
|
|
2009-06-27 20:09:44 +02:00
|
|
|
// Convert the string to internal letters
|
2009-07-03 23:40:14 +02:00
|
|
|
const wstring &intInput = dic.convertFromInput(winput);
|
2009-06-27 20:09:44 +02:00
|
|
|
// The string is invalid if it contains characters not present
|
|
|
|
// in the dictionary
|
|
|
|
if (!dic.validateLetters(intInput))
|
|
|
|
return Intermediate;
|
|
|
|
|
|
|
|
QString qinput = qfw(intInput);
|
2008-01-24 21:18:00 +01:00
|
|
|
// The letters must be in the bag
|
2009-06-27 20:09:44 +02:00
|
|
|
for (int i = 0; i < qinput.size(); ++i)
|
2008-01-24 21:18:00 +01:00
|
|
|
{
|
2009-06-27 20:09:44 +02:00
|
|
|
if ((unsigned int)qinput.count(qinput[i], Qt::CaseInsensitive) >
|
2010-01-24 00:34:23 +01:00
|
|
|
m_bag->in(intInput[i]))
|
2008-01-24 21:18:00 +01:00
|
|
|
{
|
|
|
|
return Invalid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Acceptable;
|
|
|
|
}
|
|
|
|
|
|
|
|
|