Very beginning of a Qt interface. Status:

- the multiplayer modes are more or less playable
 - the training mode is not playable at all
 - the current layout is still experimental
 - many dialogs and options are missing
 - tested on Linux only

There are still hundreds of things to do...
This commit is contained in:
Olivier Teulière 2008-01-20 18:40:12 +00:00
parent 7d81fc5420
commit 0bcc2c0930
27 changed files with 2512 additions and 75 deletions

View file

@ -1,4 +1,4 @@
SUBDIRS = intl dic game utils wxwin po
SUBDIRS = intl dic game utils wxwin qt po
ACLOCAL_AMFLAGS = -I m4

View file

@ -21,6 +21,7 @@ AC_GNU_SOURCE
AC_PROG_CXX
AC_PROG_MAKE_SET
AC_PROG_RANLIB
PKG_PROG_PKG_CONFIG
AC_PROG_YACC
if test "$YACC" = yacc ; then
@ -153,6 +154,21 @@ else
fi
AM_CONDITIONAL([BUILD_NCURSES], [test "${want_ncurses}" = "1"])
dnl check for Qt
AC_ARG_ENABLE([qt],AC_HELP_STRING([--enable-qt],
[Qt interface support (default disabled)]))
qt_ok=0
AS_IF([test "${enable_qt}" = "yes"],
[PKG_CHECK_MODULES(QT, [QtCore QtGui >= 4.2.0],
[qt_ok=1
AC_PATH_PROG(MOC, moc, moc,`$PKG_CONFIG --variable=exec_prefix QtCore`/bin)
AC_PATH_PROG(UIC, uic, uic,`$PKG_CONFIG --variable=exec_prefix QtCore`/bin)
],
[AC_MSG_ERROR([Could not find Qt on your system (using pkg-config)])]
)
])
AM_CONDITIONAL([BUILD_QT], [test "${qt_ok}" = "1"])
dnl Enable/disable text version
AC_ARG_ENABLE([text],AC_HELP_STRING([--enable-text],[text interface support (default enabled)]))
AM_CONDITIONAL([BUILD_TEXT], [test "${enable_text}" != "no"])
@ -192,7 +208,8 @@ dnl --------------------------------------------------------------
AC_CONFIG_FILES(intl/Makefile po/Makefile.in
dic/Makefile
game/Makefile
wxwin/Makefile
utils/Makefile
wxwin/Makefile
qt/Makefile
Makefile)
AC_OUTPUT

View file

@ -8,7 +8,7 @@ subdir = po
top_builddir = ..
# These options get passed to xgettext.
XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ --keyword=_q --language=C++
# This is the copyright holder that gets inserted into the header of the
# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding

View file

@ -1,72 +1,92 @@
./dic/automaton.cpp
./dic/automaton.h
./dic/header.cpp
./dic/header.h
./dic/dic.cpp
./dic/dic.h
./dic/dic_internals.h
./dic/dic_search.cpp
./dic/hashtable.cpp
./dic/hashtable.h
./dic/regexp.cpp
./dic/regexp.h
./dic/tile.cpp
./dic/tile.h
./dic/compdic.cpp
./dic/listdic.cpp
./dic/regexpmain.cpp
./game/bag.cpp
./game/bag.h
./game/board.cpp
./game/board.h
./game/board_cross.cpp
./game/board_search.cpp
./game/cross.cpp
./game/cross.h
./game/debug.h
./game/duplicate.cpp
./game/duplicate.h
./game/freegame.cpp
./game/freegame.h
./game/game.cpp
./game/game.h
./game/game_io.cpp
./game/history.cpp
./game/history.h
./game/player.cpp
./game/player.h
./game/pldrack.cpp
./game/pldrack.h
./game/rack.cpp
./game/rack.h
./game/results.cpp
./game/results.h
./game/round.cpp
./game/round.h
./game/training.cpp
./game/training.h
#./utils/eliottxt.cpp
./utils/game_io.h
./utils/game_io.cpp
./utils/ncurses.cpp
./utils/ncurses.h
./wxwin/auxframes.h
./wxwin/auxframes.cc
./wxwin/confdimdlg.h
./wxwin/confdimdlg.cc
./wxwin/configdb.h
./wxwin/configdb.cc
./wxwin/confsearch.h
./wxwin/confsearch.cc
./wxwin/ewx.h
./wxwin/gfxboard.h
./wxwin/gfxboard.cc
./wxwin/gfxresult.h
./wxwin/gfxresult.cc
./wxwin/main.cc
./wxwin/mainframe.h
./wxwin/mainframe.cc
./wxwin/printout.h
./wxwin/printout.cc
./wxwin/searchpanel.h
./wxwin/searchpanel.cc
dic/automaton.cpp
dic/automaton.h
dic/header.cpp
dic/header.h
dic/dic.cpp
dic/dic.h
dic/dic_internals.h
dic/dic_search.cpp
dic/hashtable.cpp
dic/hashtable.h
dic/regexp.cpp
dic/regexp.h
dic/tile.cpp
dic/tile.h
dic/compdic.cpp
dic/listdic.cpp
dic/regexpmain.cpp
game/bag.cpp
game/bag.h
game/board.cpp
game/board.h
game/board_cross.cpp
game/board_search.cpp
game/cross.cpp
game/cross.h
game/debug.h
game/duplicate.cpp
game/duplicate.h
game/freegame.cpp
game/freegame.h
game/game.cpp
game/game.h
game/game_io.cpp
game/history.cpp
game/history.h
game/player.cpp
game/player.h
game/pldrack.cpp
game/pldrack.h
game/rack.cpp
game/rack.h
game/results.cpp
game/results.h
game/round.cpp
game/round.h
game/training.cpp
game/training.h
# utils/eliottxt.cpp
utils/game_io.h
utils/game_io.cpp
utils/ncurses.cpp
utils/ncurses.h
wxwin/auxframes.h
wxwin/auxframes.cc
wxwin/confdimdlg.h
wxwin/confdimdlg.cc
wxwin/configdb.h
wxwin/configdb.cc
wxwin/confsearch.h
wxwin/confsearch.cc
wxwin/ewx.h
wxwin/gfxboard.h
wxwin/gfxboard.cc
wxwin/gfxresult.h
wxwin/gfxresult.cc
wxwin/main.cc
wxwin/mainframe.h
wxwin/mainframe.cc
wxwin/printout.h
wxwin/printout.cc
wxwin/searchpanel.h
wxwin/searchpanel.cc
qt/aux_window.cpp
qt/aux_window.h
qt/bag_widget.cpp
qt/bag_widget.h
qt/board_widget.cpp
qt/board_widget.h
qt/history_widget.cpp
qt/history_widget.h
qt/main_window.cpp
qt/main_window.h
qt/main.cpp
qt/new_game.cpp
qt/new_game.h
qt/player_widget.cpp
qt/player_widget.h
qt/score_widget.cpp
qt/score_widget.h
qt/ui/new_game.ui
qt/ui/player_widget.ui
qt/ui/main_window.ui

7
qt/.cvsignore Normal file
View file

@ -0,0 +1,7 @@
.deps
Makefile
Makefile.in
qeliot
qeliot.exe
cscope.files
cscope.out

80
qt/Makefile.am Normal file
View file

@ -0,0 +1,80 @@
# Eliot
# Copyright (C) 2008 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
localedir = $(datadir)/locale
if BUILD_QT
AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" @QT_CFLAGS@ -I$(top_srcdir) -I../intl -I$(top_srcdir)/dic -I$(top_srcdir)/game
SUFFIXES=.ui.h .moc.cpp
bin_PROGRAMS = qeliot
EXTRA_DIST = \
ui/main_window.ui \
ui/new_game.ui \
ui/player_widget.ui
BUILT_SOURCES = \
ui/main_window.ui.h \
ui/new_game.ui.h \
ui/player_widget.ui.h \
new_game.moc.cpp \
bag_widget.moc.cpp \
score_widget.moc.cpp \
board_widget.moc.cpp \
player_widget.moc.cpp \
history_widget.moc.cpp \
aux_window.moc.cpp \
main_window.moc.cpp
qeliot_SOURCES = \
qtcommon.h \
bag_widget.cpp bag_widget.h \
new_game.cpp new_game.h \
score_widget.cpp score_widget.h \
board_widget.cpp board_widget.h \
history_widget.cpp history_widget.h \
player_widget.cpp player_widget.h \
aux_window.cpp aux_window.h \
main_window.cpp main_window.h \
main.cpp
qeliot_SOURCES += $(BUILT_SOURCES)
qeliot_LDADD = @QT_LIBS@ ../game/libgame.a ../dic/libdic.a @LIBINTL@
# Generate the implementation file from the header
%.moc.cpp: %.h
$(MOC) -o $@ $<
# Generate the header from the .ui file
# We want to translate the string with gettext, not Qt own way
%.ui.h: %.ui
mkdir -p ui
rm -f $@ $@.tmp
echo "// Note: Lines below generated by Eliot build system" > $@.tmp
echo "#include \"qtcommon.h\"" >> $@.tmp
echo "#define Q_(a,b) QString::fromUtf8(_(a))" >> $@.tmp
$(UIC) -tr "Q_" $< >> $@.tmp
sed 's/Q_(\"_(\\\"\(.*\)\\\")"/Q_("\1"/' $@.tmp >$@
rm -f $@.tmp
endif

57
qt/aux_window.cpp Normal file
View file

@ -0,0 +1,57 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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/QAction>
#include <QtGui/QWidget>
#include <QtGui/QVBoxLayout>
#include "aux_window.h"
AuxWindow::AuxWindow(QWidget &iWidget, QAction *iAction)
: m_widget(iWidget), m_action(iAction)
{
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(&iWidget);
setLayout(layout);
}
AuxWindow::~AuxWindow()
{
delete &m_widget;
}
void AuxWindow::showEvent(QShowEvent * event)
{
if (m_action)
m_action->setChecked(true);
QWidget::showEvent(event);
}
void AuxWindow::hideEvent(QHideEvent * event)
{
if (m_action)
m_action->setChecked(false);
QWidget::hideEvent(event);
}

58
qt/aux_window.h Normal file
View file

@ -0,0 +1,58 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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 AUX_WINDOW_H_
#define AUX_WINDOW_H_
#include <QtGui/QWidget>
class QAction;
/**
* This class is a wrapper for widgets which should be in their own window.
* It ensures that all the auxiliary windows have a common behaviour, which
* we can change easily.
*/
class AuxWindow: public QWidget
{
Q_OBJECT;
public:
/**
* Constructor. The AuxWindow takes ownership of the given widget (i.e. it
* is responsible for its deletion).
* The optional action checked/unchecked when the window is shown/hidden
*/
AuxWindow(QWidget &iWidget, QAction *iAction = NULL);
~AuxWindow();
protected:
virtual void showEvent(QShowEvent *event);
virtual void hideEvent(QHideEvent *event);
private:
QWidget &m_widget;
/// Action to check/uncheck
QAction *m_action;
};
#endif

91
qt/bag_widget.cpp Normal file
View file

@ -0,0 +1,91 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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 <vector>
#include <QtGui/QTreeView>
#include <QtGui/QStandardItemModel>
#include "bag_widget.h"
#include "qtcommon.h"
#include "dic.h"
#include "tile.h"
#include "bag.h"
using namespace std;
BagWidget::BagWidget(QWidget *parent, const Bag *iBag)
: QTreeView(parent), m_bag(iBag)
{
// Create the tree view
setEditTriggers(QAbstractItemView::NoEditTriggers);
setRootIsDecorated(false);
setSortingEnabled(true);
QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Expanding);
setSizePolicy(policy);
// Associate the model to the view
m_model = new QStandardItemModel(this);
setModel(m_model);
updateModel();
}
void BagWidget::setBag(const Bag *iBag)
{
m_bag = iBag;
updateModel();
}
void BagWidget::updateModel()
{
m_model->clear();
m_model->setColumnCount(2);
m_model->setHeaderData(0, Qt::Horizontal, _q("Letter"), Qt::DisplayRole);
m_model->setHeaderData(1, Qt::Horizontal, _q("Points"), Qt::DisplayRole);
if (m_bag == NULL)
return;
const vector<Tile>& allTiles = m_bag->getDic().getAllTiles();
vector<Tile>::const_iterator it;
for (it = allTiles.begin(); it != allTiles.end(); ++it)
{
unsigned int nb = m_bag->in(*it);
if (nb != 0)
{
int rowNum = m_model->rowCount();
m_model->insertRow(rowNum);
m_model->setData(m_model->index(rowNum, 0),
qfw(wstring(nb, it->toChar())));
m_model->setData(m_model->index(rowNum, 1), it->getPoints());
}
}
//resizeColumnToContents(0);
resizeColumnToContents(1);
}
QSize BagWidget::sizeHint() const
{
return QSize(160, 300);
}

56
qt/bag_widget.h Normal file
View file

@ -0,0 +1,56 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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 BAG_WIDGET_H_
#define BAG_WIDGET_H_
#include <QtGui/QTreeView>
class Bag;
class QStandardItemModel;
class BagWidget: public QTreeView
{
Q_OBJECT;
public:
explicit BagWidget(QWidget *parent = 0, const Bag *iBag = NULL);
public slots:
void setBag(const Bag *iBag = NULL);
protected:
/// Define a default size
virtual QSize sizeHint() const;
private:
/// Encapsulated bag, can be NULL
const Bag *m_bag;
/// Model of the bag
QStandardItemModel *m_model;
/// Force synchronizing the model with the contents of the bag
void updateModel();
};
#endif

123
qt/board_widget.cpp Normal file
View file

@ -0,0 +1,123 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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 <math.h>
#include <QtGui/QPainter>
#include <QtGui/QPaintEvent>
#include "board_widget.h"
#include "qtcommon.h"
#include "tile.h"
#include "board.h"
using namespace std;
const QColor BoardWidget::EmptyColour(Qt::white);
const QColor BoardWidget::L2Colour(34, 189, 240);
const QColor BoardWidget::L3Colour(29, 104, 240);
const QColor BoardWidget::W2Colour(255, 147, 196);
const QColor BoardWidget::W3Colour(240, 80, 94);
const QColor BoardWidget::TileColour(255, 235, 205);
BoardWidget::BoardWidget(QWidget *parent, const Board *iBoard)
: QFrame(parent), m_board(iBoard)
{
setFrameStyle(QFrame::Panel);
// Use as much space as possible
QSizePolicy policy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setSizePolicy(policy);
setMinimumSize(200, 200);
}
void BoardWidget::setBoard(const Board *iBoard)
{
m_board = iBoard;
refresh();
}
void BoardWidget::refresh()
{
update();
}
QSize BoardWidget::sizeHint() const
{
return QSize(300, 300);
}
void BoardWidget::paintEvent(QPaintEvent *)
{
int size = std::min(width(), height());
int squareSize = (int)floor((size - 1) / (BOARD_MAX - BOARD_MIN + 2));
// XXX: Naive implementation: we repaint everything every time
QPainter painter(this);
//painter.setPen(Qt::NoPen);
for (unsigned int row = BOARD_MIN; row <= BOARD_MAX; ++row)
{
for (unsigned int col = BOARD_MIN; col <= BOARD_MAX; ++col)
{
// Set the brush color
if (m_board != NULL && !m_board->getTile(row, col).isEmpty())
painter.setBrush(TileColour);
else if (Board::GetWordMultiplier(row, col) == 3)
painter.setBrush(W3Colour);
else if (Board::GetWordMultiplier(row, col) == 2)
painter.setBrush(W2Colour);
else if (Board::GetLetterMultiplier(row, col) == 3)
painter.setBrush(L3Colour);
else if (Board::GetLetterMultiplier(row, col) == 2)
painter.setBrush(L2Colour);
else
painter.setBrush(EmptyColour);
painter.drawRect((col - BOARD_MIN + 1) * squareSize,
(row - BOARD_MIN + 1) * squareSize,
squareSize, squareSize);
// Draw the letter
if (m_board != NULL && !m_board->getTile(row, col).isEmpty())
{
painter.drawText((col - BOARD_MIN + 1) * squareSize,
(row - BOARD_MIN + 1) * squareSize + 1,
squareSize, squareSize,
Qt::AlignCenter,
qfw(wstring(1, m_board->getTile(row, col).toChar())));
}
}
}
// Draw the coordinates
for (unsigned x = 1; x <= BOARD_MAX - BOARD_MIN + 1; ++x)
{
painter.drawText(x * squareSize, 1,
squareSize, squareSize,
Qt::AlignCenter,
QString::number(x));
painter.drawText(0, x * squareSize,
squareSize, squareSize,
Qt::AlignCenter,
QString(1, 'A' + x - 1));
}
}

63
qt/board_widget.h Normal file
View file

@ -0,0 +1,63 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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 BOARD_WIDGET_H_
#define BOARD_WIDGET_H_
#include <QtGui/QFrame>
class Board;
class QTreeView;
class BoardWidget: public QFrame
{
Q_OBJECT;
public:
explicit BoardWidget(QWidget *parent = 0, const Board *iBoard = NULL);
public slots:
void setBoard(const Board *iBoard = NULL);
void refresh();
protected:
/// Define a default size
virtual QSize sizeHint() const;
/// Paint the board
virtual void paintEvent(QPaintEvent *iEvent);
private:
/// Encapsulated board, can be NULL
const Board *m_board;
/// Define a few background colours
//@{
static const QColor EmptyColour;
static const QColor L2Colour;
static const QColor L3Colour;
static const QColor W2Colour;
static const QColor W3Colour;
static const QColor TileColour;
//@}
};
#endif

126
qt/history_widget.cpp Normal file
View file

@ -0,0 +1,126 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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 <iostream>
#include <QtGui/QTreeView>
#include <QtGui/QStandardItemModel>
#include "history_widget.h"
#include "qtcommon.h"
#include "dic.h"
#include "tile.h"
#include "history.h"
#include "turn.h"
#include "move.h"
using namespace std;
HistoryWidget::HistoryWidget(QWidget *parent, const History *iHistory)
: QTreeView(parent), m_history(iHistory)
{
// Create the tree view
setEditTriggers(QAbstractItemView::NoEditTriggers);
setRootIsDecorated(false);
// Associate the model to the view
m_model = new QStandardItemModel(this);
setModel(m_model);
updateModel();
}
void HistoryWidget::setHistory(const History *iHistory)
{
m_history = iHistory;
updateModel();
}
void HistoryWidget::updateModel()
{
m_model->clear();
m_model->setColumnCount(6);
m_model->setHeaderData(0, Qt::Horizontal, _q("Turn"), Qt::DisplayRole);
m_model->setHeaderData(1, Qt::Horizontal, _q("Rack"), Qt::DisplayRole);
m_model->setHeaderData(2, Qt::Horizontal, _q("Word"), Qt::DisplayRole);
m_model->setHeaderData(3, Qt::Horizontal, _q("Ref"), Qt::DisplayRole);
m_model->setHeaderData(4, Qt::Horizontal, _q("Points"), Qt::DisplayRole);
m_model->setHeaderData(5, Qt::Horizontal, _q("Player"), Qt::DisplayRole);
if (m_history != NULL)
{
for (unsigned int i = 0; i < m_history->getSize(); ++i)
{
int rowNum = m_model->rowCount();
m_model->insertRow(rowNum);
QColor color = Qt::black;
const Turn& t = m_history->getTurn(i);
const Move& m = t.getMove();
// Set data common to all moves)
m_model->setData(m_model->index(rowNum, 0), i + 1);
m_model->setData(m_model->index(rowNum, 1),
qfw(t.getPlayedRack().toString()));
m_model->setData(m_model->index(rowNum, 4), m.getScore());
m_model->setData(m_model->index(rowNum, 5), t.getPlayer() + 1);
// Set the rest
if (m.getType() == Move::VALID_ROUND)
{
const Round &r = m.getRound();
wstring coord = r.getCoord().toString();
m_model->setData(m_model->index(rowNum, 2), qfw(r.getWord()));
m_model->setData(m_model->index(rowNum, 3), qfw(coord));
color = Qt::black;
}
else if (m.getType() == Move::INVALID_WORD)
{
m_model->setData(m_model->index(rowNum, 2),
"<" + qfw(m.getBadWord()) + ">");
m_model->setData(m_model->index(rowNum, 3), qfw(m.getBadCoord()));
color = Qt::red;
}
else if (m.getType() == Move::PASS)
{
m_model->setData(m_model->index(rowNum, 2), _q("(PASS)"));
color = Qt::blue;
}
else
{
m_model->setData(m_model->index(rowNum, 2),
"[-" + qfw(m.getChangedLetters()) + "]");
color = Qt::blue;
}
// Set the color of the text
for (int col = 0; col < 6; ++col)
{
m_model->setData(m_model->index(rowNum, col),
QBrush(color), Qt::ForegroundRole);
}
}
}
resizeColumnToContents(0);
resizeColumnToContents(3);
resizeColumnToContents(4);
resizeColumnToContents(5);
}

52
qt/history_widget.h Normal file
View file

@ -0,0 +1,52 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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 HISTORY_WIDGET_H_
#define HISTORY_WIDGET_H_
#include <QtGui/QTreeView>
class History;
class QStandardItemModel;
class HistoryWidget: public QTreeView
{
Q_OBJECT;
public:
explicit HistoryWidget(QWidget *parent = 0, const History *iHistory = NULL);
public slots:
void setHistory(const History *iHistory = NULL);
private:
/// Encapsulated history, can be NULL
const History *m_history;
/// Model of the history
QStandardItemModel *m_model;
/// Force synchronizing the model with the contents of the history
void updateModel();
};
#endif

44
qt/main.cpp Normal file
View file

@ -0,0 +1,44 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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 "config.h"
#include <qapplication.h>
#include "main_window.h"
int main(int argc, char **argv)
{
#if HAVE_SETLOCALE
// Set locale via LC_ALL
setlocale(LC_ALL, "");
#endif
#if ENABLE_NLS
// Set the message domain
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#endif
QApplication app(argc, argv);
MainWindow qmain;
qmain.move(200, 200);
qmain.show();
return app.exec();
}

265
qt/main_window.cpp Normal file
View file

@ -0,0 +1,265 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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 "config.h"
#include <QtGui/QMessageBox>
#include <QtGui/QFileDialog>
#include <QtGui/QDockWidget>
#include "main_window.h"
#include "dic.h"
#include "encoding.h"
#include "header.h"
#include "game.h"
#include "freegame.h"
#include "player.h"
#include "debug.h"
#include "new_game.h"
#include "bag_widget.h"
#include "board_widget.h"
#include "score_widget.h"
#include "player_widget.h"
#include "history_widget.h"
#include "aux_window.h"
#include "qtcommon.h"
#include "round.h"
#include "coord.h"
MainWindow::MainWindow(QWidget *iParent)
: QMainWindow(iParent), m_dic(NULL), m_game(NULL), m_newGame(NULL),
m_bagWindow(NULL)
{
m_ui.setupUi(this);
// Cascading signals
QObject::connect(this, SIGNAL(gameChanged(const Game*)),
this, SLOT(gameUpdated()));
// Create the main window
BoardWidget *boardWidget = new BoardWidget;
QObject::connect(this, SIGNAL(boardChanged(const Board*)),
boardWidget, SLOT(setBoard(const Board*)));
QDockWidget *dock = new QDockWidget;
dock->setWidget(boardWidget);
boardWidget->setWindowTitle(_q("Board"));
ScoreWidget *scores = new ScoreWidget;
QObject::connect(this, SIGNAL(gameChanged(const Game*)),
scores, SLOT(setGame(const Game*)));
HistoryWidget *historyWidget = new HistoryWidget;
QObject::connect(this, SIGNAL(historyChanged(const History*)),
historyWidget, SLOT(setHistory(const History*)));
QHBoxLayout *hlayout = new QHBoxLayout;
hlayout->addWidget(dock);
hlayout->addWidget(scores);
hlayout->addWidget(historyWidget);
m_ui.groupBoxTest->setLayout(hlayout);
// XXX: temporary, for testing purposes!
try
{
m_dic = new Dictionary("/home/ipkiss/ods5.dawg");
}
catch (...)
{
// Ignore the error silently :)
}
}
MainWindow::~MainWindow()
{
delete m_bagWindow;
delete m_game;
delete m_dic;
}
void MainWindow::on_action_About_triggered()
{
QString msg;
msg.sprintf("Eliot %s\n\n", VERSION);
msg += _q( \
"Copyright (C) 1999-2008 - Antoine Fraboulet & Olivier Teuliere\n\n" \
"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.");
// QMessageBox::about() doesn't add the nice information icon, so we create
// the box manually (not much work...)
QMessageBox *aboutBox = new QMessageBox(QMessageBox::Information,
_q("About Eliot"), msg, QMessageBox::Ok, this);
aboutBox->exec();
}
void MainWindow::on_action_Bag_triggered()
{
if (m_bagWindow == NULL)
{
// Create the bag window
BagWidget *bagWidget =
new BagWidget(NULL, m_game ? &m_game->getBag() : NULL);
m_bagWindow = new AuxWindow(*bagWidget, m_ui.action_Bag);
QObject::connect(this, SIGNAL(bagChanged(const Bag*)),
bagWidget, SLOT(setBag(const Bag*)));
// XXX
m_bagWindow->move(20, 20);
}
if (m_bagWindow->isVisible())
m_bagWindow->hide();
else
m_bagWindow->show();
}
void MainWindow::on_action_ChooseDic_triggered()
{
QString fileName =
QFileDialog::getOpenFileName(this, _q("Choose a dictionary"), "", "*.dawg");
if (!fileName.isEmpty())
{
try
{
Dictionary *dic = new Dictionary(qtl(fileName));
delete m_dic;
m_dic = dic;
emit dicChanged(fileName, qfw(m_dic->getHeader().getName()));
}
catch (std::exception &e)
{
displayErrorMsg(e.what());
}
}
}
void MainWindow::on_action_New_Game_triggered()
{
if (m_dic == NULL)
{
displayErrorMsg(_q("You have to select a dictionary first!"));
return;
}
if (m_newGame == NULL)
m_newGame = new NewGame(this);
int res = m_newGame->exec();
if (res == QDialog::Rejected)
return;
m_game = m_newGame->createGame(*m_dic);
if (m_game == NULL)
return;
int nbTabs = m_ui.tabWidgetPlayers->count();
for (int i = 0; i < nbTabs; ++i)
m_ui.tabWidgetPlayers->removeTab(0);
m_game->start();
for (unsigned int i = 0; i < m_game->getNPlayers(); ++i)
{
PlayerWidget *r = new PlayerWidget(NULL, i, m_game);
QObject::connect(this, SIGNAL(rackChanged()), r, SLOT(refresh()));
QObject::connect(r, SIGNAL(playingWord(unsigned int, QString, QString)),
this, SLOT(playerPlays(unsigned int, QString, QString)));
QObject::connect(r, SIGNAL(passing(unsigned int, QString)),
this, SLOT(playerPasses(unsigned int, QString)));
m_ui.tabWidgetPlayers->addTab(r, qfw(m_game->getPlayer(i).getName()));
}
emit gameChanged(m_game);
}
void MainWindow::gameUpdated()
{
emit bagChanged(&m_game->getBag());
emit boardChanged(&m_game->getBoard());
emit historyChanged(&m_game->getHistory());
emit rackChanged();
}
void MainWindow::playerPlays(unsigned int p, QString iWord, QString iCoord)
{
cerr << "Player " << p << " plays \"" << convertToMb(qtw(iWord))
<< "\" in " << convertToMb(qtw(iCoord)) << endl;
int res = m_game->play(qtw(iCoord), qtw(iWord));
if (res)
{
// XXX: tmp
QString error;
error.sprintf("Error: %d", res);
displayErrorMsg(error, qfl("playing word"));
return;
}
emit gameChanged(m_game);
}
void MainWindow::playerPasses(unsigned int p, QString iChangedLetters)
{
if (iChangedLetters == "")
{
cerr << "Player " << p << " passes" << endl;
}
else
{
cerr << "Player " << p << " changes \""
<< convertToMb(qtw(iChangedLetters)) << "\"" << endl;
}
FreeGame *free = dynamic_cast<FreeGame*>(m_game);
ASSERT(free != NULL,
"MainWindow::playerPasses() called while not in a free game");
int res = free->pass(qtw(iChangedLetters));
if (res)
{
// XXX: tmp
QString error;
error.sprintf("Error: %d", res);
displayErrorMsg(error, qfl("playing word"));
return;
}
emit bagChanged(&m_game->getBag());
emit boardChanged(&m_game->getBoard());
emit historyChanged(&m_game->getHistory());
emit rackChanged();
}
void MainWindow::displayErrorMsg(QString iMsg, QString iContext)
{
if (iContext == "")
iContext = PACKAGE_NAME;
QMessageBox::warning(this, iContext, iMsg);
}

87
qt/main_window.h Normal file
View file

@ -0,0 +1,87 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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 MAIN_WINDOW_H_
#define MAIN_WINDOW_H_
#include <QMainWindow>
#include <ui/main_window.ui.h>
class Dictionary;
class Bag;
class Board;
class History;
class Game;
class NewGame;
class AuxWindow;
class MainWindow: public QMainWindow
{
Q_OBJECT;
public:
MainWindow(QWidget *iParent = 0);
~MainWindow();
signals:
void dicChanged(QString iDicFile, QString iDicName);
void gameChanged(const Game *iGame);
void bagChanged(const Bag *iBag);
void boardChanged(const Board *iBoard);
void historyChanged(const History *iHistory);
void rackChanged();
public slots:
void playerPlays(unsigned int p, QString iWord, QString iCoord);
void playerPasses(unsigned int p, QString iLetters);
private slots:
/// Emit various specific signals
void gameUpdated();
void on_action_About_triggered();
void on_action_Bag_triggered();
void on_action_ChooseDic_triggered();
void on_action_New_Game_triggered();
private:
/// Display an error message to the user
void displayErrorMsg(QString iMsg, QString iContext = QString());
/// Current dictionary
const Dictionary *m_dic;
/// Current game
Game *m_game;
/// The UI file generated with Qt Designer
Ui::MainWindow m_ui;
/// Dialog for creating a new game
NewGame *m_newGame;
/// Bag window
AuxWindow *m_bagWindow;
};
#endif

242
qt/new_game.cpp Normal file
View file

@ -0,0 +1,242 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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/QKeyEvent>
#include <QtGui/QMessageBox>
#include "new_game.h"
#include "qtcommon.h"
#include "game_factory.h"
#include "game.h"
#include "training.h"
#include "freegame.h"
#include "duplicate.h"
#include "player.h"
const QString NewGame::kHUMAN = _q("Human");
const QString NewGame::kAI = _q("AI");
NewGame::NewGame(QWidget *iParent)
: QDialog(iParent)
{
setupUi(this);
// Initialize the model of the default players
m_model = new QStandardItemModel(2, 2, this);
m_model->setHeaderData(0, Qt::Horizontal, _q("Name"), Qt::DisplayRole);
m_model->setHeaderData(1, Qt::Horizontal, _q("Type"), Qt::DisplayRole);
m_model->setData(m_model->index(0, 0), _q("HumanPlayer"));
m_model->setData(m_model->index(0, 1), kHUMAN);
m_model->setData(m_model->index(1, 0), _q("Eliot"));
m_model->setData(m_model->index(1, 1), kAI);
// Initialize the QTreeView with the model we just created
treeViewPlayers->setModel(m_model);
PlayersDelegate *delegate = new PlayersDelegate(this);
treeViewPlayers->setItemDelegateForColumn(1, delegate);
// Enable the Remove button only when there is a selection in the tree
QObject::connect(treeViewPlayers->selectionModel(),
SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
this,
SLOT(enableRemoveButton(const QItemSelection&, const QItemSelection&)));
// Enable the Ok button only when if there are enough players for the
// current mode
QObject::connect(m_model, SIGNAL(rowsInserted(const QModelIndex&, int, int)),
this, SLOT(enableOkButton()));
QObject::connect(m_model, SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
this, SLOT(enableOkButton()));
QObject::connect(comboBoxMode, SIGNAL(currentIndexChanged(int)),
this, SLOT(enableOkButton()));
// Install a custom event filter, to remove the selection when the
// "Delete" key is pressed
PlayersEventFilter *filter = new PlayersEventFilter(this);
treeViewPlayers->installEventFilter(filter);
QObject::connect(filter, SIGNAL(deletePressed()),
this, SLOT(on_pushButtonRemove_clicked()));
}
Game * NewGame::createGame(const Dictionary &iDic) const
{
// Create the game
Game *game = NULL;
if (comboBoxMode->currentText() == _q("Training"))
game = GameFactory::Instance()->createTraining(iDic);
else if (comboBoxMode->currentText() == _q("Free game"))
game = GameFactory::Instance()->createFreeGame(iDic);
else
game = GameFactory::Instance()->createDuplicate(iDic);
// Add the players
if (comboBoxMode->currentText() != _q("Training"))
{
for (int num = 0; num < m_model->rowCount(); ++num)
{
QString name = m_model->data(m_model->index(num, 0)).toString();
if (name == "")
name = _q("Player %1").arg(num + 1);
QString type = m_model->data(m_model->index(num, 1)).toString();
if (type == kHUMAN)
game->addHumanPlayer();
else
game->addAIPlayer();
// FIXME: ugly const_cast, because of the awkward Game API
// (we should have addPlayer(Player &) instead)
const Player *player = &game->getPlayer(game->getNPlayers() - 1);
const_cast<Player *>(player)->setName(qtw(name));
}
}
else
{
const_cast<Player *>(&game->getPlayer(0))->setName(qtw(_q("Training")));
}
// Joker game?
if (checkBoxJoker->isChecked())
game->setVariant(Game::kJOKER);
return game;
}
void NewGame::enableOkButton()
{
// Enable the "Ok" button:
// - always in training mode
// - if there is at least one player in duplicate mode
// - if there are at least 2 players in free game mode
bool disable =
(comboBoxMode->currentText() == _q("Duplicate") && m_model->rowCount() < 1) ||
(comboBoxMode->currentText() == _q("Free game") && m_model->rowCount() < 2);
buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!disable);
}
void NewGame::enableRemoveButton(const QItemSelection &iSelected,
const QItemSelection &)
{
// Enable the "Remove" button iff at least one line in the tree view
// is selected
pushButtonRemove->setEnabled(!iSelected.indexes().empty());
}
void NewGame::on_comboBoxMode_activated(int iIndex)
{
groupBoxPlayers->setEnabled(iIndex != 2);
}
void NewGame::on_pushButtonAdd_clicked()
{
// Add a new row
int rowNum = m_model->rowCount();
bool res = m_model->insertRow(rowNum);
if (!res)
return;
// Change the contents of the row
m_model->setData(m_model->index(rowNum, 0), lineEditName->displayText());
m_model->setData(m_model->index(rowNum, 1), comboBoxType->currentText());
}
void NewGame::on_pushButtonRemove_clicked()
{
QModelIndexList indexList = treeViewPlayers->selectionModel()->selectedIndexes();
if (indexList.empty())
return;
m_model->removeRow(indexList.front().row());
}
PlayersDelegate::PlayersDelegate(QObject *parent)
: QItemDelegate(parent)
{
}
QWidget *PlayersDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &,
const QModelIndex &) const
{
QComboBox *editor = new QComboBox(parent);
editor->addItem(NewGame::kHUMAN);
editor->addItem(NewGame::kAI);
return editor;
}
void PlayersDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
QComboBox *combo = static_cast<QComboBox*>(editor);
QString text = index.model()->data(index, Qt::DisplayRole).toString();
combo->setCurrentIndex(combo->findText(text));
}
void PlayersDelegate::setModelData(QWidget *editor,
QAbstractItemModel *model,
const QModelIndex &index) const
{
QComboBox *combo = static_cast<QComboBox*>(editor);
model->setData(index, combo->currentText());
}
void PlayersDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &) const
{
editor->setGeometry(option.rect);
}
PlayersEventFilter::PlayersEventFilter(QObject *parent)
: QObject(parent)
{
}
bool PlayersEventFilter::eventFilter(QObject *obj, QEvent *event)
{
// If the Delete key is pressed, remove the selected line, if any
if (event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Delete)
{
emit deletePressed();
return true;
}
}
// Standard event processing
return QObject::eventFilter(obj, event);
}

109
qt/new_game.h Normal file
View file

@ -0,0 +1,109 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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 NEW_GAME_H_
#define NEW_GAME_H_
#include <QDialog>
#include <QtGui/QItemDelegate>
#include <ui/new_game.ui.h>
class Dictionary;
class Game;
class QStandardItemModel;
class NewGame: public QDialog, private Ui::NewGameDialog
{
Q_OBJECT;
public:
explicit NewGame(QWidget *iParent = 0);
/// Possible values for the player type
static const QString kHUMAN;
static const QString kAI;
/**
* Create and return a game object from the information of the dialog.
* The Game object is always valid
*/
Game * createGame(const Dictionary& iDic) const;
private slots:
void enableOkButton();
void enableRemoveButton(const QItemSelection&, const QItemSelection&);
// The following slots are automatically connected
void on_comboBoxMode_activated(int);
void on_pushButtonAdd_clicked();
void on_pushButtonRemove_clicked();
private:
/// Model of the players
QStandardItemModel *m_model;
};
/// Delegate used for the edition of the players display
class PlayersDelegate: public QItemDelegate
{
Q_OBJECT;
public:
explicit PlayersDelegate(QObject *parent = 0);
virtual ~PlayersDelegate() {}
// Implement the needed methods
virtual QWidget *createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const;
virtual void setEditorData(QWidget *editor,
const QModelIndex &index) const;
virtual void setModelData(QWidget *editor,
QAbstractItemModel *model,
const QModelIndex &index) const;
virtual void updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &index) const;
};
/// Event filter used for the edition of the players display
class PlayersEventFilter: public QObject
{
Q_OBJECT;
public:
explicit PlayersEventFilter(QObject *parent = 0);
virtual ~PlayersEventFilter() {}
signals:
/// As its name indicates...
void deletePressed();
protected:
virtual bool eventFilter(QObject *obj, QEvent *event);
};
#endif

212
qt/player_widget.cpp Normal file
View file

@ -0,0 +1,212 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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/QLineEdit>
#include <QtGui/QHBoxLayout>
#include <QtGui/QValidator>
#include <QtCore/QStringList>
#include "player_widget.h"
#include "qtcommon.h"
#include "game.h"
#include "player.h"
#include "pldrack.h"
#include "coord.h"
#include "dic.h"
#include "debug.h"
#include "encoding.h"
/// Validator used for the "change letters" line edit
class ChangeValidator: public QValidator
{
public:
explicit ChangeValidator(QObject *parent,
const QLineEdit &iLineEdit);
virtual State validate(QString &input, int &pos) const;
private:
const QLineEdit &m_lineEdit;
};
/// Validator used for the "change letters" line edit
class PlayWordValidator: public QValidator
{
public:
explicit PlayWordValidator(QObject *parent,
const Dictionary &iDic);
virtual State validate(QString &input, int &pos) const;
private:
const Dictionary &m_dic;
};
PlayerWidget::PlayerWidget(QWidget *parent, unsigned int iPlayerNb,
const Game *iGame)
: QWidget(parent), m_game(iGame), m_player(iPlayerNb)
{
setupUi(this);
if (m_game)
{
lineEditPlay->setValidator(new PlayWordValidator(this, m_game->getDic()));
// Do not allow messing with AI players
if (!m_game->getPlayer(m_player).isHuman())
setEnabled(false);
// Changing the rack is authorized only in training mode
lineEditRack->setReadOnly(m_game->getMode() != Game::kTRAINING);
}
if (m_game == NULL || m_game->getMode() != Game::kFREEGAME)
{
// Hide the freegame-specific controls
labelChange->hide();
lineEditChange->hide();
pushButtonChange->hide();
pushButtonPass->hide();
}
else
{
lineEditChange->setValidator(new ChangeValidator(this, *lineEditRack));
}
refresh();
}
QSize PlayerWidget::sizeHint() const
{
return QSize(100, 100);
}
void PlayerWidget::refresh()
{
lineEditPlay->clear();
if (m_game == NULL)
{
// XXX
lineEditRack->clear();
return;
}
const PlayedRack &pld = m_game->getPlayer(m_player).getCurrentRack();
lineEditRack->setText(qfw(pld.toString(PlayedRack::RACK_EXTRA)));
lineEditPlay->clear();
lineEditChange->clear();
}
void PlayerWidget::on_pushButtonShuffle_clicked()
{
// TODO
}
void PlayerWidget::on_lineEditPlay_textChanged()
{
pushButtonPlay->setEnabled(lineEditPlay->hasAcceptableInput());
}
void PlayerWidget::on_lineEditChange_textChanged()
{
pushButtonChange->setEnabled(lineEditChange->hasAcceptableInput() &&
lineEditChange->text() != "");
pushButtonPass->setEnabled(lineEditChange->text() == "");
}
void PlayerWidget::on_lineEditPlay_returnPressed()
{
QStringList items = lineEditPlay->text().split(' ', QString::SkipEmptyParts);
ASSERT(items.size() == 2, "Bug found in the validator");
emit playingWord(m_player, items[0], items[1]);
}
void PlayerWidget::on_lineEditChange_returnPressed()
{
emit passing(m_player, lineEditChange->text());
}
ChangeValidator::ChangeValidator(QObject *parent,
const QLineEdit &iLineEdit)
: QValidator(parent), m_lineEdit(iLineEdit)
{
}
QValidator::State ChangeValidator::validate(QString &input, int &) const
{
QString rack = m_lineEdit.text();
if (input.size() > rack.size())
return Intermediate;
// The letters to change must be in the rack
for (int i = 0; i < input.size(); ++i)
{
if (input.count(input[i], Qt::CaseInsensitive) >
rack.count(input[i], Qt::CaseInsensitive))
{
return Intermediate;
}
}
return Acceptable;
}
PlayWordValidator::PlayWordValidator(QObject *parent,
const Dictionary &iDic)
: QValidator(parent), m_dic(iDic)
{
}
QValidator::State PlayWordValidator::validate(QString &input, int &) const
{
if (input == "")
return Intermediate;
QStringList items = input.split(' ', QString::SkipEmptyParts);
// The string is invalid if it contains characters not present
// in the dictionary
if (!m_dic.validateLetters(qtw(items[0])))
return Invalid;
if (items.size() != 2 || items[0].size() < 2)
return Intermediate;
// Check coordinates
Coord c(qtw(items[1]));
if (!c.isValid())
return Intermediate;
return Acceptable;
}

68
qt/player_widget.h Normal file
View file

@ -0,0 +1,68 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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 RACK_WIDGET_H_
#define RACK_WIDGET_H_
#include <QtGui/QWidget>
#include "ui/player_widget.ui.h"
class QLineEdit;
class Game;
class PlayerWidget: public QWidget, private Ui::PlayerWidget
{
Q_OBJECT;
public:
explicit PlayerWidget(QWidget *parent = 0,
unsigned int iPlayerNb = 0,
const Game *iGame = NULL);
QSize sizeHint() const;
signals:
void playingWord(unsigned int iPlayer, QString iWord, QString iCoord);
void passing(unsigned int iPlayer, QString iChangedLetters);
public slots:
void refresh();
private slots:
void on_pushButtonShuffle_clicked();
void on_pushButtonPlay_clicked() { on_lineEditPlay_returnPressed(); }
void on_pushButtonChange_clicked() { on_lineEditChange_returnPressed(); }
void on_pushButtonPass_clicked() { on_lineEditChange_returnPressed(); }
void on_lineEditPlay_textChanged();
void on_lineEditChange_textChanged();
void on_lineEditPlay_returnPressed();
void on_lineEditChange_returnPressed();
private:
/// Encapsulated game, can be NULL
const Game *m_game;
/// Encapsulated player, valid iff m_game is not NULL
unsigned int m_player;
};
#endif

46
qt/qtcommon.h Normal file
View file

@ -0,0 +1,46 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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 QT_COMMON_H_
#define QT_COMMON_H_
#if ENABLE_NLS
# include <libintl.h>
# define _(String) gettext(String)
// Apparently needed on Windows, where libintl.h defines sprintf
// as libintl_sprintf...
# undef sprintf
#else
# define _(String) String
#endif
// Convert to/from utf-8 char*
#define qfu(s) QString::fromUtf8(s)
#define qtu(s) (s).toUtf8().data()
// Convert to/from std::wstring
#define qfw(s) QString::fromStdWString(s)
#define qtw(s) (s).toStdWString().data()
// Convert to/from local encoding
#define qfl(s) QString::fromLocal8Bit(s)
#define qtl(s) (s).toLocal8Bit().data()
// Translation macro to use gettext
#define _q(s) qfu(_(s))
#endif

83
qt/score_widget.cpp Normal file
View file

@ -0,0 +1,83 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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/QTreeView>
#include <QtGui/QStandardItemModel>
#include "score_widget.h"
#include "qtcommon.h"
#include "game.h"
#include "player.h"
using namespace std;
ScoreWidget::ScoreWidget(QWidget *parent, const Game *iGame)
: QTreeView(parent), m_game(iGame)
{
// Create the tree view
setEditTriggers(QAbstractItemView::NoEditTriggers);
setRootIsDecorated(false);
setSortingEnabled(true);
QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Expanding);
setSizePolicy(policy);
// Associate the model to the view
m_model = new QStandardItemModel(this);
setModel(m_model);
updateModel();
}
void ScoreWidget::setGame(const Game *iGame)
{
m_game = iGame;
updateModel();
}
void ScoreWidget::updateModel()
{
m_model->clear();
m_model->setColumnCount(2);
m_model->setHeaderData(0, Qt::Horizontal, _q("Player"), Qt::DisplayRole);
m_model->setHeaderData(1, Qt::Horizontal, _q("Score"), Qt::DisplayRole);
resizeColumnToContents(0);
//resizeColumnToContents(1);
if (m_game == NULL)
return;
for (unsigned int i = 0; i < m_game->getNPlayers(); ++i)
{
const Player &p = m_game->getPlayer(i);
int rowNum = m_model->rowCount();
m_model->insertRow(rowNum);
m_model->setData(m_model->index(rowNum, 0), qfw(p.getName()));
m_model->setData(m_model->index(rowNum, 1), p.getPoints());
}
}
QSize ScoreWidget::sizeHint() const
{
return QSize(160, 100);
}

56
qt/score_widget.h Normal file
View file

@ -0,0 +1,56 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2008 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 SCORE_WIDGET_H_
#define SCORE_WIDGET_H_
#include <QtGui/QTreeView>
class Game;
class QStandardItemModel;
class ScoreWidget: public QTreeView
{
Q_OBJECT;
public:
explicit ScoreWidget(QWidget *parent = 0, const Game *iGame = NULL);
public slots:
void setGame(const Game *iGame = NULL);
protected:
/// Define a default size
virtual QSize sizeHint() const;
private:
/// Encapsulated game, can be NULL
const Game *m_game;
/// Model of the game
QStandardItemModel *m_model;
/// Force synchronizing the model with the contents of the game
void updateModel();
};
#endif

146
qt/ui/main_window.ui Normal file
View file

@ -0,0 +1,146 @@
<ui version="4.0" >
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>683</width>
<height>589</height>
</rect>
</property>
<property name="windowTitle" >
<string>Eliot</string>
</property>
<property name="windowIcon" >
<iconset>../../../bzr-cppdic/wxwin/eliot.xpm</iconset>
</property>
<widget class="QWidget" name="centralwidget" >
<layout class="QVBoxLayout" >
<item>
<widget class="QGroupBox" name="groupBoxTest" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Expanding" hsizetype="Preferred" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title" >
<string>GroupBox</string>
</property>
</widget>
</item>
<item>
<widget class="QTabWidget" name="tabWidgetPlayers" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<widget class="QWidget" name="tab" >
<attribute name="title" >
<string>_("No game")</string>
</attribute>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>683</width>
<height>28</height>
</rect>
</property>
<widget class="QMenu" name="menuFile" >
<property name="title" >
<string>_("&amp;Game")</string>
</property>
<addaction name="action_New_Game" />
<addaction name="separator" />
<addaction name="action_Quit" />
</widget>
<widget class="QMenu" name="menuHelp" >
<property name="title" >
<string>&amp;Settings</string>
</property>
<addaction name="action_ChooseDic" />
</widget>
<widget class="QMenu" name="menu_Help" >
<property name="title" >
<string>_("&amp;Help")</string>
</property>
<addaction name="action_About" />
<addaction name="separator" />
</widget>
<widget class="QMenu" name="menu_Windows" >
<property name="title" >
<string>_("&amp;Windows")</string>
</property>
<addaction name="action_Bag" />
</widget>
<addaction name="menuFile" />
<addaction name="menuHelp" />
<addaction name="menu_Windows" />
<addaction name="menu_Help" />
</widget>
<widget class="QStatusBar" name="statusbar" />
<action name="action_ChooseDic" >
<property name="text" >
<string>&amp;Choose dictionary...</string>
</property>
</action>
<action name="action_About" >
<property name="text" >
<string>_("&amp;About...")</string>
</property>
<property name="statusTip" >
<string>About Eliot</string>
</property>
</action>
<action name="action_Quit" >
<property name="text" >
<string>_("&amp;Quit")</string>
</property>
</action>
<action name="action_New_Game" >
<property name="text" >
<string>_("&amp;New game...")</string>
</property>
<property name="shortcut" >
<string>Ctrl+N</string>
</property>
</action>
<action name="action_Bag" >
<property name="checkable" >
<bool>true</bool>
</property>
<property name="text" >
<string>_("&amp;Bag")</string>
</property>
</action>
</widget>
<resources/>
<connections>
<connection>
<sender>action_Quit</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>close()</slot>
<hints>
<hint type="sourcelabel" >
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel" >
<x>260</x>
<y>215</y>
</hint>
</hints>
</connection>
</connections>
</ui>

213
qt/ui/new_game.ui Normal file
View file

@ -0,0 +1,213 @@
<ui version="4.0" >
<class>NewGameDialog</class>
<widget class="QDialog" name="NewGameDialog" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>374</width>
<height>327</height>
</rect>
</property>
<property name="windowTitle" >
<string>_("New game")</string>
</property>
<property name="modal" >
<bool>true</bool>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<string>_("Game type")</string>
</property>
<layout class="QHBoxLayout" >
<item>
<widget class="QLabel" name="label_3" >
<property name="text" >
<string>_("Mode:")</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxMode" >
<item>
<property name="text" >
<string>_("Duplicate")</string>
</property>
</item>
<item>
<property name="text" >
<string>_("Free game")</string>
</property>
</item>
<item>
<property name="text" >
<string>_("Training")</string>
</property>
</item>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>16</width>
<height>26</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="checkBoxJoker" >
<property name="text" >
<string>_("Joker game")</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxPlayers" >
<property name="title" >
<string>_("Players")</string>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QTreeView" name="treeViewPlayers" >
<property name="editTriggers" >
<set>QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::NoEditTriggers</set>
</property>
<property name="rootIsDecorated" >
<bool>false</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" >
<item>
<widget class="QLabel" name="label" >
<property name="text" >
<string>_("Name:")</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditName" >
<property name="text" >
<string>_("Player")</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>_("Type:")</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxType" >
<item>
<property name="text" >
<string>_("Human")</string>
</property>
</item>
<item>
<property name="text" >
<string>_("AI")</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" >
<item>
<widget class="QPushButton" name="pushButtonAdd" >
<property name="text" >
<string>_("Add player")</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButtonRemove" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" >
<string>_("Remove player")</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>NewGameDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<x>194</x>
<y>309</y>
</hint>
<hint type="destinationlabel" >
<x>173</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>NewGameDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<x>101</x>
<y>298</y>
</hint>
<hint type="destinationlabel" >
<x>75</x>
<y>275</y>
</hint>
</hints>
</connection>
</connections>
</ui>

116
qt/ui/player_widget.ui Normal file
View file

@ -0,0 +1,116 @@
<ui version="4.0" >
<class>PlayerWidget</class>
<widget class="QWidget" name="PlayerWidget" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>599</width>
<height>170</height>
</rect>
</property>
<layout class="QGridLayout" >
<item row="0" column="0" >
<widget class="QLabel" name="label" >
<property name="text" >
<string>_("Rack:")</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2" >
<widget class="QLineEdit" name="lineEditRack" >
<property name="readOnly" >
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="3" >
<widget class="QPushButton" name="pushButtonShuffle" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" >
<string>_("Shuffle")</string>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>_("Play a word:")</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2" >
<widget class="QLineEdit" name="lineEditPlay" >
<property name="toolTip" >
<string>_("To play a word, enter the word (case sensitive) and its coordinates. E.g.: WORD H4")</string>
</property>
<property name="text" >
<string>dummy</string>
</property>
</widget>
</item>
<item row="1" column="3" >
<widget class="QPushButton" name="pushButtonPlay" >
<property name="text" >
<string>_("Play")</string>
</property>
</widget>
</item>
<item row="2" column="0" >
<widget class="QLabel" name="labelChange" >
<property name="text" >
<string>_("Change letters:")</string>
</property>
</widget>
</item>
<item row="2" column="1" >
<widget class="QLineEdit" name="lineEditChange" >
<property name="toolTip" >
<string>_("Enter the letters you want to change")</string>
</property>
<property name="text" >
<string>dummy</string>
</property>
</widget>
</item>
<item row="2" column="2" >
<widget class="QPushButton" name="pushButtonChange" >
<property name="text" >
<string>_("Change")</string>
</property>
</widget>
</item>
<item row="2" column="3" >
<widget class="QPushButton" name="pushButtonPass" >
<property name="text" >
<string>_("Pass")</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3" >
<widget class="QLabel" name="label_3" >
<property name="text" >
<string>_("To play a word, enter the word (case sensitive) and its coordinates. E.g.: WORD H4")</string>
</property>
</widget>
</item>
<item row="4" column="1" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>