Topping: new widget dedicated to topping mode.

It is currently very ugly, and quite buggy...
This commit is contained in:
Olivier Teulière 2012-12-29 18:49:52 +01:00
parent c4635c66f9
commit ac0abba535
8 changed files with 441 additions and 9 deletions

View file

@ -244,6 +244,13 @@ void PublicGame::trainingSetRackManual(bool iCheck, const wstring &iLetters)
/***************************/
vector<Move> PublicGame::toppingGetTriedMoves() const
{
return getTypedGame<Topping>(m_game).getTriedMoves();
}
/***************************/
void PublicGame::duplicateSetPlayer(unsigned int p)
{
getTypedGame<Duplicate>(m_game).setPlayer(p);

View file

@ -21,6 +21,7 @@
#ifndef PUBLIC_GAME_H_
#define PUBLIC_GAME_H_
#include <vector>
#include <string>
class GameParams;
@ -208,6 +209,15 @@ public:
void trainingSetRackManual(bool iCheck, const wstring &iLetters);
/***************
* Topping games
* These methods throw an exception if the current game is not in
* the Topping mode.
***************/
vector<Move> toppingGetTriedMoves() const;
/***************
* Duplicate games
* These methods throw an exception if the current game is not in

View file

@ -54,6 +54,7 @@ EXTRA_DIST = \
ui/player_widget.ui \
ui/prefs_dialog.ui \
ui/tables_dialog.ui \
ui/topping_widget.ui \
ui/training_widget.ui \
eliot.qrc \
$(RESOURCES) \
@ -83,6 +84,7 @@ eliot_SOURCES = \
stats_widget.cpp stats_widget.h \
play_word_mediator.cpp play_word_mediator.h \
tables_dialog.cpp tables_dialog.h \
topping_widget.cpp topping_widget.h \
training_widget.cpp training_widget.h \
player_widget.cpp player_widget.h \
prefs_dialog.cpp prefs_dialog.h \
@ -98,6 +100,7 @@ nodist_eliot_SOURCES = \
ui/new_game.ui.h \
ui/player_widget.ui.h \
ui/tables_dialog.ui.h \
ui/topping_widget.ui.h \
ui/training_widget.ui.h \
ui/prefs_dialog.ui.h \
ui/dic_tools_widget.ui.h \
@ -127,6 +130,7 @@ nodist_eliot_SOURCES = \
play_word_mediator.moc.cpp \
player_widget.moc.cpp \
tables_dialog.moc.cpp \
topping_widget.moc.cpp \
training_widget.moc.cpp \
prefs_dialog.moc.cpp \
aux_window.moc.cpp \

View file

@ -59,6 +59,7 @@
#include "score_widget.h"
#include "player_widget.h"
#include "training_widget.h"
#include "topping_widget.h"
#include "arbitration_widget.h"
#include "history_widget.h"
#include "stats_widget.h"
@ -77,6 +78,7 @@ const char *MainWindow::m_windowName = "MainWindow";
MainWindow::MainWindow(QWidget *iParent)
: QMainWindow(iParent), m_dic(NULL), m_game(NULL),
m_playersWidget(NULL), m_trainingWidget(NULL),
m_toppingWidget(NULL),
m_arbitrationWidget(NULL), m_scoresWidget(NULL),
m_bagWindow(NULL), m_boardWindow(NULL),
m_historyWindow(NULL), m_statsWindow(NULL), m_timerWindow(NULL),
@ -411,6 +413,10 @@ void MainWindow::updateForGame(PublicGame *iGame)
QtCommon::DestroyObject(m_trainingWidget, this);
m_trainingWidget = NULL;
// Destroy the topping widget
QtCommon::DestroyObject(m_toppingWidget, this);
m_toppingWidget = NULL;
// Destroy the arbitration widget
QtCommon::DestroyObject(m_arbitrationWidget, this);
m_arbitrationWidget = NULL;
@ -486,19 +492,16 @@ void MainWindow::updateForGame(PublicGame *iGame)
m_ui.groupBoxPlayers->setTitle(_q("Topping"));
// Players widget
m_playersWidget = new PlayerTabWidget(m_playModel, NULL);
m_ui.groupBoxPlayers->layout()->addWidget(m_playersWidget);
QObject::connect(m_playersWidget, SIGNAL(gameUpdated()),
m_toppingWidget = new ToppingWidget(NULL, m_playModel, iGame);
m_ui.groupBoxPlayers->layout()->addWidget(m_toppingWidget);
QObject::connect(m_toppingWidget, SIGNAL(gameUpdated()),
this, SIGNAL(gameUpdated()));
QObject::connect(m_playersWidget, SIGNAL(notifyInfo(QString)),
QObject::connect(m_toppingWidget, SIGNAL(notifyInfo(QString)),
this, SLOT(displayInfoMsg(QString)));
QObject::connect(m_playersWidget, SIGNAL(notifyProblem(QString)),
QObject::connect(m_toppingWidget, SIGNAL(notifyProblem(QString)),
this, SLOT(displayErrorMsg(QString)));
QObject::connect(m_playersWidget, SIGNAL(requestDefinition(QString)),
this, SLOT(showDefinition(QString)));
QObject::connect(this, SIGNAL(gameUpdated()),
m_playersWidget, SLOT(refresh()));
m_playersWidget->setGame(iGame);
m_toppingWidget, SLOT(refresh()));
// Players score
m_scoresWidget = new ScoreWidget(NULL, iGame);

View file

@ -41,6 +41,7 @@ class HistoryTabWidget;
class PlayerTabWidget;
class ScoreWidget;
class TrainingWidget;
class ToppingWidget;
class ArbitrationWidget;
class AuxWindow;
class TimerModel;
@ -149,6 +150,9 @@ private:
/// Widget for the training mode
TrainingWidget *m_trainingWidget;
/// Widget for the topping mode
ToppingWidget *m_toppingWidget;
/// Widget for the arbitration mode
ArbitrationWidget *m_arbitrationWidget;

164
qt/topping_widget.cpp Normal file
View file

@ -0,0 +1,164 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2010-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 <QtGui/QStandardItemModel>
#include <QtGui/QMenu>
#include <QtGui/QHeaderView>
#include "topping_widget.h"
#include "qtcommon.h"
#include "play_word_mediator.h"
#include "validator_factory.h"
#include "player.h"
#include "dic.h"
#include "move.h"
#include "public_game.h"
#include "game_exception.h"
#include "debug.h"
using namespace std;
INIT_LOGGER(qt, ToppingWidget);
ToppingWidget::ToppingWidget(QWidget *parent, PlayModel &iPlayModel, PublicGame *iGame)
: QWidget(parent), m_game(iGame), m_autoResizeColumns(true)
{
setupUi(this);
tableViewMoves->setAlternatingRowColors(true);
blackPalette = lineEditRack->palette();
redPalette = lineEditRack->palette();
redPalette.setColor(QPalette::Text, Qt::red);
// Use the mediator
m_mediator = new PlayWordMediator(this, *lineEditPlay, *lineEditCoords,
*lineEditPoints, *pushButtonPlay,
iPlayModel, m_game);
QObject::connect(m_mediator, SIGNAL(gameUpdated()),
this, SIGNAL(gameUpdated()));
QObject::connect(m_mediator, SIGNAL(notifyProblem(QString)),
this, SIGNAL(notifyProblem(QString)));
// Associate the model to the view
m_model = new QStandardItemModel(this);
tableViewMoves->setModel(m_model);
m_model->setColumnCount(3);
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);
QObject::connect(lineEditRack, SIGNAL(returnPressed()),
this, SLOT(search()));
// Add a context menu to the table header
QAction *lockSizesAction = new QAction(_q("Lock columns sizes"), this);
lockSizesAction->setCheckable(true);
lockSizesAction->setStatusTip(_q("Disable auto-resizing of the columns"));
tableViewMoves->horizontalHeader()->addAction(lockSizesAction);
tableViewMoves->horizontalHeader()->setContextMenuPolicy(Qt::ActionsContextMenu);
QObject::connect(lockSizesAction, SIGNAL(toggled(bool)),
this, SLOT(lockSizesChanged(bool)));
// Allow very thin columns
tableViewMoves->horizontalHeader()->setMinimumSectionSize(1);
refresh();
}
void ToppingWidget::refresh()
{
updateModel();
if (m_game == NULL)
{
lineEditRack->setText("");
lineEditRack->setEnabled(false);
pushButtonPlay->setEnabled(false);
}
else
{
wstring rack = m_game->getPlayer(0).getCurrentRack().toString(PlayedRack::RACK_SIMPLE);
// Update the rack only if it is needed, to avoid losing cursor position
if (qfw(rack) != lineEditRack->text())
lineEditRack->setText(qfw(rack));
lineEditPlay->clear();
lineEditCoords->clear();
lineEditRack->setEnabled(true);
// Do not allow entering a move when displaying an old turn
setEnabled(m_game->isLastTurn());
}
}
void ToppingWidget::updateModel()
{
// Clear the table
m_model->removeRows(0, m_model->rowCount());
// Force the sort column
tableViewMoves->sortByColumn(2);
if (m_game == NULL)
return;
const vector<Move> &triedMoves = m_game->toppingGetTriedMoves();
for (unsigned int i = 0; i < triedMoves.size(); ++i)
{
const Move &m = triedMoves[i];
int rowNum = m_model->rowCount();
m_model->insertRow(rowNum);
if (m.isValid())
{
m_model->setData(m_model->index(rowNum, 0), qfw(m.getRound().getWord()));
m_model->setData(m_model->index(rowNum, 1),
qfw(m.getRound().getCoord().toString()));
}
else
{
ASSERT(m.isInvalid(), "Unhandled move type");
m_model->setData(m_model->index(rowNum, 0), qfw(m.getBadWord()));
m_model->setData(m_model->index(rowNum, 1), qfw(m.getBadCoord()));
}
m_model->setData(m_model->index(rowNum, 2), m.getScore());
}
if (m_autoResizeColumns)
{
tableViewMoves->resizeColumnToContents(0);
tableViewMoves->resizeColumnToContents(1);
tableViewMoves->resizeColumnToContents(2);
}
}
void ToppingWidget::lockSizesChanged(bool checked)
{
m_autoResizeColumns = !checked;
}
QSize ToppingWidget::sizeHint() const
{
return QSize(160, 300);
}

85
qt/topping_widget.h Normal file
View file

@ -0,0 +1,85 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008-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 TOPPING_WIDGET_H_
#define TOPPING_WIDGET_H_
#include <QtGui/QWidget>
#include "ui/topping_widget.ui.h"
#include "logging.h"
class QStandardItemModel;
class QString;
class QPoint;
class PlayModel;
class PlayWordMediator;
class PublicGame;
class ToppingWidget: public QWidget, private Ui::ToppingWidget
{
Q_OBJECT;
DEFINE_LOGGER();
public:
explicit ToppingWidget(QWidget *parent, PlayModel &iPlayModel, PublicGame *iGame);
public slots:
void refresh();
signals:
void gameUpdated();
void notifyProblem(QString iMsg);
void notifyInfo(QString iMsg);
void rackUpdated(const QString &iRack);
protected:
/// Define a default size
virtual QSize sizeHint() const;
private slots:
void lockSizesChanged(bool checked);
private:
/// Encapsulated training game, can be NULL
PublicGame *m_game;
/// Indicate whether the columns should be resized after a search
bool m_autoResizeColumns;
/// Model of the search results
QStandardItemModel *m_model;
/// Mediator for the "play word" controls
PlayWordMediator *m_mediator;
/// Palette to write text in black
QPalette blackPalette;
/// Palette to write text in red
QPalette redPalette;
/// Force synchronizing the model with the contents of the search results
void updateModel();
};
#endif

155
qt/ui/topping_widget.ui Normal file
View file

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ToppingWidget</class>
<widget class="QWidget" name="ToppingWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>560</width>
<height>123</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="layoutWidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>_(&quot;Rack:&quot;)</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditRack">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="pushButtonShuffle">
<property name="text">
<string>_(&quot;Shu&amp;ffle&quot;)</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>_(&quot;Ref.:&quot;)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEditCoords">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>45</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>_(&quot;Enter the coordinates of the word. Specify the row before the column for horizontal words, and the column before the row for vertical words. E.g.: H4 or 4H&quot;)</string>
</property>
<property name="statusTip">
<string>_(&quot;Enter the coordinates of the word. Specify the row before the column for horizontal words, and the column before the row for vertical words. E.g.: H4 or 4H&quot;)</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>_(&quot;Word:&quot;)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="lineEditPlay">
<property name="toolTip">
<string>_(&quot;Enter the word to play (case-insensitive). A joker from the rack must be written in parentheses. E.g.: w(o)rd or W(O)RD&quot;)</string>
</property>
<property name="statusTip">
<string>_(&quot;Enter the word to play (case-insensitive). A joker from the rack must be written in parentheses. E.g.: w(o)rd or W(O)RD&quot;)</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="pushButtonPlay">
<property name="text">
<string>_(&quot;Play&quot;)</string>
</property>
</widget>
</item>
<item row="3" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2">
<widget class="QLineEdit" name="lineEditPoints">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QTableView" name="tableViewMoves">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>