Commit b2db3145 authored by Johannes Bergmeier's avatar Johannes Bergmeier

Some refactoring:

* Made KsView an extra class which communicates with the actual views through signal/slot
I don't know whether this change is a step forward or backward, so i hope I will come up with a better idea soon.

svn path=/trunk/KDE/kdegames/ksudoku/; revision=674242
parent 27cd1b9c
......@@ -107,8 +107,10 @@ void KSudoku::updateStatusBar()
// QWidget* current = m_tabs->currentPage();
// if(KsView* view = dynamic_cast<KsView*>(current))
// m = view->status();
if(currentView())
m = currentView()->status();
// if(currentView())
// m = currentView()->status();
// TODO fix this: add new status bar generation code
statusBar()->showMessage(m);
}
......@@ -118,6 +120,10 @@ KSudoku::KSudoku()
{
setObjectName("ksudoku");
m_gameWidget = 0;
m_gameUI = 0;
activeWidget = 0;
m_selectValueMapper = new QSignalMapper(this);
connect(m_selectValueMapper, SIGNAL(mapped(int)), this, SLOT(selectValue(int)));
m_enterValueMapper = new QSignalMapper(this);
......@@ -132,16 +138,11 @@ KSudoku::KSudoku()
// and a status bar
statusBar()->show();
setupGUI();
wrapper = new QWidget();
(void) new QHBoxLayout(wrapper);
activeWidget = 0;
QMainWindow::setCentralWidget(wrapper);
wrapper->show();
m_gameWidget = 0;
// Create ValueListWidget
m_valueListWidget = new ValueListWidget(wrapper);
......@@ -207,29 +208,42 @@ void KSudoku::startGame(const Game& game) {
GameType type = game.puzzle()->gameType(); //game solver()->g->sizeZ() > 1) ? 1 : 0;
KsView* view = 0;
view = new KsView(game, this);
connect(view, SIGNAL(valueSelected(int)), m_valueListWidget, SLOT(selectValue(int)));
connect(m_valueListWidget, SIGNAL(valueSelected(int)), view, SLOT(selectValue(int)));
switch(type){
case sudoku: { //cUrly braces needed to avoid "crosses initialization" compile error
ksudokuView* v = new ksudokuView(wrapper, game, false);
// v->setup(game);
connect(v, SIGNAL(valueSelected(int)), SLOT(updateStatusBar()));
view = v;
connect(v, SIGNAL(valueSelected(int)), m_valueListWidget, SLOT(selectValue(int)));
connect(m_valueListWidget, SIGNAL(valueSelected(int)), v, SLOT(selectValue(int)));
connect(v, SIGNAL(valueSelected(int)), view, SLOT(selectValue(int)));
connect(view, SIGNAL(valueSelected(int)), v, SLOT(selectValue(int)));
view->setWidget(v);
connect(view, SIGNAL(flagsChanged(ViewFlags)), v, SLOT(setFlags(ViewFlags)));
connect(view, SIGNAL(symbolsChanged(SymbolTable*)), v, SLOT(setSymbols(SymbolTable*)));
connect(v, SIGNAL(mouseOverCell(int)), view, SLOT(setCursor(int)));
connect(view, SIGNAL(cursorMoved(int)), v, SLOT(setCursor(int)));
connect(view, SIGNAL(valueSelected(int)), v, SLOT(selectValue(int)));
break; }
case roxdoku: {
RoxdokuView* v = new RoxdokuView(game, &m_symbols, wrapper, "ksudoku-3dwnd");
connect(m_valueListWidget, SIGNAL(valueSelected(int)), v, SLOT(selectValue(int)));
view = v;
connect(view, SIGNAL(valueSelected(int)), v, SLOT(selectValue(int)));
connect(view, SIGNAL(flagsChanged(ViewFlags)), v, SLOT(setFlags(ViewFlags)));
view->setWidget(v);
break; }
case custom:{
// SKPuzzle* puzzle = game.puzzle()->puzzle();
//GraphCustom* gc = game.puzzle()->solver()->g;
ksudokuView* v = new ksudokuView(wrapper, game, true);
// v->setup(game);
connect(v, SIGNAL(valueSelected(int)), SLOT(updateStatusBar()));
view = v;
connect(v, SIGNAL(valueSelected(int)), m_valueListWidget, SLOT(selectValue(int)));
connect(m_valueListWidget, SIGNAL(valueSelected(int)), v, SLOT(selectValue(int)));
connect(v, SIGNAL(valueSelected(int)), view, SLOT(selectValue(int)));
connect(view, SIGNAL(valueSelected(int)), v, SLOT(selectValue(int)));
view->setWidget(v);
connect(view, SIGNAL(flagsChanged(ViewFlags)), v, SLOT(setFlags(ViewFlags)));
connect(view, SIGNAL(symbolsChanged(SymbolTable*)), v, SLOT(setSymbols(SymbolTable*)));
connect(v, SIGNAL(mouseOverCell(int)), view, SLOT(setCursor(int)));
connect(view, SIGNAL(cursorMoved(int)), v, SLOT(setCursor(int)));
connect(view, SIGNAL(valueSelected(int)), v, SLOT(selectValue(int)));
}
default:
///@todo if here, BUG => throw exception (??)
......@@ -240,6 +254,7 @@ void KSudoku::startGame(const Game& game) {
m_welcomeScreen->hide();
QWidget* widget = view->widget();
m_gameUI = view;
Game game2(game);
connect(game2.interface(), SIGNAL(completed(bool,const QTime&,bool)), SLOT(onCompleted(bool,const QTime&,bool)));
......@@ -293,6 +308,8 @@ void KSudoku::setCentralWidget(QWidget* widget, bool autoDel) {
void KSudoku::showWelcomeScreen() {
m_valueListWidget->hide();
delete m_gameUI;
m_gameUI = 0;
setCentralWidget(m_welcomeScreen, false);
}
......@@ -310,12 +327,8 @@ void KSudoku::mouseOnlySuperscript()
void KSudoku::setGuidedMode()
{
if(ksudokuView* view = dynamic_cast<ksudokuView*>(currentView())) {
view->toggleGuided();
view->update();
} else if(RoxdokuView* view = dynamic_cast<RoxdokuView*>(currentView())) {
view->toggleGuided();
view->update();
if(KsView* view = currentView()) {
view->setFlags(view->flags() ^ ShowErrors);
}
saveProperties( KGlobal::config().data());
......@@ -589,34 +602,11 @@ void KSudoku::setupActions()
void KSudoku::adaptActions2View() {
// TODO This whole function is only a temporary hack, views should have their own UI
if(ksudokuView* view = dynamic_cast<ksudokuView*>(currentView())) {
KToggleAction* a;
if((a = dynamic_cast<KToggleAction*>(action("mouseOnlySuperscript")))) {
a->setEnabled(true);
a->setChecked(view->mouseOnlySuperscript);
}
if((a = dynamic_cast<KToggleAction*>(action("guidedMode")))) {
a->setEnabled(true);
a->setChecked(view->guidedMode());
}
if((a = dynamic_cast<KToggleAction*>(action("showTracker")))) {
a->setEnabled(true);
a->setChecked(view->showTracker);
}
} else if(RoxdokuView* view = dynamic_cast<RoxdokuView*>(currentView())) {
if(KsView* view = currentView()) {
KToggleAction* a;
if((a = dynamic_cast<KToggleAction*>(action("mouseOnlySuperscript")))) {
a->setEnabled(false);
a->setChecked(false);
}
if((a = dynamic_cast<KToggleAction*>(action("guidedMode")))) {
a->setEnabled(true);
a->setChecked(view->guidedMode());
}
if((a = dynamic_cast<KToggleAction*>(action("showTracker")))) {
a->setEnabled(false);
a->setChecked(false);
a->setChecked(view->flags().testFlag(ShowErrors));
}
} else {
KToggleAction* a;
......@@ -719,12 +709,9 @@ void KSudoku::saveProperties(KConfig *config)
// later when this app is restored
KConfigGroup group = config->group("ksudoku General");
if(ksudokuView* view = dynamic_cast<ksudokuView*>(currentView())) {
group.writeEntry("guidedMode", QVariant(view->guidedMode()));
group.writeEntry("mouseOnlySuperscript", QVariant(view->mouseOnlySuperscript));
group.writeEntry("showTracker", QVariant(view->showTracker ));
} else if(RoxdokuView* view = dynamic_cast<RoxdokuView*>(currentView())) {
group.writeEntry("guidedMode", QVariant(view->guidedMode()));
if(KsView* view = currentView()) {
group.writeEntry("guidedMode", QVariant(view->flags().testFlag(ShowErrors)));
group.writeEntry("showTracker", QVariant(view->flags().testFlag(ShowTracker)));
}
config->sync();
......@@ -740,12 +727,11 @@ void KSudoku::readProperties(KConfig *config)
QString Url = group.readEntry("lastUrl", "");
if(ksudokuView* view = dynamic_cast<ksudokuView*>(currentView())) {
view->setGuidedMode(group.readEntry("guidedMode", true));
view->showTracker = group.readEntry("showTracker", true);
view->mouseOnlySuperscript = group.readEntry("mouseOnlySuperscript", true);
} else if(RoxdokuView* view = dynamic_cast<RoxdokuView*>(currentView())) {
view->setGuidedMode(group.readEntry("guidedMode", true));
if(KsView* view = currentView()) {
ViewFlags flags = view->flags();
if(flags.testFlag(ShowErrors) xor group.readEntry("guidedMode", true))
flags ^= ShowErrors;
view->setFlags(flags);
}
}
......@@ -929,9 +915,11 @@ ksudoku::KsView* KSudoku::currentView() const{
// TODO this might cause trouble as the central widget don't have to be a
// KsView instance
// if(activeWidget)
if(centralWidget() == 0) return 0;
// if(centralWidget() == 0) return 0;
return dynamic_cast<KsView*>(activeWidget);
// return dynamic_cast<KsView*>(activeWidget);
return m_gameUI;
}
void KSudoku::loadCustomShapeFromPath()
......
......@@ -216,6 +216,8 @@ private:
QWidget* m_gameWidget;
ValueListWidget* m_valueListWidget;
KsView* m_gameUI;
bool m_autoDelCentralWidget;
......
......@@ -40,8 +40,8 @@ namespace ksudoku {
ksudokuView::ksudokuView(QWidget *parent, const Game& game, bool customd)
: QWidget(parent)
, KsView()
{
m_symbolTable = 0;
isWaitingForNumber = -1;
highlighted = -1;
......@@ -74,26 +74,32 @@ QString ksudokuView::status() const
{
QString m;
SymbolTable* table = symbolTable();
if(!table) return m;
if(!m_symbolTable) return m;
int secs = QTime(0,0).secsTo(m_game.time());
if(secs % 36 < 12)
m = i18n("Selected item %1, Time elapsed %2. Press SHIFT to highlight.",
table->symbolForValue(current_selected_number),
m_symbolTable->symbolForValue(current_selected_number),
m_game.time().toString("hh:mm:ss"));
else if(secs % 36 < 24)
m = i18n("Selected item %1, Time elapsed %2. Use RMB to pencil-mark(superscript).",
table->symbolForValue(current_selected_number),
m_symbolTable->symbolForValue(current_selected_number),
m_game.time().toString("hh:mm:ss"));
else
m = i18n("Selected item %1, Time elapsed %2. Type in a cell to replace that number in it.",
table->symbolForValue(current_selected_number),
m_symbolTable->symbolForValue(current_selected_number),
m_game.time().toString("hh::mm::ss"));
return m;
}
QChar ksudokuView::symbol(int value) const {
if(m_symbolTable == 0)
return '\0';
return m_symbolTable->symbolForValue(value);
}
void ksudokuView::draw(QPainter& p, int height, int width) const
{
if(m_buttons.size() == 0)
......@@ -127,17 +133,17 @@ void ksudokuView::draw(QPainter& p, int height, int width) const
}
void ksudokuView::btn_enter(int x, int y)
{
//for wrapping:
int max_x = ((GraphCustom*) m_game.puzzle()->solver()->g)->sizeX() - 1;
int max_y = ((GraphCustom*) m_game.puzzle()->solver()->g)->sizeY() - 1;
if(x > max_x+1) x = max_x; //uint => negative == max uint
if(y > max_y+1) y = max_y;
if(x > max_x) x = 0;
if(y > max_y) y = 0;
void ksudokuView::btn_enter(int x, int y) {
emit mouseOverCell(m_game.index(x,y));
}
m_buttons[m_game.index(x,y)]->setFocus();
void ksudokuView::setCursor(int cell) {
m_buttons[cell]->setFocus();
m_currentCell = cell;
Graph* g = m_game.puzzle()->solver()->g;
int x = g->cellPosX(cell);
int y = g->cellPosY(cell);
isWaitingForNumber = -1;
......@@ -145,51 +151,28 @@ void ksudokuView::btn_enter(int x, int y)
m_highlightUpdate.resize(m_game.size());
for(int i = 0; i < m_game.size(); ++i) {
// m_buttons[i]->setHighlight(HighlightBaseMask, HighlightNone);
m_highlightUpdate[i] = HighlightNone;
}
m_currentCell = m_game.index(x,y);
if(custom==0)
{
for(int i = 0; i < m_game.order(); ++i)
{
// uint base = m_game.userPuzzle()->base;
if(custom==0) {
for(int i = 0; i < m_game.order(); ++i) {
int base = static_cast<int>(sqrt(m_game.puzzle()->order()));
// m_buttons[m_game.index(i, y)]->setHighlight(HighlightRow);
// m_buttons[m_game.index(x, i)]->setHighlight(HighlightColumn);
m_highlightUpdate[m_game.index(i, y)] |= HighlightRow;
m_highlightUpdate[m_game.index(x, i)] |= HighlightColumn;
int sx = (x/base) * base;
int sy = (y/base) * base;
// m_buttons[m_game.index(i/base+sx, sy+(i%base))]->setHighlight(HighlightClique);
m_highlightUpdate[m_game.index(i/base+sx,i%base+sy)] |= HighlightClique;
}
}
else
{
/*int colorA = m_color0;
m_color0 = (m_color0+1)%2;
int colorB = m_color0;
GraphCustom* g = ((GraphCustom*) m_game.puzzle()->solver()->g);
int index = m_game.index(y,x);
m_buttons[index]->setHighlighted(colorA+1,true);
for(int i=0; i<g->optimized_d[index]; i++)
{
m_buttons[g->optimized[index][i]]->setHighlighted(colorB+1,true);
}*/
GraphCustom* g = ((GraphCustom*) m_game.puzzle()->solver()->g);
int index = g->cellIndex(x,y);
//printf("(%d %d) %d\n", y, x, index);
} else {
GraphCustom* gc = dynamic_cast<GraphCustom*>(g);
int count = 0;
for(uint i=0; i<g->cliques.size(); i++)
for(uint i=0; i<gc->cliques.size(); i++)
{
for(uint j=0; j<g->cliques[i].size(); j++)
for(uint j=0; j<gc->cliques[i].size(); j++)
{
if(g->cliques[i][j]==index)
if(gc->cliques[i][j]==cell)
{
uint mask = HighlightNone;
switch(count) {
......@@ -203,10 +186,9 @@ void ksudokuView::btn_enter(int x, int y)
mask = HighlightClique;
break;
}
for(uint k=0; k<g->cliques[i].size(); k++)
for(uint k=0; k<gc->cliques[i].size(); k++)
{
// m_buttons[g->cliques[i][k]]->setHighlight(mask);
m_highlightUpdate[g->cliques[i][k]] |= mask;
m_highlightUpdate[gc->cliques[i][k]] |= mask;
}
count = (count+1)%3;
break;
......@@ -291,60 +273,25 @@ void ksudokuView::setGame(const ksudoku::Game& game) {
m_buttons[i]->show();
}
connect(m_game.interface(), SIGNAL(cellChange(int)), this, SLOT(onCellChange(int)));
connect(m_game.interface(), SIGNAL(fullChange()), this, SLOT(onFullChange()));
connect(m_game.interface(), SIGNAL(cellChange(int)), this, SLOT(update(int)));
connect(m_game.interface(), SIGNAL(fullChange()), this, SLOT(update()));
}
void ksudokuView::selectValue(int value) {
current_selected_number = value;
}
void ksudokuView::enterValue(int value) {
if(!m_game.given(m_currentCell)) {
m_game.setValue(m_currentCell, value);
}
if(getHighlighted() != -1)
beginHighlight(value);
}
void ksudokuView::markValue(int value) {
if(!m_game.given(m_currentCell)) {
m_game.flipMarker(m_currentCell, value);
}
void ksudokuView::setSymbols(SymbolTable* table) {
m_symbolTable = table;
update();
}
void ksudokuView::moveUp() {
Graph* g = m_game.puzzle()->solver()->g;
int x = g->cellPosX(m_currentCell);
int y = g->cellPosY(m_currentCell);
if(--y < 0) y = g->sizeY()-1;
btn_enter(x,y);
}
void ksudokuView::moveDown() {
Graph* g = m_game.puzzle()->solver()->g;
int x = g->cellPosX(m_currentCell);
int y = g->cellPosY(m_currentCell);
if(++y >= g->sizeY()) y = 0;
btn_enter(x,y);
}
void ksudokuView::moveLeft() {
Graph* g = m_game.puzzle()->solver()->g;
int x = g->cellPosX(m_currentCell);
int y = g->cellPosY(m_currentCell);
if(--x < 0) x = g->sizeX()-1;
btn_enter(x,y);
}
void ksudokuView::moveRight() {
Graph* g = m_game.puzzle()->solver()->g;
int x = g->cellPosX(m_currentCell);
int y = g->cellPosY(m_currentCell);
if(++x >= g->sizeX()) x = 0;
btn_enter(x,y);
}
void ksudokuView::updateSymbols() {
onFullChange();
void ksudokuView::setFlags(ViewFlags flags) {
m_guidedMode = flags.testFlag(ShowErrors);
update();
}
void ksudokuView::beginHighlight(int val)
......@@ -383,10 +330,9 @@ void ksudokuView::resizeEvent(QResizeEvent * /*event*/ )
}
void ksudokuView::wheelEvent (QWheelEvent* e) {
int order = game().order();
int order = m_game.order();
int value = (current_selected_number - e->delta()/120) % order;
if(value <= 0) value = order - value;
current_selected_number = value;
emit valueSelected(value);
}
......@@ -394,8 +340,7 @@ void ksudokuView::slotHello(int x, int y)
{
if(m_game.given(x,y))
{
current_selected_number = m_game.value(x,y);
emit valueSelected(current_selected_number);
emit valueSelected(m_game.value(x,y));
}
else
{
......@@ -419,14 +364,16 @@ void ksudokuView::slotRight(int x, int y)
}
}
void ksudokuView::onCellChange(int index) {
if(m_buttons[index])
m_buttons[index]->updateData();
}
void ksudokuView::update(int cell) {
if(cell < 0) {
for(int i = 0; i < m_buttons.count(); i++)
m_buttons[i]->updateData();
return;
}
if(m_buttons[cell])
m_buttons[cell]->updateData();
void ksudokuView::onFullChange() {
for(int i = 0; i < m_buttons.count(); i++)
m_buttons[i]->updateData();
if(getHighlighted() != -1) beginHighlight(getHighlighted());
}
}
......
......@@ -49,7 +49,7 @@ class Symbols;
* Gui for a sudoku puzzle
* @TODO rename ksudokuView to sudokuView
*/
class ksudokuView : public QWidget, public KsView
class ksudokuView : public QWidget
{
Q_OBJECT
friend class QSudokuButton;
......@@ -73,11 +73,10 @@ public:
virtual void draw(QPainter& p, int height, int width) const;
signals:
void mouseOverCell(int cell);
void valueSelected(int value);
public:
// void setup (const Game& game);
bool mouseOnlySuperscript;
bool showTracker;
int isWaitingForNumber;
......@@ -85,22 +84,24 @@ public:
bool custom;
void enterValue(int value);
void markValue(int value);
void moveUp();
void moveDown();
void moveLeft();
void moveRight();
Game game() { return m_game; }
QChar symbol(int value) const;
public slots:
void setCursor(int cell);
void selectValue(int value);
void setSymbols(SymbolTable* table);
void setFlags(ViewFlags flags);
/// call this to update the view
/// if @p cell is a positive value only the according
/// cell will be updated
void update(int cell = -1);
protected:
void resizeEvent(QResizeEvent *);
void wheelEvent(QWheelEvent* e);
void updateSymbols();
private slots:
void slotHello(int x, int y);
void btn_enter(int x, int y);
......@@ -111,8 +112,6 @@ private slots:
void beginHighlight(int val);
void finishHighlight();
void onCellChange(int index);
void onFullChange();
QWidget* widget() { return this; }
......@@ -128,6 +127,11 @@ private:
bool puzzle_mark_wrong;
int highlighted;
int m_color0;
bool m_guidedMode;
Game m_game;
SymbolTable* m_symbolTable;
};
}
......
......@@ -26,12 +26,21 @@
#include <qpixmap.h>
#include <qpainter.h>
#include "ksview.moc"
#include "sudoku_solver.h"
#include "puzzle.h"
#include <QtDebug>
namespace ksudoku{
KsView::KsView()
: m_game()
KsView::KsView(const Game& game, QObject* parent)
: QObject(parent), m_game(game), m_viewWidget(0)
{
m_symbolTable = 0;
m_currentValue = 1;
m_currentCell = 0;
}
KsView::~KsView()
......@@ -46,28 +55,66 @@ void KsView::draw(QPainter& /*p*/, int /*height*/, int /*width*/) const
// p.drawPixmap(0,0,qp,-1,-1);
}
void KsView::setCursor(int cell) {
m_currentCell = cell;
emit cursorMoved(cell);
}
void KsView::selectValue(int value) {
Q_UNUSED( value );
m_currentValue = value;
emit valueSelected(value);
}
void KsView::enterValue(int value) {
Q_UNUSED( value );
if(!m_game.given(m_currentCell)) {
m_game.setValue(m_currentCell, value);
}
}
void KsView::markValue(int value) {
Q_UNUSED( value );
if(!m_game.given(m_currentCell)) {
m_game.flipMarker(m_currentCell, value);
}
}
void KsView::moveUp() {
Graph* g = m_game.puzzle()->solver()->g;
int x = g->cellPosX(m_currentCell);
int y = g->cellPosY(m_currentCell);