#include "QzCrossWord.h"

QzCrossWordCell::QzCrossWordCell (QWidget* parent, char*) : QWidget(parent, "QzCrossWordCell") {
    _colLabel   = 0;
    _rowLabel   = 0;
    _solution   = '.';
    _guess      = ' ';
    
    revealSolution(false);
    setShowCorrectness (false);
    setNumber(0);
    showNumber(false);
    hilite(false);
}

QzCrossWordCell::~QzCrossWordCell () {
}

QSize QzCrossWordCell::sizeHint () const {
    return QSize(20,20);
}

QSizePolicy QzCrossWordCell::sizePolicy () const {
    return QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, true);
}

void QzCrossWordCell::setSolution (const char letter) {
    _solution = letter;

    update();
}

void QzCrossWordCell::setColRowLabel (const int col, const int row) {
    _colLabel = col;
    _rowLabel = row;
}

int QzCrossWordCell::colLabel () const {
    return _colLabel;
}

int QzCrossWordCell::rowLabel () const {
    return _rowLabel;
}

void QzCrossWordCell::setGuess (const char letter) {

    setShowCorrectness(false);

    // Don't change guess if cell is revealed.
    if (isSolutionRevealed()) return;

    _guess = letter;

    update();
}

char QzCrossWordCell::solution () const {
    return _solution;
}

char QzCrossWordCell::guess () const {
    return _guess;
}

void QzCrossWordCell::revealSolution (const bool flag) {
    _isSolutionRevealed = flag;

    if (flag == true) {
        setShowCorrectness(false);
    }

    if (flag == false) {
        _guess = ' ';
    }else{
        _guess = solution();
    }

    update();
}

bool QzCrossWordCell::isSolutionRevealed () const {
    return _isSolutionRevealed;
}

bool QzCrossWordCell::showCorrectness () const {
    return _showCorrectness;
}

void QzCrossWordCell::setShowCorrectness (const bool flag) {
    _showCorrectness = flag;

    update ();
}

bool QzCrossWordCell::isSolutionCorrect () const {
    return (solution() == guess());
}

void QzCrossWordCell::setNumber (const int number) {
    _number = number;

    if (_number == 0) showNumber(false);

    update();
}

int QzCrossWordCell::number () const {
    return _number;
}

void QzCrossWordCell::showNumber (const bool flag) {
    if (number() == 0) {
        _isNumberShown = false;
        return;
    }

    _isNumberShown = flag;

    update();
}

bool QzCrossWordCell::isNumberShown () const {
    return _isNumberShown;
}

void QzCrossWordCell::hilite (const bool flag) {
    _isHilited = flag;

    update ();
}

bool QzCrossWordCell::isHilited () const {
    return _isHilited;
}

void QzCrossWordCell::paintEvent (QPaintEvent*) {
    QPainter p(this);
    p.setPen(QPen(QColor("black")));

    if (solution() == '.') {
        paintBlock(p);
    }else{
        if (hasFocus()) {
            p.fillRect(rect(), QColor("yellow"));
        }else{
            if (isHilited()) {
                p.fillRect(rect(), QColor(200,200,200));
            }else{
                p.fillRect(rect(), QColor("white"));
            }
        }

        paintFrame(p);

        if (isNumberShown()) {
            paintNumber(p);
        }

        paintLetter(p);
    }
}

void QzCrossWordCell::paintBlock (QPainter& p) {
    p.fillRect(rect(), QColor("black"));
}

void QzCrossWordCell::paintFrame (QPainter& p) {
    p.setPen(QPen(QColor("black"),1));
    p.drawRect(rect());
}

void QzCrossWordCell::paintNumber (QPainter& p) {
    QRect r = rect();
    r.setHeight( 12 );
    r.moveBy( 3,0 );

    // Resize the font to the size of the cell.
    QFont f = p.font();
    QFontMetrics fm (f);
    while (fm.height() < r.height()) {
        f.setPointSize( f.pointSize() + 2 );
        fm = QFontMetrics(f);
    }
    p.setFont(f);

    QString text;
    text.setNum(number());

    p.drawText(r, Qt::AlignLeft, text);
}

void QzCrossWordCell::paintLetter (QPainter& p) {
    QRect r = rect();
    int deltaY = r.height() - (int)((float)r.height() * .70);

    r.setHeight( r.height() - deltaY );
    r.moveBy( 0, deltaY );

    // Resize the font to the size of the cell.
    QFont f = p.font();
    QFontMetrics fm (f);
    while (fm.height() < r.height()) {
        f.setPointSize( f.pointSize() + 2 );
        fm = QFontMetrics(f);
    }
    p.setFont(f);

    QString letter;
    if (isSolutionRevealed() == false) {
        letter = QString(QChar(guess()));
    }else{
        letter = QString(QChar(solution()));
    }

    p.drawText(r, Qt::AlignCenter, letter, 1);

    if (showCorrectness() == true && isSolutionRevealed() == false && guess() != ' ' && isSolutionCorrect() == false) {
        p.drawLine (rect().width(),0, 0,rect().height());
    }
}




QzCrossWordGrid::QzCrossWordGrid (QWidget* parent, char* name) : QWidget (parent, name){
    _gridLayout       = 0;
    _puzzle           = 0;
    _focusOrientation = FocusHorizontal;

    setBackgroundColor("white");
}

QzCrossWordGrid::QzCrossWordGrid (AcrossLitePuzzleBase* puzzle, QWidget* parent, char* name) : QWidget (parent, name) {
    _gridLayout       = 0;
    _puzzle           = 0;
    _focusOrientation = FocusHorizontal;

    setBackgroundColor("white");

    setPuzzle (puzzle);
}

QzCrossWordGrid::~QzCrossWordGrid () {
}

void QzCrossWordGrid::setPuzzle (AcrossLitePuzzleBase* puzzle) {
    if (_gridLayout) {
        delete _gridLayout;
        _gridLayout = 0;
    }

    while (_cells.size() > 0) {
        QzCrossWordCell* w = _cells.back();
        delete w;
        _cells.pop_back();
    }

    _gridLayout       = new QGridLayout(this, 1, 1);
    _puzzle           = puzzle;
    _focusOrientation = FocusHorizontal;

    for (int r = 0; r<_puzzle->nRows(); r++) {
        for (int c = 0; c<_puzzle->nColumns(); c++) {
            QzCrossWordCell* w = new QzCrossWordCell(this);
            w->setColRowLabel(c,r);
            w->setSolution(_puzzle->solutionCell(c,r));
            w->setShowCorrectness (false);
            // w->setGuess(' ');
            w->setGuess(_puzzle->diagramCell(c,r));
            w->setNumber(_puzzle->cellNumber(c,r));
            w->showNumber(true);
            w->setFocusPolicy(QWidget::ClickFocus);
            w->show();

            w->installEventFilter( this ); // then install filter

            _gridLayout->addWidget(w,r,c);

            _cells.push_back(w);
        }
    }

    _gridLayout->activate();
};

AcrossLitePuzzleBase* QzCrossWordGrid::puzzle () {
    return _puzzle;
}

void QzCrossWordGrid::savePuzzle (const QString& filename) {
    if (_puzzle == 0) return;

    QString f = filename;

    if (f.contains('.') == false) {
        f += ".puz";
    }

    int indx = f.findRev('.');

    QString sub = f.mid(indx);

    if (sub != QString(".puz")) {
        QMessageBox::warning (this, "KrossWordPlayer", "Trying to save to a file with a '" + sub + "' extension\nwhen it should be a '.puz' extension.");
        return;
    }

    AcrossLitePuzPuzzle puz;
    puz.copy(*_puzzle);

    QObjectList*  l = queryList("QWidget", "QzCrossWordCell");
    QObjectListIt it(*l);
    QObject*      obj;

    while ( (obj=it.current()) != 0) {
        QzCrossWordCell* cel = (QzCrossWordCell*)obj;

        if (cel->solution() != '.') {
            int letter = cel->guess();
            puz.setDiagramCell(cel->colLabel(), cel->rowLabel(), letter);
        }

        ++it;
    }


    puz.save(f.ascii());
}

void QzCrossWordGrid::revealSolution (const bool flag) {
    QObjectList*  l = queryList("QWidget", "QzCrossWordCell");
    QObjectListIt it(*l);
    QObject*      obj;

    while ( (obj=it.current()) != 0) {
        ((QzCrossWordCell*)obj)->revealSolution(flag);
        ++it;
    }
}

void QzCrossWordGrid::revealWord (const bool flag) {
    QObjectList*  l = queryList("QWidget", "QzCrossWordCell");
    QObjectListIt it(*l);
    QObject*      obj;

    while ( (obj=it.current()) != 0) {
        QzCrossWordCell* cell = (QzCrossWordCell*)obj;
        if (cell->isHilited()) {
            cell->revealSolution(flag);
        }
        ++it;
    }
}

void QzCrossWordGrid::revealLetter (const bool flag) {
    QzCrossWordCell* cell = focusCell();
    if (cell != 0 && cell->isHilited()) {
        cell->revealSolution(flag);
    }
}

void QzCrossWordGrid::uncheckSolution () {
    QObjectList*  l = queryList("QWidget", "QzCrossWordCell");
    QObjectListIt it(*l);
    QObject*      obj;

    while ( (obj=it.current()) != 0) {
        ((QzCrossWordCell*)obj)->setShowCorrectness(false);
        ++it;
    }
}

void QzCrossWordGrid::checkSolution () {
    QObjectList*  l = queryList("QWidget", "QzCrossWordCell");
    QObjectListIt it(*l);
    QObject*      obj;

    while ( (obj=it.current()) != 0) {
        ((QzCrossWordCell*)obj)->setShowCorrectness(true);
        ++it;
    }
}

void QzCrossWordGrid::checkWord () {
    QObjectList*  l = queryList("QWidget", "QzCrossWordCell");
    QObjectListIt it(*l);
    QObject*      obj;

    while ( (obj=it.current()) != 0) {
        QzCrossWordCell* cell = (QzCrossWordCell*)obj;
        if (cell->isHilited()) {
            cell->setShowCorrectness(true);
        }
        ++it;
    }
}

void QzCrossWordGrid::checkLetter () {
    QzCrossWordCell* cell = focusCell();
    if (cell != 0 && cell->isHilited()) {
        cell->setShowCorrectness(true);
    }
}

QSize QzCrossWordGrid::sizeHint () const {
    return QSize(20,20);
}

QSizePolicy QzCrossWordGrid::sizePolicy () const {
    return QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, true);
}

QSize QzCrossWordGrid::minimumSizeHint () const {
    return QSize(20,20);
}

void QzCrossWordGrid::keyPressEvent (QKeyEvent* e) {
    QString letter = e->text().upper();

    // cout << "Grid - Key pressed: " << letter.ascii() << endl;

    QzCrossWordCell* cell = focusCell();
    if (cell) {
        if (e->key() == Key_Right) {
            if (focusOrientation() == QzCrossWordGrid::FocusHorizontal) {
                setFocusCell(cell->colLabel()+1, cell->rowLabel());
            }else{
                setFocusOrientation(QzCrossWordGrid::FocusHorizontal);
            }

        }else if (e->key() == Key_Left) {
            if (focusOrientation() == QzCrossWordGrid::FocusHorizontal) {
                setFocusCell(cell->colLabel()-1, cell->rowLabel());
            }else{
                setFocusOrientation(QzCrossWordGrid::FocusHorizontal);
            }

        }else if (e->key() == Key_Up) {
            if (focusOrientation() == QzCrossWordGrid::FocusVertical) {
                setFocusCell(cell->colLabel(), cell->rowLabel()-1);
            }else{
                setFocusOrientation(QzCrossWordGrid::FocusVertical);
            }

        }else if (e->key() == Key_Down) {
            if (focusOrientation() == QzCrossWordGrid::FocusVertical) {
                setFocusCell(cell->colLabel(), cell->rowLabel()+1);
            }else{
                setFocusOrientation(QzCrossWordGrid::FocusVertical);
            }

        }else if (e->key() >= Key_A && e->key() <= Key_Z) {
            cell->setGuess (letter.ascii()[0]);

            advanceFocusCell();

        }else if (e->key() == Key_Space) {
            cell->setGuess (' ');

            advanceFocusCell();

        }else if (e->key() == Key_Delete || e->key() == Key_BackSpace) {
            cell->setGuess (' ');

            advanceFocusCell(-1);
        }
    }
}

void QzCrossWordGrid::mousePressEvent (QMouseEvent* e) {
    hiliteFullSolution(false);

    if (e->button() == RightButton) {
        if (focusOrientation() == QzCrossWordGrid::FocusHorizontal) {
            setFocusOrientation(QzCrossWordGrid::FocusVertical);
        }else if (focusOrientation() == QzCrossWordGrid::FocusVertical) {
            setFocusOrientation(QzCrossWordGrid::FocusHorizontal);
        }
    }

    hiliteSolution(true);
}

bool QzCrossWordGrid::eventFilter( QObject* o, QEvent* e ) {
    if ( e->type() == QEvent::KeyPress ) {  // key press
        QKeyEvent* k = (QKeyEvent*)e;
        switch (k->key()) {
            case Key_Left:
            case Key_Right:
            case Key_Up:
            case Key_Down:
            case Key_Delete:
            case Key_BackSpace:
                keyPressEvent(k);
                return TRUE;  // eat event
                break;
            default:
                if (k->key() >= Key_A && k->key() <= Key_Z) {
                    keyPressEvent(k);
                    return TRUE;
                }
                break;
        }

    }else if ( e->type() == QEvent::MouseButtonPress ) {  // mouse press
        QMouseEvent* m = (QMouseEvent*)e;
        switch(m->button()) {
            case RightButton:
            case LeftButton:
                {
                    mousePressEvent(m);

                    QzCrossWordCell* cell = focusCell();
                    if (cell) {
                        setFocusCell (cell->colLabel(), cell->rowLabel());
                    }

                    return TRUE; // eat event
                }

                break;

            default:
                break;
        }
    }

    return QWidget::eventFilter( o, e );    // standard event processing
}

QzCrossWordCell* QzCrossWordGrid::focusCell () {
    QObjectList*  l = queryList("QWidget", "QzCrossWordCell");
    QObjectListIt it(*l);
    QObject*      obj;

    while ( (obj=it.current()) != 0) {
        QzCrossWordCell* cell = (QzCrossWordCell*)obj;
        if (cell->hasFocus()) {
            return cell;
        }
        ++it;
    }

    return 0;
}

QzCrossWordCell* QzCrossWordGrid::cell (const int col, const int row) {
    QObjectList*  l = queryList("QWidget", "QzCrossWordCell");
    QObjectListIt it(*l);
    QObject*      obj;

    while ( (obj=it.current()) != 0) {
        QzCrossWordCell* cell = (QzCrossWordCell*)obj;
        if (cell->colLabel() == col && cell->rowLabel() == row) {
            return cell;
        }
        ++it;
    }

    return 0;
}

QzCrossWordCell* QzCrossWordGrid::cell (const int number) {
    QObjectList*  l = queryList("QWidget", "QzCrossWordCell");
    QObjectListIt it(*l);
    QObject*      obj;

    while ( (obj=it.current()) != 0) {
        QzCrossWordCell* cell = (QzCrossWordCell*)obj;
        if (cell->number() == number) {
            return cell;
        }
        ++it;
    }

    return 0;
}


void QzCrossWordGrid::setFocusCell (const int col, const int row) {
    hiliteSolution(false);

    QzCrossWordCell* c = cell(col, row);
    if (c) {
        c->setFocus();

        hiliteSolution(true);

        emit colFocused(col);
        emit rowFocused(row);
        emit colRowFocused(col,row);
    }
}

void QzCrossWordGrid::setFocusCell (AcrossLiteClue::Orientation o, int number) {
    hiliteFullSolution(false);

    QzCrossWordCell* c = cell(number);
    if (c) {
        setFocusCell(c->colLabel(), c->rowLabel());

        if (o == AcrossLiteClue::Across) {
            setFocusOrientation (QzCrossWordGrid::FocusHorizontal);
        }else if (o == AcrossLiteClue::Down) {
            setFocusOrientation (QzCrossWordGrid::FocusVertical);
        }else{
            setFocusOrientation (QzCrossWordGrid::FocusUnknown);
        }

        hiliteSolution(true);
    }
}

void QzCrossWordGrid::advanceFocusCell(const int count) {
    QzCrossWordCell* c = focusCell();
    if (c == 0) return;

    int col = c->colLabel();
    int row = c->rowLabel();

    if (focusOrientation() == QzCrossWordGrid::FocusVertical) {
        QzCrossWordCell* cx = cell(col, row+count);
        if (cx == 0) return;
        if (cx->solution() == '.') return;

        setFocusCell (col, row+count);

    }else if (focusOrientation() == QzCrossWordGrid::FocusHorizontal) {
        QzCrossWordCell* cx = cell(col+count, row);
        if (cx == 0) return;
        if (cx->solution() == '.') return;

        setFocusCell (col+count, row);
    }
}

void QzCrossWordGrid::setFocusOrientation (const QzCrossWordGrid::FocusOrientation orientation) {
    hiliteSolution(false);

    _focusOrientation = orientation;

    hiliteSolution(true);
}

QzCrossWordGrid::FocusOrientation QzCrossWordGrid::focusOrientation () const {
    return _focusOrientation;
}

void QzCrossWordGrid::hiliteSolution (const bool flag) {
    QzCrossWordCell* c = focusCell();
    if (c == 0) return;

    int col = c->colLabel(); // Get current col/row.
    int row = c->rowLabel();

    if (focusOrientation() == QzCrossWordGrid::FocusVertical) {
        // Current to top.
        for (int r = row; ; r--) {
            QzCrossWordCell* cx = cell(col, r);
            if (cx == 0) break;
            if (cx->solution() == '.') break;

            cx->hilite(flag);
        }
        
        // Current to bottom.
        for (int r = row; ; r++) {
            QzCrossWordCell* cx = cell(col, r);
            if (cx == 0) break;
            if (cx->solution() == '.') break;

            cx->hilite(flag);
        }

    }else if (focusOrientation() == QzCrossWordGrid::FocusHorizontal) {
        // Current to left.
        for (int c = col; ; c--) {
            QzCrossWordCell* cx = cell(c, row);
            if (cx == 0) break;
            if (cx->solution() == '.') break;

            cx->hilite(flag);
        }
        
        // Current to right.
        for (int c = col; ; c++) {
            QzCrossWordCell* cx = cell(c, row);
            if (cx == 0) break;
            if (cx->solution() == '.') break;

            cx->hilite(flag);
        }
    }
}

void QzCrossWordGrid::hiliteFullSolution (const bool flag) {
    QObjectList*  l = queryList("QWidget", "QzCrossWordCell");
    QObjectListIt it(*l);
    QObject*      obj;

    while ( (obj=it.current()) != 0) {
        QzCrossWordCell* cell = (QzCrossWordCell*)obj;
        if (cell->isHilited() != flag) {
            cell->hilite(flag);
        }
        ++it;
    }
}

void QzCrossWordGrid::colRowToDownAcross (const int col, const int row,  int& down, int& across) {
    down = across = -1;

    // Find nearest down solution number.
    int r = row;
    QzCrossWordCell* downCell = cell(col, r);
    while (downCell) {
        if (downCell->solution() == '.') break;

        down = downCell->number();

        downCell = cell(col, --r);
    }

    // Find nearest across solution number.
    int c = col;
    QzCrossWordCell* acrossCell = cell(c, row);
    while (acrossCell) {
        if (acrossCell->solution() == '.') break;

        across = acrossCell->number();

        acrossCell = cell(--c, row);
    }
}





QzCrossWordClue::QzCrossWordClue (const int n, QListBox* listbox, const QString& text) : QListBoxText (listbox, "") {
    _number = n;

    setText (QString::number(number()) + QString(".") + text);
}

QzCrossWordClue::QzCrossWordClue (const int n, const QString& text) : QListBoxText ("") {
    _number = n;

    setText (QString::number(number()) + QString(".") + text);
}

QzCrossWordClue::QzCrossWordClue (const int n, QListBox* listbox, const QString& text, QListBoxItem* after) : QListBoxText (listbox, "", after) {
    _number = n;

    setText (QString::number(number()) + QString(".") + text);
}

QzCrossWordClue::~QzCrossWordClue () {
}


int QzCrossWordClue::number () const {
    return _number;
}

QzCrossWordClueList::QzCrossWordClueList ( QWidget* parent, char* name ) : QListBox (parent, name) {
    _puzzle   = 0;
    _clueList = AcrossLiteClue::Unknown;

    QObject::connect (this, SIGNAL(pressed(QListBoxItem*)), this, SLOT(_selected(QListBoxItem*)));
}

QzCrossWordClueList::QzCrossWordClueList ( AcrossLitePuzzleBase* puzzle, AcrossLiteClue::Orientation clueList, QWidget* parent, char* name) : QListBox (parent, name) {
    _puzzle   = 0;
    _clueList = AcrossLiteClue::Unknown;

    setPuzzle (puzzle, clueList);
}

QzCrossWordClueList::~QzCrossWordClueList () {
}

void QzCrossWordClueList::setPuzzle (AcrossLitePuzzleBase* puzzle, AcrossLiteClue::Orientation clueList) {
    _puzzle   = puzzle;
    _clueList = clueList;

    clear ();

    if (_clueList == AcrossLiteClue::Across) {
        AcrossLiteClues::const_iterator b = _puzzle->beginAcrossClue ();
        AcrossLiteClues::const_iterator e = _puzzle->endAcrossClue ();
        while (b != e) {
            QzCrossWordClue* clue = new QzCrossWordClue ( (*b).number(), QString((*b).clue().c_str()) );
            insertItem (clue);

            b++;
        }

    }else if (_clueList == AcrossLiteClue::Down) {
        AcrossLiteClues::const_iterator b = _puzzle->beginDownClue ();
        AcrossLiteClues::const_iterator e = _puzzle->endDownClue ();
        while (b != e) {
            QzCrossWordClue* clue = new QzCrossWordClue ( (*b).number(), QString((*b).clue().c_str()) );
            insertItem (clue);

            b++;
        }
    }
}

AcrossLitePuzzleBase* QzCrossWordClueList::puzzle () {
    return _puzzle;
}

AcrossLiteClue::Orientation QzCrossWordClueList::clueList () {
    return _clueList;
}

void QzCrossWordClueList::clueSelected (int n) {
    for (unsigned int i=0; i<count(); i++) {
        QzCrossWordClue* clue = (QzCrossWordClue*) item(i);
        if (clue->number() == n) {
            setSelected (i, true);
            break;
        }
    }

    ensureCurrentVisible();
}

void QzCrossWordClueList::_selected (QListBoxItem* item) {
    QzCrossWordClue* clue = (QzCrossWordClue*) item;

    if (clue) {
        emit clueSelected(clueList(), clue->number());
    }
}



QzCrossWord::QzCrossWord (QWidget* parent, char* name) : QWidget (parent, name) {
    _puzzle      = 0;
    _grid        = 0;
    _acrossClues = 0;
    _downClues   = 0;

    // Create widgets
    _puzzleGroupBox = new QHGroupBox("Puzzle", this);

    QVBox*      cluesBox       = new QVBox(this);
    QVGroupBox* acrossGroupBox = new QVGroupBox("Across", cluesBox);
    QVGroupBox* downGroupBox   = new QVGroupBox("Down",   cluesBox);

    _grid        = new QzCrossWordGrid     (_puzzleGroupBox);
    _grid->setMinimumSize(500,500);
    _acrossClues = new QzCrossWordClueList (acrossGroupBox);
    _acrossClues->setMinimumWidth(300);
    _downClues   = new QzCrossWordClueList (downGroupBox);
    _downClues->setMinimumWidth(300);

    // Create Layouts
    QLayout* topLayout = new QHBoxLayout(this, 5);
    topLayout->add(_puzzleGroupBox);
    topLayout->add(cluesBox);

    QObject::connect (_acrossClues, SIGNAL(clueSelected(AcrossLiteClue::Orientation, int)), _grid,        SLOT(setFocusCell(AcrossLiteClue::Orientation, int)));
    QObject::connect (_downClues,   SIGNAL(clueSelected(AcrossLiteClue::Orientation, int)), _grid,        SLOT(setFocusCell(AcrossLiteClue::Orientation, int)));
    QObject::connect (_grid,        SIGNAL(colRowFocused(int, int)),                        this,         SLOT(handleNewColRowFocused(int, int)));
}

QzCrossWord::~QzCrossWord () {
    if (_puzzle) {
        delete _puzzle;
        _puzzle = 0;
    }
}

void QzCrossWord::setPuzzle (const QString& filename) {
    if (_puzzle) {
        delete _puzzle;
        _puzzle = 0;
    }

    if (filename.right(4) == QString(".puz")) {
        _puzzle = new AcrossLitePuzPuzzle(filename.ascii());

    }else if (filename.right(4) == QString(".txt")) {
        _puzzle = new AcrossLiteTxtPuzzle(filename.ascii());
    }

    _grid->setPuzzle (_puzzle);
    _acrossClues->setPuzzle (_puzzle, AcrossLiteClue::Across);
    _downClues->setPuzzle (_puzzle, AcrossLiteClue::Down);

    _puzzleGroupBox->setTitle(QString(_puzzle->puzzleName().c_str()));
}

void QzCrossWord::savePuzzle (const QString& filename) {
    _grid->savePuzzle(filename);
}

void QzCrossWord::clearSolution () {
    _grid->revealSolution (false);
    _grid->uncheckSolution ();
}

void QzCrossWord::revealSolution (const bool flag) {
    _grid->revealSolution (flag);
}

void QzCrossWord::revealWord (const bool flag) {
    _grid->revealWord (flag);
}

void QzCrossWord::revealLetter (const bool flag) {
    _grid->revealLetter (flag);
}

void QzCrossWord::checkSolution () {
    _grid->checkSolution ();
}

void QzCrossWord::checkWord () {
    _grid->checkWord ();
}

void QzCrossWord::checkLetter () {
    _grid->checkLetter ();
}

void QzCrossWord::handleNewColRowFocused (int newCol, int newRow) {
    int down, across;

    _grid->colRowToDownAcross (newCol, newRow, down, across);

    if (down != -1) {
        _downClues->clueSelected (down);
    }

    if (across != -1) {
        _acrossClues->clueSelected (across);
    }
}

