mirror of
git://git.savannah.nongnu.org/eliot.git
synced 2025-01-28 19:58:35 +01:00
Qt interface:
- Ensure unicity of players names (in the interface only, not the core) - Update the main window title with the game type - Display the player name in the history - The history widget is now able not to align the rack and the corresponding word - The dictionary path is remembered in the preferences - Ask for confirmation when loading a dictionary in the middle of a game - Preview tiles are coloured differently, and joker characters are in lowercase
This commit is contained in:
parent
d8780822c2
commit
457b368ae7
11 changed files with 242 additions and 39 deletions
|
@ -37,6 +37,7 @@ 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);
|
||||
const QColor BoardWidget::PreviewColour(183, 183, 123);
|
||||
|
||||
|
||||
BoardWidget::BoardWidget(QWidget *parent)
|
||||
|
@ -83,7 +84,12 @@ void BoardWidget::paintEvent(QPaintEvent *)
|
|||
{
|
||||
// Set the brush color
|
||||
if (m_game != NULL && !m_game->getBoard().getTile(row, col).isEmpty())
|
||||
painter.setBrush(TileColour);
|
||||
{
|
||||
if (m_game->getBoard().getCharAttr(row, col) & ATTR_TEST)
|
||||
painter.setBrush(PreviewColour);
|
||||
else
|
||||
painter.setBrush(TileColour);
|
||||
}
|
||||
else if (Board::GetWordMultiplier(row, col) == 3)
|
||||
painter.setBrush(W3Colour);
|
||||
else if (Board::GetWordMultiplier(row, col) == 2)
|
||||
|
@ -101,11 +107,14 @@ void BoardWidget::paintEvent(QPaintEvent *)
|
|||
// Draw the letter
|
||||
if (m_game != NULL && !m_game->getBoard().getTile(row, col).isEmpty())
|
||||
{
|
||||
wchar_t chr = m_game->getBoard().getTile(row, col).toChar();
|
||||
if (m_game->getBoard().getCharAttr(row, col) & ATTR_JOKER)
|
||||
chr = towlower(chr);
|
||||
painter.drawText((col - BOARD_MIN + 1) * squareSize,
|
||||
(row - BOARD_MIN + 1) * squareSize + 1,
|
||||
squareSize, squareSize,
|
||||
Qt::AlignCenter,
|
||||
qfw(wstring(1, m_game->getBoard().getTile(row, col).toChar())));
|
||||
qfw(wstring(1, chr)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ private:
|
|||
static const QColor W2Colour;
|
||||
static const QColor W3Colour;
|
||||
static const QColor TileColour;
|
||||
static const QColor PreviewColour;
|
||||
//@}
|
||||
};
|
||||
|
||||
|
|
|
@ -22,8 +22,10 @@
|
|||
#include <QtGui/QTreeView>
|
||||
#include <QtGui/QTabWidget>
|
||||
#include <QtGui/QStandardItemModel>
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
#include "history_widget.h"
|
||||
#include "prefs_dialog.h"
|
||||
#include "qtcommon.h"
|
||||
#include "game.h"
|
||||
#include "player.h"
|
||||
|
@ -55,9 +57,11 @@ HistoryWidget::HistoryWidget(QWidget *parent)
|
|||
|
||||
|
||||
void HistoryWidget::setHistory(const History *iHistory,
|
||||
const Game *iGame,
|
||||
bool iIsForPlayer)
|
||||
{
|
||||
m_history = iHistory;
|
||||
m_game = iGame;
|
||||
m_forPlayer = iIsForPlayer;
|
||||
updateModel();
|
||||
}
|
||||
|
@ -82,24 +86,41 @@ void HistoryWidget::updateModel()
|
|||
m_model->setHeaderData(5, Qt::Horizontal, _q("Player"), Qt::DisplayRole);
|
||||
}
|
||||
|
||||
if (m_history != NULL)
|
||||
if (m_history != NULL && m_history->getSize() != 0)
|
||||
{
|
||||
// Should we align the rack with its solution?
|
||||
QSettings qs;
|
||||
bool align = qs.value(PrefsDialog::kINTF_ALIGN_HISTORY).toBool();
|
||||
|
||||
if (!align)
|
||||
m_model->insertRow(0);
|
||||
|
||||
for (unsigned int i = 0; i < m_history->getSize(); ++i)
|
||||
{
|
||||
int rowNum = m_model->rowCount();
|
||||
m_model->insertRow(rowNum);
|
||||
int prevRowNum;
|
||||
if (align)
|
||||
prevRowNum = rowNum;
|
||||
else
|
||||
prevRowNum = rowNum - 1;
|
||||
|
||||
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),
|
||||
|
||||
// Set data common to all moves
|
||||
m_model->setData(m_model->index(prevRowNum, 0), i + 1);
|
||||
m_model->setData(m_model->index(prevRowNum, 1),
|
||||
qfw(t.getPlayedRack().toString()));
|
||||
m_model->setData(m_model->index(rowNum, 4), m.getScore());
|
||||
if (!m_forPlayer)
|
||||
m_model->setData(m_model->index(rowNum, 5), t.getPlayer() + 1);
|
||||
if (!m_forPlayer && m_game != NULL)
|
||||
{
|
||||
const wstring &name = m_game->getPlayer(t.getPlayer()).getName();
|
||||
m_model->setData(m_model->index(rowNum, 5), qfw(name));
|
||||
}
|
||||
|
||||
// Set the rest
|
||||
if (m.getType() == Move::VALID_ROUND)
|
||||
{
|
||||
|
@ -127,6 +148,7 @@ void HistoryWidget::updateModel()
|
|||
"[-" + qfw(m.getChangedLetters()) + "]");
|
||||
color = Qt::blue;
|
||||
}
|
||||
|
||||
// Set the color of the text
|
||||
for (int col = 0; col < 6; ++col)
|
||||
{
|
||||
|
@ -159,33 +181,40 @@ void HistoryTabWidget::setGame(const Game *iGame)
|
|||
{
|
||||
m_game = iGame;
|
||||
|
||||
// Keep only the Game tab, because it is nicer to have something, even
|
||||
// if it is empty
|
||||
int nbTabs = count();
|
||||
for (int i = nbTabs - 1; i > 0; --i)
|
||||
{
|
||||
setCurrentIndex(i);
|
||||
// Cut all the connections with the page (needed because removeTab()
|
||||
// doesn't really destroy the widget)
|
||||
disconnect(currentWidget());
|
||||
removeTab(i);
|
||||
}
|
||||
|
||||
if (m_game == NULL)
|
||||
{
|
||||
// Cut all the connections with the pages
|
||||
disconnect();
|
||||
|
||||
// Keep only the Game tab, because it is nicer to have something, even
|
||||
// if it is empty
|
||||
int nbTabs = count();
|
||||
for (int i = nbTabs - 1; i > 0; --i)
|
||||
removeTab(i);
|
||||
|
||||
// Tell the remaining tab that there is no more history to display
|
||||
m_gameHistoryWidget->setHistory(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Refresh the Game tab
|
||||
m_gameHistoryWidget->setHistory(&m_game->getHistory());
|
||||
m_gameHistoryWidget->setHistory(&m_game->getHistory(), m_game);
|
||||
QObject::connect(this, SIGNAL(refreshSignal()),
|
||||
m_gameHistoryWidget, SLOT(refresh()));
|
||||
|
||||
// In training mode, the players history is completely useless
|
||||
if (m_game->getMode() == Game::kTRAINING)
|
||||
return;
|
||||
|
||||
// Add one history tab per player
|
||||
for (unsigned int i = 0; i < m_game->getNPlayers(); ++i)
|
||||
{
|
||||
const Player &player = m_game->getPlayer(i);
|
||||
HistoryWidget *h = new HistoryWidget(NULL);
|
||||
h->setHistory(&player.getHistory(), true);
|
||||
h->setHistory(&player.getHistory(), m_game, true);
|
||||
QObject::connect(this, SIGNAL(refreshSignal()), h, SLOT(refresh()));
|
||||
addTab(h, qfw(player.getName()));
|
||||
}
|
||||
|
|
|
@ -37,7 +37,8 @@ class HistoryWidget: public QTreeView
|
|||
public:
|
||||
explicit HistoryWidget(QWidget *parent = 0);
|
||||
|
||||
void setHistory(const History *iHistory = NULL,
|
||||
void setHistory(const History *iHistory,
|
||||
const Game *iGame = NULL,
|
||||
bool iIsForPlayer = false);
|
||||
|
||||
public slots:
|
||||
|
@ -47,9 +48,12 @@ private:
|
|||
/// Encapsulated history, can be NULL
|
||||
const History *m_history;
|
||||
|
||||
/// Corresponding game (used to retrieve the players names) can be NULL
|
||||
const Game *m_game;
|
||||
|
||||
/**
|
||||
* Flag to avoid displaying the "players" column when the History object
|
||||
* is precisely associated to a Player
|
||||
* is associated to a Player
|
||||
*/
|
||||
bool m_forPlayer;
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <QtGui/QMessageBox>
|
||||
#include <QtGui/QFileDialog>
|
||||
#include <QtGui/QDockWidget>
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
#include "main_window.h"
|
||||
#include "dic.h"
|
||||
|
@ -55,6 +56,8 @@ MainWindow::MainWindow(QWidget *iParent)
|
|||
m_prefsDialog(NULL), m_bagWindow(NULL)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
QObject::connect(this, SIGNAL(gameChanged(const Game*)),
|
||||
this, SLOT(updateForGame(const Game*)));
|
||||
|
||||
// Board
|
||||
BoardWidget *boardWidget = new BoardWidget;
|
||||
|
@ -102,14 +105,28 @@ MainWindow::MainWindow(QWidget *iParent)
|
|||
scores, SLOT(refresh()));
|
||||
m_ui.groupBoxPlayers->layout()->addWidget(scores);
|
||||
|
||||
// XXX: temporary, for testing purposes!
|
||||
try
|
||||
emit gameChangedNonConst(NULL);
|
||||
emit gameChanged(NULL);
|
||||
|
||||
// Load dictionary
|
||||
QSettings qs;
|
||||
QString dicPath = qs.value(PrefsDialog::kINTF_DIC_PATH, "").toString();
|
||||
// FIXME: the messages are not displayed anymore when the window is shown
|
||||
if (dicPath == "")
|
||||
{
|
||||
m_dic = new Dictionary("/home/ipkiss/ods5.dawg");
|
||||
displayInfoMsg(_q("No dictionary selected"));
|
||||
}
|
||||
catch (...)
|
||||
else
|
||||
{
|
||||
// Ignore the error silently :)
|
||||
try
|
||||
{
|
||||
m_dic = new Dictionary(qtl(dicPath));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
displayInfoMsg(_q("No dictionary selected"));
|
||||
displayErrorMsg(_q("Cannot load dictionary '%1' indicated in the preferences").arg(dicPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,6 +156,32 @@ void MainWindow::destroyCurrentGame()
|
|||
}
|
||||
|
||||
|
||||
void MainWindow::updateForGame(const Game *iGame)
|
||||
{
|
||||
if (iGame == NULL)
|
||||
{
|
||||
m_ui.action_GameSaveAs->setEnabled(false);
|
||||
setWindowTitle(_q("No game") + " - Eliot");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui.action_GameSaveAs->setEnabled(true);
|
||||
if (iGame->getMode() == Game::kTRAINING)
|
||||
{
|
||||
setWindowTitle(_q("Training mode") + " - Eliot");
|
||||
}
|
||||
else if (iGame->getMode() == Game::kDUPLICATE)
|
||||
{
|
||||
setWindowTitle(_q("Duplicate game") + " - Eliot");
|
||||
}
|
||||
else
|
||||
{
|
||||
setWindowTitle(_q("Free game") + " - Eliot");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::displayErrorMsg(QString iMsg, QString iContext)
|
||||
{
|
||||
if (iContext == "")
|
||||
|
@ -148,6 +191,12 @@ void MainWindow::displayErrorMsg(QString iMsg, QString iContext)
|
|||
}
|
||||
|
||||
|
||||
void MainWindow::displayInfoMsg(QString iMsg)
|
||||
{
|
||||
statusBar()->showMessage(iMsg);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_action_GameNew_triggered()
|
||||
{
|
||||
if (m_dic == NULL)
|
||||
|
@ -177,6 +226,7 @@ void MainWindow::on_action_GameNew_triggered()
|
|||
emit gameChangedNonConst(m_game);
|
||||
emit gameChanged(m_game);
|
||||
emit gameUpdated();
|
||||
displayInfoMsg(_q("Game started"));
|
||||
}
|
||||
|
||||
|
||||
|
@ -202,6 +252,7 @@ void MainWindow::on_action_GameLoad_triggered()
|
|||
emit gameChangedNonConst(m_game);
|
||||
emit gameChanged(m_game);
|
||||
emit gameUpdated();
|
||||
displayInfoMsg(_q("Game loaded"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,6 +267,7 @@ void MainWindow::on_action_GameSaveAs_triggered()
|
|||
{
|
||||
ofstream fout(qtl(fileName));
|
||||
m_game->save(fout);
|
||||
displayInfoMsg(_q("Game saved"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,23 +275,45 @@ void MainWindow::on_action_GameSaveAs_triggered()
|
|||
void MainWindow::on_action_SettingsPreferences_triggered()
|
||||
{
|
||||
if (m_prefsDialog == NULL)
|
||||
{
|
||||
m_prefsDialog = new PrefsDialog(this);
|
||||
QObject::connect(m_prefsDialog, SIGNAL(gameUpdated()),
|
||||
this, SIGNAL(gameUpdated()));
|
||||
}
|
||||
m_prefsDialog->exec();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_action_SettingsChooseDic_triggered()
|
||||
{
|
||||
if (m_game)
|
||||
{
|
||||
int res = QMessageBox::question(this, _q("Stop current game?"),
|
||||
_q("Loading a dictionary will stop the current game. Do you want to continue?"),
|
||||
QMessageBox::Yes | QMessageBox::Default,
|
||||
QMessageBox::No | QMessageBox::Escape);
|
||||
if (res == QMessageBox::No)
|
||||
return;
|
||||
}
|
||||
|
||||
QString fileName =
|
||||
QFileDialog::getOpenFileName(this, _q("Choose a dictionary"), "", "*.dawg");
|
||||
if (!fileName.isEmpty())
|
||||
{
|
||||
destroyCurrentGame();
|
||||
|
||||
try
|
||||
{
|
||||
Dictionary *dic = new Dictionary(qtl(fileName));
|
||||
delete m_dic;
|
||||
m_dic = dic;
|
||||
emit dicChanged(fileName, qfw(m_dic->getHeader().getName()));
|
||||
displayInfoMsg(QString("Loaded dictionary '%1'").arg(fileName));
|
||||
|
||||
// Save the location of the dictionary in the preferences
|
||||
QSettings qs;
|
||||
QString dicPath = qs.value(PrefsDialog::kINTF_DIC_PATH, "").toString();
|
||||
qs.setValue(PrefsDialog::kINTF_DIC_PATH, fileName);
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
|
|
|
@ -52,6 +52,7 @@ signals:
|
|||
public slots:
|
||||
/// Display an error message to the user
|
||||
void displayErrorMsg(QString iMsg, QString iContext = "");
|
||||
void displayInfoMsg(QString iMsg);
|
||||
|
||||
private slots:
|
||||
void on_action_GameNew_triggered();
|
||||
|
@ -62,6 +63,12 @@ private slots:
|
|||
void on_action_WindowsBag_triggered();
|
||||
void on_action_HelpAbout_triggered();
|
||||
|
||||
/**
|
||||
* Perform several updates when the game changes (title bar, status bar,
|
||||
* grey out some menu items, ...)
|
||||
*/
|
||||
void updateForGame(const Game *iGame);
|
||||
|
||||
private:
|
||||
/// Current dictionary
|
||||
const Dictionary *m_dic;
|
||||
|
|
|
@ -92,11 +92,24 @@ Game * NewGame::createGame(const Dictionary &iDic) const
|
|||
// Add the players
|
||||
if (comboBoxMode->currentText() != _q("Training"))
|
||||
{
|
||||
set<QString> allNames;
|
||||
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);
|
||||
// Ensure unicity of the players names
|
||||
if (allNames.find(name) != allNames.end())
|
||||
{
|
||||
int n = 2;
|
||||
while (allNames.find(name + QString(" (%1)").arg(n)) != allNames.end())
|
||||
{
|
||||
++n;
|
||||
}
|
||||
name += QString(" (%1)").arg(n);
|
||||
}
|
||||
allNames.insert(name);
|
||||
|
||||
QString type = m_model->data(m_model->index(num, 1)).toString();
|
||||
if (type == kHUMAN)
|
||||
game->addHumanPlayer();
|
||||
|
|
|
@ -255,7 +255,7 @@ void PlayerTabWidget::setGame(Game *iGame)
|
|||
int nbTabs = count();
|
||||
for (int i = 0; i < nbTabs; ++i)
|
||||
{
|
||||
setCurrentWidget(0);
|
||||
setCurrentIndex(0);
|
||||
// Cut all the connections with the page (needed because removeTab()
|
||||
// doesn't really destroy the widget)
|
||||
disconnect(currentWidget());
|
||||
|
|
|
@ -19,13 +19,14 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtGui/QFileDialog>
|
||||
|
||||
#include "prefs_dialog.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
|
||||
const QString PrefsDialog::kINTF_ALIGN_HISTORY = "AlignHistory";
|
||||
const QString PrefsDialog::kINTF_ALIGN_HISTORY = "Interface/AlignHistory";
|
||||
const QString PrefsDialog::kINTF_DIC_PATH = "Interface/DicPath";
|
||||
|
||||
|
||||
PrefsDialog::PrefsDialog(QWidget *iParent)
|
||||
|
@ -35,12 +36,8 @@ PrefsDialog::PrefsDialog(QWidget *iParent)
|
|||
|
||||
// Interface settings
|
||||
QSettings qs;
|
||||
qs.beginGroup("Interface");
|
||||
checkBoxIntfAlignHistory->setChecked(qs.value(kINTF_ALIGN_HISTORY).toBool());
|
||||
qs.endGroup();
|
||||
// XXX: Hide the Interface settings until the "align history" is really
|
||||
// taken into account by the HistoryWidget class
|
||||
groupBoxInterface->hide();
|
||||
lineEditIntfDicPath->setText(qs.value(kINTF_DIC_PATH, "").toString());
|
||||
|
||||
// Duplicate settings
|
||||
checkBoxDuplRefuseInvalid->setChecked(Settings::Instance().getBool("duplicate-reject-invalid"));
|
||||
|
@ -68,11 +65,17 @@ void PrefsDialog::accept()
|
|||
|
||||
void PrefsDialog::updateSettings()
|
||||
{
|
||||
bool shouldEmitUpdate = false;
|
||||
|
||||
// Interface settings
|
||||
QSettings qs;
|
||||
qs.beginGroup("Interface");
|
||||
qs.setValue(kINTF_ALIGN_HISTORY, checkBoxIntfAlignHistory->isChecked());
|
||||
qs.endGroup();
|
||||
if (qs.value(kINTF_ALIGN_HISTORY).toBool() != checkBoxIntfAlignHistory->isChecked())
|
||||
{
|
||||
// We need to redraw the history widget
|
||||
shouldEmitUpdate = true;
|
||||
qs.setValue(kINTF_ALIGN_HISTORY, checkBoxIntfAlignHistory->isChecked());
|
||||
}
|
||||
qs.setValue(kINTF_DIC_PATH, lineEditIntfDicPath->text());
|
||||
|
||||
// Duplicate settings
|
||||
Settings::Instance().setBool("duplicate-reject-invalid",
|
||||
|
@ -87,6 +90,18 @@ void PrefsDialog::updateSettings()
|
|||
checkBoxFreeRefuseInvalid->isChecked());
|
||||
|
||||
// Training settings
|
||||
|
||||
|
||||
if (shouldEmitUpdate)
|
||||
emit gameUpdated();
|
||||
}
|
||||
|
||||
|
||||
void PrefsDialog::on_pushButtonIntfDicBrowse_clicked()
|
||||
{
|
||||
QString fileName =
|
||||
QFileDialog::getOpenFileName(this, _q("Choose a dictionary"), "", "*.dawg");
|
||||
if (fileName != "")
|
||||
lineEditIntfDicPath->setText(fileName);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,11 +35,18 @@ public:
|
|||
explicit PrefsDialog(QWidget *iParent = 0);
|
||||
|
||||
static const QString kINTF_ALIGN_HISTORY;
|
||||
static const QString kINTF_DIC_PATH;
|
||||
|
||||
public slots:
|
||||
/// Update the settings when the user selects "OK"
|
||||
virtual void accept();
|
||||
|
||||
signals:
|
||||
void gameUpdated();
|
||||
|
||||
private slots:
|
||||
void on_pushButtonIntfDicBrowse_clicked();
|
||||
|
||||
private:
|
||||
void updateSettings();
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>343</width>
|
||||
<height>383</height>
|
||||
<width>365</width>
|
||||
<height>418</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
|
@ -19,8 +19,52 @@
|
|||
<string>_("Interface")</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4" >
|
||||
<property name="text" >
|
||||
<string>_("Dictionary path:")</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="QLineEdit" name="lineEditIntfDicPath" >
|
||||
<property name="toolTip" >
|
||||
<string>_("Enter the dictionary path (mandatory to start a game)")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonIntfDicBrowse" >
|
||||
<property name="toolTip" >
|
||||
<string>_("Open a browser window to choose the dictionary")</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>_("Browse...")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxIntfAlignHistory" >
|
||||
<property name="toolTip" >
|
||||
<string>_("If checked, the game and player histories will diaplay the rack and the corresponding solution on the same line")</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>_("Align the rack and the solution in history")</string>
|
||||
</property>
|
||||
|
|
Loading…
Add table
Reference in a new issue