mirror of
git://git.savannah.nongnu.org/eliot.git
synced 2025-01-29 20:34:56 +01:00
Split the ArbitrationWidget class into 2 classes, to keep the code manageable
This commit is contained in:
parent
d4c7511ae5
commit
82b5694a59
7 changed files with 912 additions and 690 deletions
|
@ -45,6 +45,7 @@ EXTRA_DIST = \
|
|||
ui/dic_wizard_letters_def_page.ui \
|
||||
ui/dic_wizard_conclusion_page.ui \
|
||||
ui/arbitration_widget.ui \
|
||||
ui/arbit_assignments.ui \
|
||||
ui/bag_widget.ui \
|
||||
ui/main_window.ui \
|
||||
ui/new_game.ui \
|
||||
|
@ -67,6 +68,7 @@ eliot_SOURCES = \
|
|||
misc_helpers.cpp misc_helpers.h \
|
||||
custom_popup.cpp custom_popup.h \
|
||||
arbitration_widget.cpp arbitration_widget.h \
|
||||
arbit_assignments.cpp arbit_assignments.h \
|
||||
bag_widget.cpp bag_widget.h \
|
||||
bag_widget2.cpp bag_widget2.h \
|
||||
dic_tools_widget.cpp dic_tools_widget.h \
|
||||
|
@ -88,6 +90,7 @@ eliot_SOURCES = \
|
|||
nodist_eliot_SOURCES = \
|
||||
ui/main_window.ui.h \
|
||||
ui/arbitration_widget.ui.h \
|
||||
ui/arbit_assignments.ui.h \
|
||||
ui/bag_widget.ui.h \
|
||||
ui/new_game.ui.h \
|
||||
ui/player_widget.ui.h \
|
||||
|
@ -110,6 +113,7 @@ nodist_eliot_SOURCES = \
|
|||
new_game.moc.cpp \
|
||||
dic_tools_widget.moc.cpp \
|
||||
arbitration_widget.moc.cpp \
|
||||
arbit_assignments.moc.cpp \
|
||||
bag_widget.moc.cpp \
|
||||
bag_widget2.moc.cpp \
|
||||
score_widget.moc.cpp \
|
||||
|
|
601
qt/arbit_assignments.cpp
Normal file
601
qt/arbit_assignments.cpp
Normal file
|
@ -0,0 +1,601 @@
|
|||
/*****************************************************************************
|
||||
* Eliot
|
||||
* Copyright (C) 2012 Olivier Teulière
|
||||
* 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 <boost/foreach.hpp>
|
||||
|
||||
#include <QtGui/QStandardItemModel>
|
||||
#include <QtGui/QSortFilterProxyModel>
|
||||
#include <QtGui/QMenu>
|
||||
|
||||
#include "arbit_assignments.h"
|
||||
#include "qtcommon.h"
|
||||
#include "custom_popup.h"
|
||||
#include "misc_helpers.h"
|
||||
|
||||
#include "public_game.h"
|
||||
#include "player.h"
|
||||
#include "rack.h"
|
||||
#include "results.h"
|
||||
#include "debug.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
INIT_LOGGER(qt, ArbitAssignments);
|
||||
|
||||
|
||||
ArbitAssignments::ArbitAssignments(QWidget *parent, PublicGame *iGame)
|
||||
: QWidget(parent), m_game(iGame)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
// Associate a model to the players view.
|
||||
// We use a proxy, to enable easy sorting of the players.
|
||||
m_proxyPlayersModel = new QSortFilterProxyModel(this);
|
||||
m_proxyPlayersModel->setDynamicSortFilter(true);
|
||||
m_playersModel = new QStandardItemModel(this);
|
||||
m_proxyPlayersModel->setSourceModel(m_playersModel);
|
||||
treeViewPlayers->setModel(m_proxyPlayersModel);
|
||||
m_playersModel->setColumnCount(4);
|
||||
m_playersModel->setHeaderData(0, Qt::Horizontal, _q("Table"), Qt::DisplayRole);
|
||||
m_playersModel->setHeaderData(1, Qt::Horizontal, _q("Player"), Qt::DisplayRole);
|
||||
m_playersModel->setHeaderData(2, Qt::Horizontal, _q("Word"), Qt::DisplayRole);
|
||||
m_playersModel->setHeaderData(3, Qt::Horizontal, _q("Ref"), Qt::DisplayRole);
|
||||
m_playersModel->setHeaderData(4, Qt::Horizontal, _q("Points"), Qt::DisplayRole);
|
||||
treeViewPlayers->sortByColumn(0, Qt::AscendingOrder);
|
||||
|
||||
treeViewPlayers->setColumnWidth(0, 70);
|
||||
treeViewPlayers->setColumnWidth(1, 160);
|
||||
treeViewPlayers->setColumnWidth(2, 160);
|
||||
treeViewPlayers->setColumnWidth(3, 40);
|
||||
treeViewPlayers->setColumnWidth(4, 50);
|
||||
|
||||
KeyEventFilter *filter = new KeyEventFilter(this, Qt::Key_T);
|
||||
QObject::connect(filter, SIGNAL(keyPressed(int, int)),
|
||||
this, SLOT(assignTopMove()));
|
||||
treeViewPlayers->installEventFilter(filter);
|
||||
|
||||
filter = new KeyEventFilter(this, Qt::Key_W);
|
||||
QObject::connect(filter, SIGNAL(keyPressed(int, int)),
|
||||
this, SLOT(addRemoveWarning()));
|
||||
treeViewPlayers->installEventFilter(filter);
|
||||
|
||||
filter = new KeyEventFilter(this, Qt::Key_P);
|
||||
QObject::connect(filter, SIGNAL(keyPressed(int, int)),
|
||||
this, SLOT(addPenalty()));
|
||||
treeViewPlayers->installEventFilter(filter);
|
||||
|
||||
// Display a preview of the master word when clicked
|
||||
QObject::connect(labelMasterMove, SIGNAL(clicked()),
|
||||
this, SLOT(showMasterPreview()));
|
||||
|
||||
// Enable the assignment buttons according to the selections in trees
|
||||
QObject::connect(treeViewPlayers->selectionModel(),
|
||||
SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
|
||||
this, SLOT(enableAssignmentButtons()));
|
||||
|
||||
// Move assignment
|
||||
QObject::connect(buttonSelectMaster, SIGNAL(clicked()),
|
||||
this, SLOT(assignMasterMove()));
|
||||
QObject::connect(buttonNoMove, SIGNAL(clicked()),
|
||||
this, SLOT(assignNoMove()));
|
||||
QObject::connect(buttonAssign, SIGNAL(clicked()),
|
||||
this, SLOT(assignSelectedMove()));
|
||||
QObject::connect(treeViewPlayers, SIGNAL(activated(const QModelIndex&)),
|
||||
this, SLOT(assignSelectedMove()));
|
||||
|
||||
// End turn
|
||||
QObject::connect(buttonEndTurn, SIGNAL(clicked()),
|
||||
this, SLOT(endTurn()));
|
||||
|
||||
// Add a context menu for the players
|
||||
CustomPopup *playersPopup = new CustomPopup(treeViewPlayers);
|
||||
QObject::connect(playersPopup, SIGNAL(popupCreated(QMenu&, const QPoint&)),
|
||||
this, SLOT(populatePlayersMenu(QMenu&, const QPoint&)));
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::refresh()
|
||||
{
|
||||
updatePlayersModel();
|
||||
|
||||
// Update the master move
|
||||
const Move &masterMove = m_game->duplicateGetMasterMove();
|
||||
if (masterMove.getType() == Move::NO_MOVE)
|
||||
{
|
||||
labelMasterMove->setText(QString("<i>%1</i>").arg(_q("Not selected yet")));
|
||||
}
|
||||
else
|
||||
{
|
||||
QString label = QString("<b>%1</b>").arg(formatMove(masterMove));
|
||||
labelMasterMove->setText(label);
|
||||
}
|
||||
|
||||
if (m_game->isFinished())
|
||||
{
|
||||
setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::updatePlayersModel()
|
||||
{
|
||||
// Save the ID of the selected players
|
||||
QSet<unsigned int> playersIdSet = getSelectedPlayers();
|
||||
|
||||
m_playersModel->removeRows(0, m_playersModel->rowCount());
|
||||
if (m_game == NULL)
|
||||
return;
|
||||
|
||||
const bool hideAssignedPlayers = checkBoxHideAssigned->isChecked();
|
||||
for (unsigned int i = 0; i < m_game->getNbPlayers(); ++i)
|
||||
{
|
||||
const Player &player = m_game->getPlayer(i);
|
||||
if (hideAssignedPlayers && m_game->hasPlayed(player.getId()))
|
||||
continue;
|
||||
// Only display human players
|
||||
if (!player.isHuman())
|
||||
continue;
|
||||
const int rowNum = m_playersModel->rowCount();
|
||||
m_playersModel->insertRow(rowNum);
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 0), player.getTableNb());
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 1), qfw(player.getName()));
|
||||
// Store the player ID
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 0),
|
||||
player.getId(), Qt::UserRole);
|
||||
// Display the played word, if any
|
||||
if (m_game->hasPlayed(player.getId()))
|
||||
{
|
||||
const Move &move = player.getLastMove();
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 4), move.getScore());
|
||||
|
||||
QPalette palette = treeViewPlayers->palette();
|
||||
QColor color = palette.color(QPalette::Normal, QPalette::WindowText);
|
||||
if (move.getType() == Move::VALID_ROUND)
|
||||
{
|
||||
const Round &round = move.getRound();
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 2), qfw(round.getWord()));
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 3), qfw(round.getCoord().toString()));
|
||||
}
|
||||
else if (move.getType() == Move::NO_MOVE)
|
||||
{
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 2), _q("(NO MOVE)"));
|
||||
color = Qt::blue;
|
||||
}
|
||||
else if (move.getType() == Move::INVALID_WORD)
|
||||
{
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 2), "<" + qfw(move.getBadWord()) + ">");
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 3), qfw(move.getBadCoord()));
|
||||
color = Qt::red;
|
||||
}
|
||||
// Apply the color
|
||||
const QBrush brush(color);
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 2),
|
||||
brush, Qt::ForegroundRole);
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 3),
|
||||
brush, Qt::ForegroundRole);
|
||||
}
|
||||
// Restore the selection
|
||||
if (playersIdSet.contains(player.getId()))
|
||||
{
|
||||
LOG_DEBUG("selecting player " << player.getId());
|
||||
treeViewPlayers->selectionModel()->select(m_playersModel->index(rowNum, 0),
|
||||
QItemSelectionModel::Select | QItemSelectionModel::Rows);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::enableAssignmentButtons()
|
||||
{
|
||||
bool hasSelResult = m_game->isLastTurn() &&
|
||||
m_selectedMove.getType() != Move::NO_MOVE;
|
||||
bool hasSelPlayer = m_game->isLastTurn() &&
|
||||
treeViewPlayers->selectionModel()->hasSelection();
|
||||
// Enable the "Assign move" button iff a move is selected
|
||||
// and at least one player in the tree view is selected
|
||||
buttonAssign->setEnabled(hasSelResult && hasSelPlayer);
|
||||
if (hasSelResult && hasSelPlayer)
|
||||
{
|
||||
const Move &move = m_selectedMove;
|
||||
buttonAssign->setToolTip(_q("Assign move (%1) to the selected player(s)")
|
||||
.arg(formatMove(move)));
|
||||
}
|
||||
buttonNoMove->setEnabled(hasSelPlayer);
|
||||
buttonSelectMaster->setEnabled(hasSelResult);
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::populatePlayersMenu(QMenu &iMenu, const QPoint &iPoint)
|
||||
{
|
||||
const QModelIndex &index = treeViewPlayers->indexAt(iPoint);
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
// Action to assign the selected move
|
||||
if (m_selectedMove.getType() != Move::NO_MOVE)
|
||||
{
|
||||
const Move &move = m_selectedMove;
|
||||
QAction *assignSelMoveAction =
|
||||
new QAction(_q("Assign selected move (%1)").arg(formatMove(move)), this);
|
||||
assignSelMoveAction->setStatusTip(_q("Assign move (%1) to the selected player(s)")
|
||||
.arg(formatMove(move)));
|
||||
assignSelMoveAction->setShortcut(Qt::Key_Enter);
|
||||
QObject::connect(assignSelMoveAction, SIGNAL(triggered()),
|
||||
this, SLOT(assignSelectedMove()));
|
||||
iMenu.addAction(assignSelMoveAction);
|
||||
}
|
||||
|
||||
// Action to assign the top move
|
||||
QAction *assignTopMoveAction = new QAction(_q("Assign top move"), this);
|
||||
assignTopMoveAction->setStatusTip(_q("Assign the top move (if unique) to the selected player(s)"));
|
||||
assignTopMoveAction->setShortcut(Qt::Key_T);
|
||||
QObject::connect(assignTopMoveAction, SIGNAL(triggered()),
|
||||
this, SLOT(assignTopMove()));
|
||||
iMenu.addAction(assignTopMoveAction);
|
||||
|
||||
// Action to warn (or "unwarn") players
|
||||
QAction *warningAction = new QAction(_q("Give (or remove) a warning"), this);
|
||||
warningAction->setStatusTip(_q("Give a warning to the selected player(s), or remove it if they already have one"));
|
||||
warningAction->setShortcut(Qt::Key_W);
|
||||
QObject::connect(warningAction, SIGNAL(triggered()),
|
||||
this, SLOT(addRemoveWarning()));
|
||||
iMenu.addAction(warningAction);
|
||||
|
||||
// Action to give a penalty to players
|
||||
QAction *penaltyAction = new QAction(_q("Give a penalty"), this);
|
||||
penaltyAction->setStatusTip(_q("Give a penalty to the selected player(s)"));
|
||||
penaltyAction->setShortcut(Qt::Key_P);
|
||||
QObject::connect(penaltyAction, SIGNAL(triggered()),
|
||||
this, SLOT(addPenalty()));
|
||||
iMenu.addAction(penaltyAction);
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::on_checkBoxHideAssigned_toggled(bool)
|
||||
{
|
||||
treeViewPlayers->selectionModel()->clearSelection();
|
||||
updatePlayersModel();
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::selectedMoveChanged(const Move &iMove)
|
||||
{
|
||||
m_selectedMove = iMove;
|
||||
enableAssignmentButtons();
|
||||
}
|
||||
|
||||
|
||||
bool ArbitAssignments::hasSelectedPlayer() const
|
||||
{
|
||||
return treeViewPlayers->selectionModel()->hasSelection();
|
||||
}
|
||||
|
||||
|
||||
QSet<unsigned int> ArbitAssignments::getSelectedPlayers() const
|
||||
{
|
||||
QSet<unsigned int> playersIdSet;
|
||||
|
||||
// Get the tree selection
|
||||
const QItemSelection &proxySelected = treeViewPlayers->selectionModel()->selection();
|
||||
// Map the selection to a source model index
|
||||
const QItemSelection &srcSelected = m_proxyPlayersModel->mapSelectionToSource(proxySelected);
|
||||
// Get the player ID for each line
|
||||
Q_FOREACH(const QModelIndex &index, srcSelected.indexes())
|
||||
{
|
||||
// Only take the first column into account
|
||||
if (index.column() != 0)
|
||||
continue;
|
||||
playersIdSet.insert(m_playersModel->data(index, Qt::UserRole).toUInt());
|
||||
}
|
||||
|
||||
return playersIdSet;
|
||||
}
|
||||
|
||||
|
||||
bool ArbitAssignments::selectPlayerByTable(unsigned tabNb, QString *oName)
|
||||
{
|
||||
// Unselect all the players
|
||||
treeViewPlayers->selectionModel()->clearSelection();
|
||||
for (int rowNum = 0; rowNum < m_playersModel->rowCount(); ++rowNum)
|
||||
{
|
||||
const QModelIndex &modelIndex = m_playersModel->index(rowNum, 0);
|
||||
if (m_playersModel->data(modelIndex).toUInt() == tabNb)
|
||||
{
|
||||
// Found!
|
||||
const QModelIndex &index = m_proxyPlayersModel->mapFromSource(modelIndex);
|
||||
treeViewPlayers->scrollTo(index);
|
||||
treeViewPlayers->selectionModel()->select(index,
|
||||
QItemSelectionModel::Select | QItemSelectionModel::Rows);
|
||||
*oName = m_playersModel->data(m_playersModel->index(rowNum, 1)).toString();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::showMasterPreview()
|
||||
{
|
||||
const Move &move = m_game->duplicateGetMasterMove();
|
||||
if (move.getType() == Move::VALID_ROUND)
|
||||
{
|
||||
// TODO: deselect move in the Results?
|
||||
m_game->setTestRound(move.getRound());
|
||||
emit gameUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rack ArbitAssignments::getRack() const
|
||||
{
|
||||
return m_game->getHistory().getCurrentRack().getRack();
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::assignMasterMove()
|
||||
{
|
||||
if (m_game->isFinished())
|
||||
return;
|
||||
|
||||
const Move &masterMove = m_game->duplicateGetMasterMove();
|
||||
// Make sure the user knows what she's doing
|
||||
if (masterMove.getType() != Move::NO_MOVE)
|
||||
{
|
||||
QString msg = _q("There is already a master move for this turn.");
|
||||
QString question = _q("Do you want to replace it?");
|
||||
if (!QtCommon::requestConfirmation(msg, question))
|
||||
return;
|
||||
}
|
||||
|
||||
const Move &move = m_selectedMove;
|
||||
if (move.getType() != Move::VALID_ROUND)
|
||||
{
|
||||
notifyProblem(_q("The master move must be a valid move."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Warn if the selected move is not a top move
|
||||
BestResults results;
|
||||
results.search(m_game->getDic(), m_game->getBoard(),
|
||||
getRack(), m_game->getHistory().beforeFirstRound());
|
||||
ASSERT(results.size() != 0, "No possible valid move");
|
||||
int bestScore = results.get(0).getPoints();
|
||||
if (bestScore > move.getScore())
|
||||
{
|
||||
QString msg = _q("The selected move scores less than the maximum.");
|
||||
QString question = _q("Do you really want to select it as master move?");
|
||||
if (!QtCommon::requestConfirmation(msg, question))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// A top move saving a joker should be prefered over one not
|
||||
// saving it, according to the French official rules.
|
||||
// Warn if the user tries to ignore the rule.
|
||||
unsigned jokerCount = move.getRound().countJokersFromRack();
|
||||
if (jokerCount > 0)
|
||||
{
|
||||
for (unsigned i = 0; i < results.size(); ++i)
|
||||
{
|
||||
if (results.get(i).countJokersFromRack() < jokerCount)
|
||||
{
|
||||
QString msg = _q("The selected move uses more jokers than "
|
||||
"another move with the same score (%1).")
|
||||
.arg(formatMove(Move(results.get(i))));
|
||||
QString question = _q("Do you really want to select it as master move?");
|
||||
if (!QtCommon::requestConfirmation(msg, question))
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assign the master move
|
||||
m_game->duplicateSetMasterMove(move);
|
||||
emit gameUpdated();
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::assignDefaultMasterMove()
|
||||
{
|
||||
const Move &currMove = m_game->duplicateGetMasterMove();
|
||||
// Do not overwrite an existing move
|
||||
if (currMove.getType() != Move::NO_MOVE)
|
||||
return;
|
||||
|
||||
// Search the best moves
|
||||
BestResults results;
|
||||
results.search(m_game->getDic(), m_game->getBoard(),
|
||||
getRack(), m_game->getHistory().beforeFirstRound());
|
||||
// XXX: End of game
|
||||
if (results.size() == 0)
|
||||
return;
|
||||
|
||||
unsigned currIndex = 0;
|
||||
unsigned jokerCount = results.get(0).countJokersFromRack();
|
||||
if (jokerCount > 0)
|
||||
{
|
||||
for (unsigned i = 1; i < results.size(); ++i)
|
||||
{
|
||||
if (results.get(i).countJokersFromRack() < jokerCount)
|
||||
{
|
||||
currIndex = i;
|
||||
jokerCount = results.get(i).countJokersFromRack();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assign the master move
|
||||
Move move = Move(results.get(currIndex));
|
||||
m_game->duplicateSetMasterMove(move);
|
||||
emit gameUpdated();
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::assignSelectedMove()
|
||||
{
|
||||
if (m_selectedMove.getType() == Move::NO_MOVE ||
|
||||
!treeViewPlayers->selectionModel()->hasSelection())
|
||||
{
|
||||
return;
|
||||
}
|
||||
helperAssignMove(m_selectedMove);
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::assignTopMove()
|
||||
{
|
||||
BestResults results;
|
||||
results.search(m_game->getDic(), m_game->getBoard(),
|
||||
getRack(), m_game->getHistory().beforeFirstRound());
|
||||
// TODO: what if there are several moves?
|
||||
if (results.size() == 1)
|
||||
helperAssignMove(Move(results.get(0)));
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::assignNoMove()
|
||||
{
|
||||
helperAssignMove(Move());
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::helperAssignMove(const Move &iMove)
|
||||
{
|
||||
QSet<unsigned int> playersIdSet = getSelectedPlayers();
|
||||
|
||||
// Warn if some of the selected players already have an assigned move
|
||||
QSet<unsigned int> assignedIdSet;
|
||||
BOOST_FOREACH(unsigned int id, playersIdSet)
|
||||
{
|
||||
if (m_game->hasPlayed(id))
|
||||
assignedIdSet.insert(id);
|
||||
}
|
||||
if (!assignedIdSet.empty())
|
||||
{
|
||||
QString msg = _q("The following players already have an assigned move:\n");
|
||||
BOOST_FOREACH(unsigned int id, assignedIdSet)
|
||||
{
|
||||
msg += QString("\t%1\n").arg(qfw(m_game->getPlayer(id).getName()));
|
||||
}
|
||||
QString question = _q("Do you want to replace it?");
|
||||
if (!QtCommon::requestConfirmation(msg, question))
|
||||
return;
|
||||
}
|
||||
|
||||
// Assign the move to each selected player
|
||||
BOOST_FOREACH(unsigned int id, playersIdSet)
|
||||
{
|
||||
LOG_DEBUG(lfq(QString("Assigning move %1 to player %2")
|
||||
.arg(qfw(iMove.toString())).arg(id)));
|
||||
|
||||
// Assign the move
|
||||
m_game->arbitrationAssign(id, iMove);
|
||||
}
|
||||
emit notifyInfo(_q("Move assigned to player(s)"));
|
||||
emit gameUpdated();
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::addRemoveWarning()
|
||||
{
|
||||
QSet<unsigned int> playersIdSet = getSelectedPlayers();
|
||||
if (playersIdSet.isEmpty())
|
||||
return;
|
||||
|
||||
BOOST_FOREACH(unsigned int id, playersIdSet)
|
||||
{
|
||||
m_game->arbitrationToggleWarning(id);
|
||||
}
|
||||
emit gameUpdated();
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::addPenalty()
|
||||
{
|
||||
QSet<unsigned int> playersIdSet = getSelectedPlayers();
|
||||
if (playersIdSet.isEmpty())
|
||||
return;
|
||||
|
||||
BOOST_FOREACH(unsigned int id, playersIdSet)
|
||||
{
|
||||
m_game->arbitrationAddPenalty(id, 0);
|
||||
}
|
||||
emit gameUpdated();
|
||||
}
|
||||
|
||||
|
||||
QString ArbitAssignments::formatMove(const Move &iMove) const
|
||||
{
|
||||
if (iMove.getType() == Move::VALID_ROUND)
|
||||
{
|
||||
return QString("%1 - %2 - %3")
|
||||
.arg(qfw(iMove.getRound().getWord()))
|
||||
.arg(qfw(iMove.getRound().getCoord().toString()))
|
||||
.arg(iMove.getScore());
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(iMove.getType() == Move::INVALID_WORD, "Unexpected move type");
|
||||
return QString("%1 - %2 - %3")
|
||||
.arg(qfw(iMove.getBadWord()))
|
||||
.arg(qfw(iMove.getBadCoord()))
|
||||
.arg(iMove.getScore());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ArbitAssignments::endTurn()
|
||||
{
|
||||
if (m_game->duplicateGetMasterMove().getType() != Move::VALID_ROUND)
|
||||
{
|
||||
notifyProblem(_q("You must select a master move before ending the turn."));
|
||||
return;
|
||||
}
|
||||
|
||||
bool allPlayed = true;
|
||||
for (unsigned int i = 0; i < m_game->getNbPlayers(); ++i)
|
||||
{
|
||||
if (!m_game->hasPlayed(i) && m_game->getPlayer(i).isHuman())
|
||||
allPlayed = false;
|
||||
}
|
||||
if (!allPlayed)
|
||||
{
|
||||
QString msg = _q("Some player(s) have no assigned move. "
|
||||
"If you continue, they will be assigned a \"(NO MOVE)\" "
|
||||
"pseudo-move, but you will be able to change that later.");
|
||||
if (!QtCommon::requestConfirmation(msg))
|
||||
return;
|
||||
}
|
||||
|
||||
emit notifyInfo(_q("New turn started"));
|
||||
|
||||
m_game->removeTestRound();
|
||||
m_game->arbitrationFinalizeTurn();
|
||||
// FIXME: shouldn't be done here
|
||||
setEnabled(!m_game->isFinished());
|
||||
|
||||
emit gameUpdated();
|
||||
}
|
||||
|
108
qt/arbit_assignments.h
Normal file
108
qt/arbit_assignments.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*****************************************************************************
|
||||
* Eliot
|
||||
* Copyright (C) 2012 Olivier Teulière
|
||||
* 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ARBIT_ASSIGNMENTS_H_
|
||||
#define ARBIT_ASSIGNMENTS_H_
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
#include <ui/arbit_assignments.ui.h>
|
||||
#include "move.h"
|
||||
#include "logging.h"
|
||||
|
||||
class PublicGame;
|
||||
class QStandardItemModel;
|
||||
class QSortFilterProxyModel;
|
||||
class QMenu;
|
||||
class QPoint;
|
||||
class QString;
|
||||
|
||||
class ArbitAssignments: public QWidget, private Ui::ArbitAssignments
|
||||
{
|
||||
Q_OBJECT;
|
||||
DEFINE_LOGGER();
|
||||
|
||||
public:
|
||||
ArbitAssignments(QWidget *parent, PublicGame *iGame);
|
||||
|
||||
/// Format the given move under the format WORD - Ref - Pts
|
||||
QString formatMove(const Move &iMove) const;
|
||||
|
||||
/**
|
||||
* Select the player with the given table number.
|
||||
* Return true if the player was found, false otherwise.
|
||||
* If the player is found, the oName parameter is filled
|
||||
* with the player name.
|
||||
*/
|
||||
bool selectPlayerByTable(unsigned tabNb, QString *oName);
|
||||
|
||||
bool hasSelectedPlayer() const;
|
||||
|
||||
signals:
|
||||
void gameUpdated();
|
||||
void notifyProblem(QString iMsg);
|
||||
void notifyInfo(QString iMsg);
|
||||
|
||||
public slots:
|
||||
void refresh();
|
||||
void enableAssignmentButtons();
|
||||
void assignMasterMove();
|
||||
void assignSelectedMove();
|
||||
void assignDefaultMasterMove();
|
||||
void selectedMoveChanged(const Move&);
|
||||
|
||||
private slots:
|
||||
void on_checkBoxHideAssigned_toggled(bool);
|
||||
void showMasterPreview();
|
||||
void populatePlayersMenu(QMenu &iMenu, const QPoint &iPoint);
|
||||
void assignTopMove();
|
||||
void assignNoMove();
|
||||
void addRemoveWarning();
|
||||
void addPenalty();
|
||||
void endTurn();
|
||||
|
||||
private:
|
||||
/// Encapsulated game, can be NULL
|
||||
PublicGame *m_game;
|
||||
|
||||
/// Model for the players list
|
||||
QStandardItemModel *m_playersModel;
|
||||
/// Proxy for the players model
|
||||
QSortFilterProxyModel *m_proxyPlayersModel;
|
||||
|
||||
// Move currently selected (in the Results table)
|
||||
Move m_selectedMove;
|
||||
|
||||
/// Force synchronizing the model with the players
|
||||
void updatePlayersModel();
|
||||
|
||||
/// Return the rack for the current turn
|
||||
// FIXME: this feature should be provided by the core
|
||||
Rack getRack() const;
|
||||
|
||||
/// Helper method to return the ID of the selected player(s)
|
||||
QSet<unsigned int> getSelectedPlayers() const;
|
||||
|
||||
/// Helper method to assign the given move to the selected player(s)
|
||||
void helperAssignMove(const Move &iMove);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -18,17 +18,13 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*****************************************************************************/
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <vector>
|
||||
|
||||
#include <QtGui/QStandardItemModel>
|
||||
#include <QtGui/QSortFilterProxyModel>
|
||||
#include <QtGui/QMessageBox>
|
||||
#include <QtGui/QMenu>
|
||||
#include <QtGui/QKeyEvent>
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
#include "arbitration_widget.h"
|
||||
#include "arbit_assignments.h"
|
||||
#include "qtcommon.h"
|
||||
#include "prefs_dialog.h"
|
||||
#include "validator_factory.h"
|
||||
|
@ -38,7 +34,6 @@
|
|||
|
||||
#include "public_game.h"
|
||||
#include "player.h"
|
||||
#include "pldrack.h"
|
||||
#include "rack.h"
|
||||
#include "results.h"
|
||||
#include "coord_model.h"
|
||||
|
@ -63,13 +58,20 @@ ArbitrationWidget::ArbitrationWidget(QWidget *parent,
|
|||
{
|
||||
setupUi(this);
|
||||
|
||||
m_assignmentsWidget = new ArbitAssignments(this, iGame);
|
||||
layoutAssignments->addWidget(m_assignmentsWidget);
|
||||
QObject::connect(m_assignmentsWidget, SIGNAL(gameUpdated()),
|
||||
this, SIGNAL(gameUpdated()));
|
||||
QObject::connect(m_assignmentsWidget, SIGNAL(notifyProblem(QString)),
|
||||
this, SIGNAL(notifyProblem(QString)));
|
||||
QObject::connect(m_assignmentsWidget, SIGNAL(notifyInfo(QString)),
|
||||
this, SIGNAL(notifyInfo(QString)));
|
||||
|
||||
m_keyAccum = new KeyAccumulator(this, 400);
|
||||
|
||||
// FIXME arbitration begin
|
||||
// The players widget uses more space by default
|
||||
splitter->setStretchFactor(0, 1);
|
||||
splitter->setStretchFactor(1, 2);
|
||||
// FIXME arbitration end
|
||||
|
||||
blackPalette = lineEditRack->palette();
|
||||
redPalette = lineEditRack->palette();
|
||||
|
@ -82,42 +84,6 @@ ArbitrationWidget::ArbitrationWidget(QWidget *parent,
|
|||
lineEditRack->setValidator(val);
|
||||
lineEditCoords->setValidator(ValidatorFactory::newCoordsValidator(this));
|
||||
|
||||
// Associate a model to the players view.
|
||||
// We use a proxy, to enable easy sorting of the players.
|
||||
m_proxyPlayersModel = new QSortFilterProxyModel(this);
|
||||
m_proxyPlayersModel->setDynamicSortFilter(true);
|
||||
m_playersModel = new QStandardItemModel(this);
|
||||
m_proxyPlayersModel->setSourceModel(m_playersModel);
|
||||
treeViewPlayers->setModel(m_proxyPlayersModel);
|
||||
m_playersModel->setColumnCount(4);
|
||||
m_playersModel->setHeaderData(0, Qt::Horizontal, _q("Table"), Qt::DisplayRole);
|
||||
m_playersModel->setHeaderData(1, Qt::Horizontal, _q("Player"), Qt::DisplayRole);
|
||||
m_playersModel->setHeaderData(2, Qt::Horizontal, _q("Word"), Qt::DisplayRole);
|
||||
m_playersModel->setHeaderData(3, Qt::Horizontal, _q("Ref"), Qt::DisplayRole);
|
||||
m_playersModel->setHeaderData(4, Qt::Horizontal, _q("Points"), Qt::DisplayRole);
|
||||
treeViewPlayers->sortByColumn(0, Qt::AscendingOrder);
|
||||
|
||||
treeViewPlayers->setColumnWidth(0, 70);
|
||||
treeViewPlayers->setColumnWidth(1, 160);
|
||||
treeViewPlayers->setColumnWidth(2, 160);
|
||||
treeViewPlayers->setColumnWidth(3, 40);
|
||||
treeViewPlayers->setColumnWidth(4, 50);
|
||||
|
||||
KeyEventFilter *filter = new KeyEventFilter(this, Qt::Key_T);
|
||||
QObject::connect(filter, SIGNAL(keyPressed(int, int)),
|
||||
this, SLOT(assignTopMove()));
|
||||
treeViewPlayers->installEventFilter(filter);
|
||||
|
||||
filter = new KeyEventFilter(this, Qt::Key_W);
|
||||
QObject::connect(filter, SIGNAL(keyPressed(int, int)),
|
||||
this, SLOT(addRemoveWarning()));
|
||||
treeViewPlayers->installEventFilter(filter);
|
||||
|
||||
filter = new KeyEventFilter(this, Qt::Key_P);
|
||||
QObject::connect(filter, SIGNAL(keyPressed(int, int)),
|
||||
this, SLOT(addPenalty()));
|
||||
treeViewPlayers->installEventFilter(filter);
|
||||
|
||||
// Associate a model to the results view.
|
||||
// We use a proxy, to enable easy sorting/filtering of the results.
|
||||
m_proxyResultsModel = new QSortFilterProxyModel(this);
|
||||
|
@ -143,7 +109,7 @@ ArbitrationWidget::ArbitrationWidget(QWidget *parent,
|
|||
|
||||
KeyEventFilter *masterFilter = new KeyEventFilter(this, Qt::Key_M);
|
||||
QObject::connect(masterFilter, SIGNAL(keyPressed(int, int)),
|
||||
this, SLOT(assignMasterMove()));
|
||||
m_assignmentsWidget, SLOT(assignMasterMove()));
|
||||
treeViewResults->installEventFilter(masterFilter);
|
||||
|
||||
KeyEventFilter *numFilter = new KeyEventFilter(this, Qt::Key_0);
|
||||
|
@ -179,21 +145,20 @@ ArbitrationWidget::ArbitrationWidget(QWidget *parent,
|
|||
QObject::connect(treeViewResults->selectionModel(),
|
||||
SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
|
||||
this, SLOT(showPreview(const QItemSelection&)));
|
||||
// Display a preview of the master word when clicked
|
||||
QObject::connect(labelMasterMove, SIGNAL(clicked()),
|
||||
this, SLOT(showMasterPreview()));
|
||||
|
||||
// Dynamic filter for search results
|
||||
QObject::connect(lineEditFilter, SIGNAL(textChanged(const QString&)),
|
||||
this, SLOT(resultsFilterChanged(const QString&)));
|
||||
|
||||
// Enable the assignment buttons according to the selections in trees
|
||||
QObject::connect(treeViewPlayers->selectionModel(),
|
||||
SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
|
||||
this, SLOT(enableAssignmentButtons()));
|
||||
QObject::connect(treeViewResults->selectionModel(),
|
||||
SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
|
||||
this, SLOT(enableAssignmentButtons()));
|
||||
m_assignmentsWidget, SLOT(enableAssignmentButtons()));
|
||||
|
||||
// Enable the assignment buttons according to the selections in trees
|
||||
QObject::connect(treeViewResults->selectionModel(),
|
||||
SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
|
||||
this, SLOT(updateSelectedMove()));
|
||||
|
||||
// Coordinates model
|
||||
QObject::connect(&m_coordModel, SIGNAL(coordChanged(const Coord&, const Coord&)),
|
||||
|
@ -216,20 +181,8 @@ ArbitrationWidget::ArbitrationWidget(QWidget *parent,
|
|||
this, SLOT(checkWord()));
|
||||
|
||||
// Move assignment
|
||||
QObject::connect(buttonSelectMaster, SIGNAL(clicked()),
|
||||
this, SLOT(assignMasterMove()));
|
||||
QObject::connect(buttonNoMove, SIGNAL(clicked()),
|
||||
this, SLOT(assignNoMove()));
|
||||
QObject::connect(buttonAssign, SIGNAL(clicked()),
|
||||
this, SLOT(assignSelectedMove()));
|
||||
QObject::connect(treeViewResults, SIGNAL(activated(const QModelIndex&)),
|
||||
this, SLOT(assignSelectedMove()));
|
||||
QObject::connect(treeViewPlayers, SIGNAL(activated(const QModelIndex&)),
|
||||
this, SLOT(assignSelectedMove()));
|
||||
|
||||
// End turn
|
||||
QObject::connect(buttonEndTurn, SIGNAL(clicked()),
|
||||
this, SLOT(endTurn()));
|
||||
m_assignmentsWidget, SLOT(assignSelectedMove()));
|
||||
|
||||
// Add a context menu for the results
|
||||
m_resultsPopup = new CustomPopup(treeViewResults);
|
||||
|
@ -237,10 +190,6 @@ ArbitrationWidget::ArbitrationWidget(QWidget *parent,
|
|||
this, SLOT(populateResultsMenu(QMenu&, const QPoint&)));
|
||||
QObject::connect(m_resultsPopup, SIGNAL(requestDefinition(QString)),
|
||||
this, SIGNAL(requestDefinition(QString)));
|
||||
// Add a context menu for the players
|
||||
CustomPopup *playersPopup = new CustomPopup(treeViewPlayers);
|
||||
QObject::connect(playersPopup, SIGNAL(popupCreated(QMenu&, const QPoint&)),
|
||||
this, SLOT(populatePlayersMenu(QMenu&, const QPoint&)));
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
@ -258,19 +207,7 @@ void ArbitrationWidget::refresh()
|
|||
}
|
||||
|
||||
updateResultsModel();
|
||||
updatePlayersModel();
|
||||
|
||||
// Update the master move
|
||||
const Move &masterMove = m_game->duplicateGetMasterMove();
|
||||
if (masterMove.getType() == Move::NO_MOVE)
|
||||
{
|
||||
labelMasterMove->setText(QString("<i>%1</i>").arg(_q("Not selected yet")));
|
||||
}
|
||||
else
|
||||
{
|
||||
QString label = QString("<b>%1</b>").arg(formatMove(masterMove));
|
||||
labelMasterMove->setText(label);
|
||||
}
|
||||
m_assignmentsWidget->refresh();
|
||||
|
||||
// The rack can only be changed at the last turn
|
||||
bool isLastTurn = m_game->isLastTurn();
|
||||
|
@ -327,74 +264,6 @@ void ArbitrationWidget::updateResultsModel()
|
|||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::updatePlayersModel()
|
||||
{
|
||||
// Save the ID of the selected players
|
||||
QSet<unsigned int> playersIdSet = getSelectedPlayers();
|
||||
|
||||
m_playersModel->removeRows(0, m_playersModel->rowCount());
|
||||
if (m_game == NULL)
|
||||
return;
|
||||
|
||||
const bool hideAssignedPlayers = checkBoxHideAssigned->isChecked();
|
||||
for (unsigned int i = 0; i < m_game->getNbPlayers(); ++i)
|
||||
{
|
||||
const Player &player = m_game->getPlayer(i);
|
||||
if (hideAssignedPlayers && m_game->hasPlayed(player.getId()))
|
||||
continue;
|
||||
// Only display human players
|
||||
if (!player.isHuman())
|
||||
continue;
|
||||
const int rowNum = m_playersModel->rowCount();
|
||||
m_playersModel->insertRow(rowNum);
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 0), player.getTableNb());
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 1), qfw(player.getName()));
|
||||
// Store the player ID
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 0),
|
||||
player.getId(), Qt::UserRole);
|
||||
// Display the played word, if any
|
||||
if (m_game->hasPlayed(player.getId()))
|
||||
{
|
||||
const Move &move = player.getLastMove();
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 4), move.getScore());
|
||||
|
||||
QPalette palette = treeViewPlayers->palette();
|
||||
QColor color = palette.color(QPalette::Normal, QPalette::WindowText);
|
||||
if (move.getType() == Move::VALID_ROUND)
|
||||
{
|
||||
const Round &round = move.getRound();
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 2), qfw(round.getWord()));
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 3), qfw(round.getCoord().toString()));
|
||||
}
|
||||
else if (move.getType() == Move::NO_MOVE)
|
||||
{
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 2), _q("(NO MOVE)"));
|
||||
color = Qt::blue;
|
||||
}
|
||||
else if (move.getType() == Move::INVALID_WORD)
|
||||
{
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 2), "<" + qfw(move.getBadWord()) + ">");
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 3), qfw(move.getBadCoord()));
|
||||
color = Qt::red;
|
||||
}
|
||||
// Apply the color
|
||||
const QBrush brush(color);
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 2),
|
||||
brush, Qt::ForegroundRole);
|
||||
m_playersModel->setData(m_playersModel->index(rowNum, 3),
|
||||
brush, Qt::ForegroundRole);
|
||||
}
|
||||
// Restore the selection
|
||||
if (playersIdSet.contains(player.getId()))
|
||||
{
|
||||
LOG_DEBUG("selecting player " << player.getId());
|
||||
treeViewPlayers->selectionModel()->select(m_playersModel->index(rowNum, 0),
|
||||
QItemSelectionModel::Select | QItemSelectionModel::Rows);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ArbitrationWidget::addSingleMove(const Move &iMove, int moveType,
|
||||
unsigned int index, int bestScore)
|
||||
{
|
||||
|
@ -564,26 +433,6 @@ void ArbitrationWidget::enableCheckWordButton()
|
|||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::enableAssignmentButtons()
|
||||
{
|
||||
bool hasSelResult = m_game->isLastTurn() &&
|
||||
treeViewResults->selectionModel()->hasSelection();
|
||||
bool hasSelPlayer = m_game->isLastTurn() &&
|
||||
treeViewPlayers->selectionModel()->hasSelection();
|
||||
// Enable the "Assign move" button iff a move is selected
|
||||
// and at least one player in the tree view is selected
|
||||
buttonAssign->setEnabled(hasSelResult && hasSelPlayer);
|
||||
if (hasSelResult && hasSelPlayer)
|
||||
{
|
||||
const Move &move = getSelectedMove();
|
||||
buttonAssign->setToolTip(_q("Assign move (%1) to the selected player(s)")
|
||||
.arg(formatMove(move)));
|
||||
}
|
||||
buttonNoMove->setEnabled(hasSelPlayer);
|
||||
buttonSelectMaster->setEnabled(hasSelResult);
|
||||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::on_buttonSearch_clicked()
|
||||
{
|
||||
m_game->removeTestRound();
|
||||
|
@ -596,7 +445,7 @@ void ArbitrationWidget::on_buttonSearch_clicked()
|
|||
QSettings settings;
|
||||
if (settings.value(PrefsDialog::kARBIT_AUTO_MASTER, false).toBool())
|
||||
{
|
||||
assignDefaultMasterMove();
|
||||
m_assignmentsWidget->assignDefaultMasterMove();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -624,7 +473,7 @@ void ArbitrationWidget::populateResultsMenu(QMenu &iMenu, const QPoint &iPoint)
|
|||
.arg(formatMove(move)));
|
||||
setAsMasterAction->setShortcut(Qt::Key_M);
|
||||
QObject::connect(setAsMasterAction, SIGNAL(triggered()),
|
||||
this, SLOT(assignMasterMove()));
|
||||
m_assignmentsWidget, SLOT(assignMasterMove()));
|
||||
iMenu.addAction(setAsMasterAction);
|
||||
if (move.getType() != Move::VALID_ROUND)
|
||||
setAsMasterAction->setEnabled(false);
|
||||
|
@ -636,61 +485,13 @@ void ArbitrationWidget::populateResultsMenu(QMenu &iMenu, const QPoint &iPoint)
|
|||
.arg(formatMove(move)));
|
||||
assignSelMoveAction->setShortcut(Qt::Key_Enter);
|
||||
QObject::connect(assignSelMoveAction, SIGNAL(triggered()),
|
||||
this, SLOT(assignSelectedMove()));
|
||||
m_assignmentsWidget, SLOT(assignSelectedMove()));
|
||||
iMenu.addAction(assignSelMoveAction);
|
||||
if (!treeViewPlayers->selectionModel()->hasSelection())
|
||||
if (!m_assignmentsWidget->hasSelectedPlayer())
|
||||
assignSelMoveAction->setEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::populatePlayersMenu(QMenu &iMenu, const QPoint &iPoint)
|
||||
{
|
||||
const QModelIndex &index = treeViewPlayers->indexAt(iPoint);
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
// Action to assign the selected move
|
||||
if (treeViewResults->selectionModel()->hasSelection())
|
||||
{
|
||||
const Move &move = getSelectedMove();
|
||||
QAction *assignSelMoveAction =
|
||||
new QAction(_q("Assign selected move (%1)").arg(formatMove(move)), this);
|
||||
assignSelMoveAction->setStatusTip(_q("Assign move (%1) to the selected player(s)")
|
||||
.arg(formatMove(move)));
|
||||
assignSelMoveAction->setShortcut(Qt::Key_Enter);
|
||||
QObject::connect(assignSelMoveAction, SIGNAL(triggered()),
|
||||
this, SLOT(assignSelectedMove()));
|
||||
iMenu.addAction(assignSelMoveAction);
|
||||
}
|
||||
|
||||
// Action to assign the top move
|
||||
QAction *assignTopMoveAction = new QAction(_q("Assign top move"), this);
|
||||
assignTopMoveAction->setStatusTip(_q("Assign the top move (if unique) to the selected player(s)"));
|
||||
assignTopMoveAction->setShortcut(Qt::Key_T);
|
||||
QObject::connect(assignTopMoveAction, SIGNAL(triggered()),
|
||||
this, SLOT(assignTopMove()));
|
||||
iMenu.addAction(assignTopMoveAction);
|
||||
|
||||
// Action to warn (or "unwarn") players
|
||||
QAction *warningAction = new QAction(_q("Give (or remove) a warning"), this);
|
||||
warningAction->setStatusTip(_q("Give a warning to the selected player(s), or remove it if they already have one"));
|
||||
warningAction->setShortcut(Qt::Key_W);
|
||||
QObject::connect(warningAction, SIGNAL(triggered()),
|
||||
this, SLOT(addRemoveWarning()));
|
||||
iMenu.addAction(warningAction);
|
||||
|
||||
// Action to give a penalty to players
|
||||
QAction *penaltyAction = new QAction(_q("Give a penalty"), this);
|
||||
penaltyAction->setStatusTip(_q("Give a penalty to the selected player(s)"));
|
||||
penaltyAction->setShortcut(Qt::Key_P);
|
||||
QObject::connect(penaltyAction, SIGNAL(triggered()),
|
||||
this, SLOT(addPenalty()));
|
||||
iMenu.addAction(penaltyAction);
|
||||
|
||||
// TODO: add other actions
|
||||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::checkWord()
|
||||
{
|
||||
if (lineEditWord->text().isEmpty() ||
|
||||
|
@ -755,34 +556,28 @@ void ArbitrationWidget::selectTableNumber(int key)
|
|||
|
||||
// Select the player with this table number
|
||||
LOG_DEBUG("Selecting player with table number: " + lfq(tableNum));
|
||||
treeViewPlayers->selectionModel()->clearSelection();
|
||||
unsigned tabNb = tableNum.toUInt();
|
||||
for (int rowNum = 0; rowNum < m_playersModel->rowCount(); ++rowNum)
|
||||
QString name;
|
||||
bool found = m_assignmentsWidget->selectPlayerByTable(tableNum.toUInt(), &name);
|
||||
if (found)
|
||||
{
|
||||
const QModelIndex &modelIndex = m_playersModel->index(rowNum, 0);
|
||||
if (m_playersModel->data(modelIndex).toUInt() == tabNb)
|
||||
{
|
||||
const QModelIndex &index = m_proxyPlayersModel->mapFromSource(modelIndex);
|
||||
treeViewPlayers->scrollTo(index);
|
||||
treeViewPlayers->selectionModel()->select(index,
|
||||
QItemSelectionModel::Select | QItemSelectionModel::Rows);
|
||||
// Keep the focus in the results view
|
||||
treeViewResults->setFocus();
|
||||
// Keep the focus in the results view
|
||||
treeViewResults->setFocus();
|
||||
|
||||
// Write a nice message on the status bar
|
||||
QString name = m_playersModel->data(m_playersModel->index(rowNum, 1)).toString();
|
||||
emit notifyInfo(_q("Player at table %1 selected (%2)").arg(tabNb).arg(name));
|
||||
return;
|
||||
}
|
||||
// Write a nice message on the status bar
|
||||
emit notifyInfo(_q("Player at table %1 selected (%2)").arg(tableNum).arg(name));
|
||||
return;
|
||||
}
|
||||
LOG_DEBUG("Not found");
|
||||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::on_checkBoxHideAssigned_toggled(bool)
|
||||
void ArbitrationWidget::updateSelectedMove()
|
||||
{
|
||||
treeViewPlayers->selectionModel()->clearSelection();
|
||||
updatePlayersModel();
|
||||
bool hasSelection = treeViewResults->selectionModel()->hasSelection();
|
||||
if (hasSelection)
|
||||
m_assignmentsWidget->selectedMoveChanged(getSelectedMove());
|
||||
else
|
||||
m_assignmentsWidget->selectedMoveChanged(Move());
|
||||
}
|
||||
|
||||
|
||||
|
@ -814,31 +609,11 @@ Move ArbitrationWidget::getSelectedMove() const
|
|||
}
|
||||
|
||||
|
||||
QSet<unsigned int> ArbitrationWidget::getSelectedPlayers() const
|
||||
{
|
||||
QSet<unsigned int> playersIdSet;
|
||||
|
||||
// Get the tree selection
|
||||
const QItemSelection &proxySelected = treeViewPlayers->selectionModel()->selection();
|
||||
// Map the selection to a source model index
|
||||
const QItemSelection &srcSelected = m_proxyPlayersModel->mapSelectionToSource(proxySelected);
|
||||
// Get the player ID for each line
|
||||
Q_FOREACH(const QModelIndex &index, srcSelected.indexes())
|
||||
{
|
||||
// Only take the first column into account
|
||||
if (index.column() != 0)
|
||||
continue;
|
||||
playersIdSet.insert(m_playersModel->data(index, Qt::UserRole).toUInt());
|
||||
}
|
||||
|
||||
return playersIdSet;
|
||||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::clearResults()
|
||||
{
|
||||
m_game->removeTestRound();
|
||||
m_results.clear();
|
||||
m_addedMoves.clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -857,18 +632,6 @@ void ArbitrationWidget::showPreview(const QItemSelection &iSelected)
|
|||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::showMasterPreview()
|
||||
{
|
||||
const Move &move = m_game->duplicateGetMasterMove();
|
||||
if (move.getType() == Move::VALID_ROUND)
|
||||
{
|
||||
treeViewResults->clearSelection();
|
||||
m_game->setTestRound(move.getRound());
|
||||
}
|
||||
emit gameUpdated();
|
||||
}
|
||||
|
||||
|
||||
Rack ArbitrationWidget::getRack() const
|
||||
{
|
||||
return m_game->getHistory().getCurrentRack().getRack();
|
||||
|
@ -886,252 +649,8 @@ int ArbitrationWidget::getBestScore() const
|
|||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::assignMasterMove()
|
||||
{
|
||||
if (m_game->isFinished())
|
||||
return;
|
||||
|
||||
const Move &masterMove = m_game->duplicateGetMasterMove();
|
||||
// Make sure the user knows what she's doing
|
||||
if (masterMove.getType() != Move::NO_MOVE)
|
||||
{
|
||||
QString msg = _q("There is already a master move for this turn.");
|
||||
QString question = _q("Do you want to replace it?");
|
||||
if (!QtCommon::requestConfirmation(msg, question))
|
||||
return;
|
||||
}
|
||||
|
||||
const Move &move = getSelectedMove();
|
||||
if (move.getType() != Move::VALID_ROUND)
|
||||
{
|
||||
notifyProblem(_q("The master move must be a valid move."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Warn if the selected move is not a top move
|
||||
BestResults results;
|
||||
results.search(m_game->getDic(), m_game->getBoard(),
|
||||
getRack(), m_game->getHistory().beforeFirstRound());
|
||||
ASSERT(results.size() != 0, "No possible valid move");
|
||||
int bestScore = results.get(0).getPoints();
|
||||
if (bestScore > move.getScore())
|
||||
{
|
||||
QString msg = _q("The selected move scores less than the maximum.");
|
||||
QString question = _q("Do you really want to select it as master move?");
|
||||
if (!QtCommon::requestConfirmation(msg, question))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// A top move saving a joker should be prefered over one not
|
||||
// saving it, according to the French official rules.
|
||||
// Warn if the user tries to ignore the rule.
|
||||
unsigned jokerCount = move.getRound().countJokersFromRack();
|
||||
if (jokerCount > 0)
|
||||
{
|
||||
for (unsigned i = 0; i < results.size(); ++i)
|
||||
{
|
||||
if (results.get(i).countJokersFromRack() < jokerCount)
|
||||
{
|
||||
QString msg = _q("The selected move uses more jokers than "
|
||||
"another move with the same score (%1).")
|
||||
.arg(formatMove(Move(results.get(i))));
|
||||
QString question = _q("Do you really want to select it as master move?");
|
||||
if (!QtCommon::requestConfirmation(msg, question))
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assign the master move
|
||||
m_game->duplicateSetMasterMove(move);
|
||||
emit gameUpdated();
|
||||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::assignDefaultMasterMove()
|
||||
{
|
||||
const Move &currMove = m_game->duplicateGetMasterMove();
|
||||
// Do not overwrite an existing move
|
||||
if (currMove.getType() != Move::NO_MOVE)
|
||||
return;
|
||||
|
||||
// Search the best moves
|
||||
BestResults results;
|
||||
results.search(m_game->getDic(), m_game->getBoard(),
|
||||
getRack(), m_game->getHistory().beforeFirstRound());
|
||||
// XXX: End of game
|
||||
if (results.size() == 0)
|
||||
return;
|
||||
|
||||
unsigned currIndex = 0;
|
||||
unsigned jokerCount = results.get(0).countJokersFromRack();
|
||||
if (jokerCount > 0)
|
||||
{
|
||||
for (unsigned i = 1; i < results.size(); ++i)
|
||||
{
|
||||
if (results.get(i).countJokersFromRack() < jokerCount)
|
||||
{
|
||||
currIndex = i;
|
||||
jokerCount = results.get(i).countJokersFromRack();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assign the master move
|
||||
Move move = Move(results.get(currIndex));
|
||||
m_game->duplicateSetMasterMove(move);
|
||||
emit gameUpdated();
|
||||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::assignSelectedMove()
|
||||
{
|
||||
if (!treeViewResults->selectionModel()->hasSelection() ||
|
||||
!treeViewPlayers->selectionModel()->hasSelection())
|
||||
{
|
||||
return;
|
||||
}
|
||||
helperAssignMove(getSelectedMove());
|
||||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::assignTopMove()
|
||||
{
|
||||
BestResults results;
|
||||
results.search(m_game->getDic(), m_game->getBoard(),
|
||||
getRack(), m_game->getHistory().beforeFirstRound());
|
||||
// TODO: what if there are several moves?
|
||||
if (results.size() == 1)
|
||||
helperAssignMove(Move(results.get(0)));
|
||||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::assignNoMove()
|
||||
{
|
||||
helperAssignMove(Move());
|
||||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::helperAssignMove(const Move &iMove)
|
||||
{
|
||||
QSet<unsigned int> playersIdSet = getSelectedPlayers();
|
||||
|
||||
// Warn if some of the selected players already have an assigned move
|
||||
QSet<unsigned int> assignedIdSet;
|
||||
BOOST_FOREACH(unsigned int id, playersIdSet)
|
||||
{
|
||||
if (m_game->hasPlayed(id))
|
||||
assignedIdSet.insert(id);
|
||||
}
|
||||
if (!assignedIdSet.empty())
|
||||
{
|
||||
QString msg = _q("The following players already have an assigned move:\n");
|
||||
BOOST_FOREACH(unsigned int id, assignedIdSet)
|
||||
{
|
||||
msg += QString("\t%1\n").arg(qfw(m_game->getPlayer(id).getName()));
|
||||
}
|
||||
QString question = _q("Do you want to replace it?");
|
||||
if (!QtCommon::requestConfirmation(msg, question))
|
||||
return;
|
||||
}
|
||||
|
||||
// Assign the move to each selected player
|
||||
BOOST_FOREACH(unsigned int id, playersIdSet)
|
||||
{
|
||||
LOG_DEBUG(lfq(QString("Assigning move %1 to player %2")
|
||||
.arg(qfw(iMove.toString())).arg(id)));
|
||||
|
||||
// Assign the move
|
||||
m_game->arbitrationAssign(id, iMove);
|
||||
}
|
||||
emit notifyInfo(_q("Move assigned to player(s)"));
|
||||
emit gameUpdated();
|
||||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::addRemoveWarning()
|
||||
{
|
||||
QSet<unsigned int> playersIdSet = getSelectedPlayers();
|
||||
if (playersIdSet.isEmpty())
|
||||
return;
|
||||
|
||||
BOOST_FOREACH(unsigned int id, playersIdSet)
|
||||
{
|
||||
m_game->arbitrationToggleWarning(id);
|
||||
}
|
||||
emit gameUpdated();
|
||||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::addPenalty()
|
||||
{
|
||||
QSet<unsigned int> playersIdSet = getSelectedPlayers();
|
||||
if (playersIdSet.isEmpty())
|
||||
return;
|
||||
|
||||
BOOST_FOREACH(unsigned int id, playersIdSet)
|
||||
{
|
||||
m_game->arbitrationAddPenalty(id, 0);
|
||||
}
|
||||
emit gameUpdated();
|
||||
}
|
||||
|
||||
|
||||
QString ArbitrationWidget::formatMove(const Move &iMove) const
|
||||
{
|
||||
if (iMove.getType() == Move::VALID_ROUND)
|
||||
{
|
||||
return QString("%1 - %2 - %3")
|
||||
.arg(qfw(iMove.getRound().getWord()))
|
||||
.arg(qfw(iMove.getRound().getCoord().toString()))
|
||||
.arg(iMove.getScore());
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(iMove.getType() == Move::INVALID_WORD, "Unexpected move type");
|
||||
return QString("%1 - %2 - %3")
|
||||
.arg(qfw(iMove.getBadWord()))
|
||||
.arg(qfw(iMove.getBadCoord()))
|
||||
.arg(iMove.getScore());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ArbitrationWidget::endTurn()
|
||||
{
|
||||
if (m_game->duplicateGetMasterMove().getType() != Move::VALID_ROUND)
|
||||
{
|
||||
notifyProblem(_q("You must select a master move before ending the turn."));
|
||||
return;
|
||||
}
|
||||
|
||||
bool allPlayed = true;
|
||||
for (unsigned int i = 0; i < m_game->getNbPlayers(); ++i)
|
||||
{
|
||||
if (!m_game->hasPlayed(i) && m_game->getPlayer(i).isHuman())
|
||||
allPlayed = false;
|
||||
}
|
||||
if (!allPlayed)
|
||||
{
|
||||
QString msg = _q("Some player(s) have no assigned move. "
|
||||
"If you continue, they will be assigned a \"(NO MOVE)\" "
|
||||
"pseudo-move, but you will be able to change that later.");
|
||||
if (!QtCommon::requestConfirmation(msg))
|
||||
return;
|
||||
}
|
||||
|
||||
m_addedMoves.clear();
|
||||
|
||||
emit notifyInfo(_q("New turn started"));
|
||||
|
||||
m_game->removeTestRound();
|
||||
m_game->arbitrationFinalizeTurn();
|
||||
// FIXME: shouldn't be done here
|
||||
setEnabled(!m_game->isFinished());
|
||||
|
||||
emit gameUpdated();
|
||||
return m_assignmentsWidget->formatMove(iMove);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "logging.h"
|
||||
|
||||
class PublicGame;
|
||||
class ArbitAssignments;
|
||||
class CoordModel;
|
||||
class CustomPopup;
|
||||
class KeyAccumulator;
|
||||
|
@ -36,7 +37,6 @@ class QStandardItemModel;
|
|||
class QSortFilterProxyModel;
|
||||
class QMenu;
|
||||
class QPoint;
|
||||
class QKeyEvent;
|
||||
|
||||
class ArbitrationWidget: public QWidget, private Ui::ArbitrationWidget
|
||||
{
|
||||
|
@ -62,32 +62,24 @@ private slots:
|
|||
void setRackRandom();
|
||||
void rackEdited(const QString &);
|
||||
void on_buttonSearch_clicked();
|
||||
void on_checkBoxHideAssigned_toggled(bool);
|
||||
void resultsFilterChanged(const QString &);
|
||||
void enableCheckWordButton();
|
||||
void enableAssignmentButtons();
|
||||
void checkWord();
|
||||
void clearResults();
|
||||
void updateSelectedMove();
|
||||
void showPreview(const QItemSelection &);
|
||||
void showMasterPreview();
|
||||
void updateCoordText(const Coord&, const Coord&);
|
||||
void updateCoordModel(const QString&);
|
||||
void populateResultsMenu(QMenu &iMenu, const QPoint &iPoint);
|
||||
void populatePlayersMenu(QMenu &iMenu, const QPoint &iPoint);
|
||||
void checkWord();
|
||||
void selectTableNumber(int key);
|
||||
void assignMasterMove();
|
||||
void assignDefaultMasterMove();
|
||||
void assignSelectedMove();
|
||||
void assignTopMove();
|
||||
void assignNoMove();
|
||||
void addRemoveWarning();
|
||||
void addPenalty();
|
||||
void endTurn();
|
||||
|
||||
private:
|
||||
/// Encapsulated game, can be NULL
|
||||
PublicGame *m_game;
|
||||
|
||||
/// Assignments widget (right part of the splitter)
|
||||
ArbitAssignments * m_assignmentsWidget;
|
||||
|
||||
/// Coordinates of the next word to play
|
||||
CoordModel &m_coordModel;
|
||||
|
||||
|
@ -99,11 +91,6 @@ private:
|
|||
/// Proxy for the results model
|
||||
QSortFilterProxyModel *m_proxyResultsModel;
|
||||
|
||||
/// Model for the players list
|
||||
QStandardItemModel *m_playersModel;
|
||||
/// Proxy for the players model
|
||||
QSortFilterProxyModel *m_proxyPlayersModel;
|
||||
|
||||
/// Popup menu for the search results
|
||||
CustomPopup *m_resultsPopup;
|
||||
|
||||
|
@ -121,8 +108,6 @@ private:
|
|||
|
||||
/// Force synchronizing the model with the search results
|
||||
void updateResultsModel();
|
||||
/// Force synchronizing the model with the players
|
||||
void updatePlayersModel();
|
||||
|
||||
/**
|
||||
* Add the given move to the results list.
|
||||
|
@ -139,11 +124,6 @@ private:
|
|||
|
||||
/// Helper method to return a structured move for the selected result
|
||||
Move getSelectedMove() const;
|
||||
/// Helper method to return the ID of the selected player(s)
|
||||
QSet<unsigned int> getSelectedPlayers() const;
|
||||
|
||||
/// Helper method to assign the given move to the selected player(s)
|
||||
void helperAssignMove(const Move &iMove);
|
||||
|
||||
/// Format the given move under the format WORD - Ref - Pts
|
||||
QString formatMove(const Move &iMove) const;
|
||||
|
|
150
qt/ui/arbit_assignments.ui
Normal file
150
qt/ui/arbit_assignments.ui
Normal file
|
@ -0,0 +1,150 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ArbitAssignments</class>
|
||||
<widget class="QWidget" name="ArbitAssignments">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>404</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>_("Assignments")</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>_("Master move:")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ClickableLabel" name="labelMasterMove">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonSelectMaster">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>_("Select")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxHideAssigned">
|
||||
<property name="text">
|
||||
<string>_("Hide players with an assigned move")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="treeViewPlayers">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonAssign">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>_("Assign move")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonNoMove">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>_("Indicate that the selected player(s) did not play")</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>_("No move")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonEndTurn">
|
||||
<property name="toolTip">
|
||||
<string>_("Validate the current turn and start a new one")</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>_("End turn")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ClickableLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header location="global">misc_helpers.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>839</width>
|
||||
<height>292</height>
|
||||
<width>761</width>
|
||||
<height>312</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
|
@ -35,7 +35,7 @@
|
|||
<widget class="QLineEdit" name="lineEditRack">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<width>90</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
|
@ -157,146 +157,12 @@
|
|||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>_("Assignments")</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>_("Master move:")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ClickableLabel" name="labelMasterMove">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonSelectMaster">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>_("Select")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxHideAssigned">
|
||||
<property name="text">
|
||||
<string>_("Hide players with an assigned move")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="treeViewPlayers">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonAssign">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>_("Assign move")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonNoMove">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>_("Indicate that the selected player(s) did not play")</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>_("No move")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonEndTurn">
|
||||
<property name="toolTip">
|
||||
<string>_("Validate the current turn and start a new one")</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>_("End turn")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<layout class="QVBoxLayout" name="layoutAssignments"/>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ClickableLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header location="global">misc_helpers.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>lineEditRack</tabstop>
|
||||
<tabstop>buttonRandom</tabstop>
|
||||
|
@ -306,12 +172,6 @@
|
|||
<tabstop>lineEditWord</tabstop>
|
||||
<tabstop>lineEditCoords</tabstop>
|
||||
<tabstop>buttonCheck</tabstop>
|
||||
<tabstop>buttonSelectMaster</tabstop>
|
||||
<tabstop>checkBoxHideAssigned</tabstop>
|
||||
<tabstop>treeViewPlayers</tabstop>
|
||||
<tabstop>buttonAssign</tabstop>
|
||||
<tabstop>buttonNoMove</tabstop>
|
||||
<tabstop>buttonEndTurn</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
Loading…
Add table
Reference in a new issue