Jean-Marc Lasgouttes wrote:
> Angus> I'll make some time to investigate. Will probably take me a
> Angus> couple of days. OK?
> 
> No problem really. I am so lost, that any help anytime is fine.

Note that I don't know this code at all but it has been broken from day
one. Somehow the Spellchecker dialog has always inverted the logic behind
the basic dialog control path. (Things are much better now, however.)
Everything that follows is therefore a struggle.

Anyway, following the code path, stripping out the noise...

frontends/Dialogs.C is going to call this function to launch the
spellchecker dialog:

void Dialog::show(string const & data)
{
        if (!controller().initialiseParams(data))
                return;
        view().show();
}

ControlSpellchecker::initialiseParams() starts the spell checking engine
and returns true if it succeeds in doing so.

Control passes to QDialogView::show():

void QDialogView::show()
{
        if (!form())
                build();

        update();  // make sure its up-to-date

        if (form()->isVisible()) {
                form()->raise();
        } else {
                form()->show();
        }
}

Ahhhhhh. I think that I see the problem already. update() is the thing that
is going to say "no need to show the dialog because all words are ok" but
isn't communicating this to QDialogView::show() which goes on to
raise()/show() the dialog.

At least, that's my hunch. Let's proceed anyway.

QDialogView::update() is just a wrapper that does some bookkeeping. It
hands the real work over to QSpellchecker::update_contents() which, in
turn, hands control back to ControlSpellchecker::check():

void QSpellchecker::update_contents()
{
        controller().check();
}

void ControlSpellchecker::check()
{
        while (res == SpellBase::OK || res == SpellBase::IGNORED_WORD) {
                word_ = nextWord(cur, start, bufferparams);

                // end of document
                if (getWord().empty()) {
                        showSummary();
                        return;
                }
        }
}

I guess (I can see) that this is the block that's actually launching the "3
words checked" dialog (inside showSummary()). Control returns from this
function back to QDialogView::show() which goes on to raise()/show() the
real spellchecker dialog.

So, why isn't showSummary() setting some magical flag that
QDialogView::show() can use to bail out early?

Here's the code:

void ControlSpellchecker::showSummary()
{
        if (!checkAlive() || count_ == 0) {
                dialog().CancelButton();
                return;
        }

        string message;
        if (count_ != 1)
                message = bformat(_("%1$d words checked."), count_);
        else
                message = _("One word checked.");

        dialog().CancelButton();
        Alert::information(_("Spell-checking is complete"), message);
}

I guess that it's trying to do what we want of it. Those CancelButton()
calls are saying "please hide the open dialog". However, the dialog isn't
yet open in this case...

What I think is needed is 

class Dialog::Controller {
public:
        virtual bool exit_early() const { return false; }
};

which is used by QDialogView::show(), so:

void QDialogView::show()
{
        if (!form())
                build();

        update();  // make sure its up-to-date
+       if (controller().exit_early())
+               return;

        if (form()->isVisible()) {
                form()->raise();
        } else {
                form()->show();
        }
}

and which is specialized by ControlSpellchecker:

class ControlSpellchecker() {
public:
        virtual bool exit_early() const { return exit_early_; }
private:
        bool exit_early_;
}

This flag can be set by showSummary.

I don't pretend that this is pretty, but it wasn't that difficult to
follow, was it?

-- 
Angus

Reply via email to