eliot-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Eliot-dev] eliot Makefile.am configure.in po/Makevars po/P...


From: eliot-dev
Subject: [Eliot-dev] eliot Makefile.am configure.in po/Makevars po/P...
Date: Sun, 20 Jan 2008 18:40:15 +0000

CVSROOT:        /cvsroot/eliot
Module name:    eliot
Changes by:     Olivier Teulière <ipkiss>      08/01/20 18:40:14

Modified files:
        .              : Makefile.am configure.in 
        po             : Makevars POTFILES.in 
Added files:
        qt             : .cvsignore Makefile.am aux_window.cpp 
                         aux_window.h bag_widget.cpp bag_widget.h 
                         board_widget.cpp board_widget.h 
                         history_widget.cpp history_widget.h main.cpp 
                         main_window.cpp main_window.h new_game.cpp 
                         new_game.h player_widget.cpp player_widget.h 
                         qtcommon.h score_widget.cpp score_widget.h 
        qt/ui          : main_window.ui new_game.ui player_widget.ui 

Log message:
        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...

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/eliot/Makefile.am?cvsroot=eliot&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/eliot/configure.in?cvsroot=eliot&r1=1.23&r2=1.24
http://cvs.savannah.gnu.org/viewcvs/eliot/po/Makevars?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/po/POTFILES.in?cvsroot=eliot&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/.cvsignore?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/Makefile.am?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/aux_window.cpp?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/aux_window.h?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/bag_widget.cpp?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/bag_widget.h?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/board_widget.cpp?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/board_widget.h?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/history_widget.cpp?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/history_widget.h?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/main.cpp?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/main_window.cpp?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/main_window.h?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/new_game.cpp?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/new_game.h?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/player_widget.cpp?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/player_widget.h?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/qtcommon.h?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/score_widget.cpp?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/score_widget.h?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/ui/main_window.ui?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/ui/new_game.ui?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/ui/player_widget.ui?cvsroot=eliot&rev=1.1

Patches:
Index: Makefile.am
===================================================================
RCS file: /cvsroot/eliot/eliot/Makefile.am,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- Makefile.am 13 Jan 2008 18:19:10 -0000      1.6
+++ Makefile.am 20 Jan 2008 18:40:12 -0000      1.7
@@ -1,4 +1,4 @@
-SUBDIRS = intl dic game utils wxwin po
+SUBDIRS = intl dic game utils wxwin qt po
 
 ACLOCAL_AMFLAGS = -I m4
 

Index: configure.in
===================================================================
RCS file: /cvsroot/eliot/eliot/configure.in,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -b -r1.23 -r1.24
--- configure.in        13 Jan 2008 19:01:43 -0000      1.23
+++ configure.in        20 Jan 2008 18:40:12 -0000      1.24
@@ -21,6 +21,7 @@
 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 @@
 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 @@
 AC_CONFIG_FILES(intl/Makefile po/Makefile.in
 dic/Makefile
 game/Makefile
-wxwin/Makefile
 utils/Makefile
+wxwin/Makefile
+qt/Makefile
 Makefile)
 AC_OUTPUT

Index: po/Makevars
===================================================================
RCS file: /cvsroot/eliot/eliot/po/Makevars,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- po/Makevars 6 Feb 2005 22:18:11 -0000       1.1
+++ po/Makevars 20 Jan 2008 18:40:12 -0000      1.2
@@ -8,7 +8,7 @@
 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

Index: po/POTFILES.in
===================================================================
RCS file: /cvsroot/eliot/eliot/po/POTFILES.in,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- po/POTFILES.in      8 Jan 2008 13:52:40 -0000       1.4
+++ po/POTFILES.in      20 Jan 2008 18:40:12 -0000      1.5
@@ -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

Index: qt/.cvsignore
===================================================================
RCS file: qt/.cvsignore
diff -N qt/.cvsignore
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/.cvsignore       20 Jan 2008 18:40:12 -0000      1.1
@@ -0,0 +1,7 @@
+.deps
+Makefile
+Makefile.in
+qeliot
+qeliot.exe
+cscope.files
+cscope.out

Index: qt/Makefile.am
===================================================================
RCS file: qt/Makefile.am
diff -N qt/Makefile.am
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/Makefile.am      20 Jan 2008 18:40:12 -0000      1.1
@@ -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 $@ address@hidden
+       echo "// Note: Lines below generated by Eliot build system" > 
address@hidden
+       echo "#include \"qtcommon.h\"" >> address@hidden
+       echo "#define Q_(a,b) QString::fromUtf8(_(a))" >> address@hidden
+       $(UIC) -tr "Q_" $< >> address@hidden
+       sed 's/Q_(\"_(\\\"\(.*\)\\\")"/Q_("\1"/' address@hidden >$@
+       rm -f address@hidden
+
+
+endif
+

Index: qt/aux_window.cpp
===================================================================
RCS file: qt/aux_window.cpp
diff -N qt/aux_window.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/aux_window.cpp   20 Jan 2008 18:40:12 -0000      1.1
@@ -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);
+}
+

Index: qt/aux_window.h
===================================================================
RCS file: qt/aux_window.h
diff -N qt/aux_window.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/aux_window.h     20 Jan 2008 18:40:12 -0000      1.1
@@ -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

Index: qt/bag_widget.cpp
===================================================================
RCS file: qt/bag_widget.cpp
diff -N qt/bag_widget.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/bag_widget.cpp   20 Jan 2008 18:40:12 -0000      1.1
@@ -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);
+}
+

Index: qt/bag_widget.h
===================================================================
RCS file: qt/bag_widget.h
diff -N qt/bag_widget.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/bag_widget.h     20 Jan 2008 18:40:12 -0000      1.1
@@ -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
+

Index: qt/board_widget.cpp
===================================================================
RCS file: qt/board_widget.cpp
diff -N qt/board_widget.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/board_widget.cpp 20 Jan 2008 18:40:12 -0000      1.1
@@ -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));
+    }
+}
+

Index: qt/board_widget.h
===================================================================
RCS file: qt/board_widget.h
diff -N qt/board_widget.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/board_widget.h   20 Jan 2008 18:40:13 -0000      1.1
@@ -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
+

Index: qt/history_widget.cpp
===================================================================
RCS file: qt/history_widget.cpp
diff -N qt/history_widget.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/history_widget.cpp       20 Jan 2008 18:40:13 -0000      1.1
@@ -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);
+}
+

Index: qt/history_widget.h
===================================================================
RCS file: qt/history_widget.h
diff -N qt/history_widget.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/history_widget.h 20 Jan 2008 18:40:13 -0000      1.1
@@ -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
+

Index: qt/main.cpp
===================================================================
RCS file: qt/main.cpp
diff -N qt/main.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/main.cpp 20 Jan 2008 18:40:13 -0000      1.1
@@ -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();
+}

Index: qt/main_window.cpp
===================================================================
RCS file: qt/main_window.cpp
diff -N qt/main_window.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/main_window.cpp  20 Jan 2008 18:40:13 -0000      1.1
@@ -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);
+}
+

Index: qt/main_window.h
===================================================================
RCS file: qt/main_window.h
diff -N qt/main_window.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/main_window.h    20 Jan 2008 18:40:13 -0000      1.1
@@ -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
+

Index: qt/new_game.cpp
===================================================================
RCS file: qt/new_game.cpp
diff -N qt/new_game.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/new_game.cpp     20 Jan 2008 18:40:13 -0000      1.1
@@ -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);
+}
+

Index: qt/new_game.h
===================================================================
RCS file: qt/new_game.h
diff -N qt/new_game.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/new_game.h       20 Jan 2008 18:40:13 -0000      1.1
@@ -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
+

Index: qt/player_widget.cpp
===================================================================
RCS file: qt/player_widget.cpp
diff -N qt/player_widget.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/player_widget.cpp        20 Jan 2008 18:40:13 -0000      1.1
@@ -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;
+}
+

Index: qt/player_widget.h
===================================================================
RCS file: qt/player_widget.h
diff -N qt/player_widget.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/player_widget.h  20 Jan 2008 18:40:13 -0000      1.1
@@ -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
+

Index: qt/qtcommon.h
===================================================================
RCS file: qt/qtcommon.h
diff -N qt/qtcommon.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/qtcommon.h       20 Jan 2008 18:40:13 -0000      1.1
@@ -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

Index: qt/score_widget.cpp
===================================================================
RCS file: qt/score_widget.cpp
diff -N qt/score_widget.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/score_widget.cpp 20 Jan 2008 18:40:14 -0000      1.1
@@ -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);
+}
+

Index: qt/score_widget.h
===================================================================
RCS file: qt/score_widget.h
diff -N qt/score_widget.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/score_widget.h   20 Jan 2008 18:40:14 -0000      1.1
@@ -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
+

Index: qt/ui/main_window.ui
===================================================================
RCS file: qt/ui/main_window.ui
diff -N qt/ui/main_window.ui
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/ui/main_window.ui        20 Jan 2008 18:40:14 -0000      1.1
@@ -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>

Index: qt/ui/new_game.ui
===================================================================
RCS file: qt/ui/new_game.ui
diff -N qt/ui/new_game.ui
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/ui/new_game.ui   20 Jan 2008 18:40:14 -0000      1.1
@@ -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>

Index: qt/ui/player_widget.ui
===================================================================
RCS file: qt/ui/player_widget.ui
diff -N qt/ui/player_widget.ui
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ qt/ui/player_widget.ui      20 Jan 2008 18:40:14 -0000      1.1
@@ -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>




reply via email to

[Prev in Thread] Current Thread [Next in Thread]