Am Montag, 28. März 2005 22:33 schrieb Angus Leeming: > Georg Baum wrote: > > Therefore I took the idea a bit further and came up with the attached > > patch. checkStatus() is implemented in the base class and calls > > getStatus with LFUN_INSET_APPLY. This is handled in > > InsetBase::getStatus() and only accepted if it comes from this insets's > > dialog. This prevents that open dialogs are applied in the wrong insets. > > If that is not correct for some inset (as e.g. in InsetText) it needs to > > be overriden in that inset. > > The patch seems to work, but I would like to get some feedback, and I > > need to check wether LFUN_INSET_APPLY is short-circuited in other insets > > than InsetERT, too. > > Georg, the idea looks fine to me, but I think some comments in the > LFUN_INSET_APPLY block in buffer.C about the expected usage would help.
There is no LFUN_INSET_APPLY block in buffer.C ;-( Anyway, the idea was not fine enough since invoking the tabular dialog hit the assert in LyXText::getStatus because LyXText::getStatus did not handle LFUN_INSET_MODIFY. The second bug was that InsetBase::getStatus got sometimes called with LFUN_INSET_MODIFY or LFUN_INSET_INSERT and not LFUN_INSET_APPLY. Attached is a new patch with better logic and some more comments. I moved the handling of LFUN_INSET_APPLY from text3.C to lyxfunc.C. The alternative was to duplicate it in insetbase.C, because InsetBase::getStatus() would be called if checkStatus was called when the cursor was inside an inset. I'll commit this unless somebody finds more problems. Georg
diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/ChangeLog lyx-1.4-cvs/src/ChangeLog --- lyx-1.4-clean/src/ChangeLog 2005-04-07 20:33:21.000000000 +0200 +++ lyx-1.4-cvs/src/ChangeLog 2005-04-10 14:43:56.000000000 +0200 @@ -1,3 +1,9 @@ +2005-04-10 Georg Baum <[EMAIL PROTECTED]> + + * lyxfunc.C (getStatus, dispatch): handle LFUN_INSET_APPLY + * text3.C (getStatus, dispatch): don't handle LFUN_INSET_APPLY anymore + * text3.C (getStatus): disable LFUN_INSET_MODIFY + 2005-04-06 Martin Vermeer <[EMAIL PROTECTED]> * CutAndPaste.C (eraseSelection): more precise fix for bug 1654, diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/lyxfunc.C lyx-1.4-cvs/src/lyxfunc.C --- lyx-1.4-clean/src/lyxfunc.C 2005-04-07 20:33:37.000000000 +0200 +++ lyx-1.4-cvs/src/lyxfunc.C 2005-04-10 14:13:59.000000000 +0200 @@ -462,6 +462,24 @@ FuncStatus LyXFunc::getStatus(FuncReques break; } + case LFUN_INSET_APPLY: { + string const name = cmd.getArg(0); + InsetBase * inset = owner->getDialogs().getOpenInset(name); + if (inset) { + FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument); + FuncStatus fs; + bool const success = inset->getStatus(cur, fr, fs); + // Every inset is supposed to handle this + BOOST_ASSERT(success); + flag |= fs; + } else { + FuncRequest fr(LFUN_INSET_INSERT, cmd.argument); + flag |= getStatus(fr); + } + enable = flag.enabled(); + break; + } + case LFUN_DIALOG_SHOW: { string const name = cmd.getArg(0); if (!buf) @@ -1324,6 +1344,19 @@ void LyXFunc::dispatch(FuncRequest const break; } + case LFUN_INSET_APPLY: { + string const name = cmd.getArg(0); + InsetBase * inset = owner->getDialogs().getOpenInset(name); + if (inset) { + FuncRequest fr(LFUN_INSET_MODIFY, argument); + inset->dispatch(view()->cursor(), fr); + } else { + FuncRequest fr(LFUN_INSET_INSERT, argument); + dispatch(fr); + } + break; + } + case LFUN_ALL_INSETS_TOGGLE: { string action; string const name = split(argument, action, ' '); @@ -1485,6 +1519,7 @@ void LyXFunc::dispatch(FuncRequest const view()->update(true, update); // if we executed a mutating lfun, mark the buffer as dirty + // FIXME: Why not use flag.enabled() but call getStatus again? if (getStatus(cmd).enabled() && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)) diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/text3.C lyx-1.4-cvs/src/text3.C --- lyx-1.4-clean/src/text3.C 2005-03-10 20:51:19.000000000 +0100 +++ lyx-1.4-cvs/src/text3.C 2005-04-10 15:06:31.000000000 +0200 @@ -301,7 +299,7 @@ void LyXText::dispatch(LCursor & cur, Fu bool start = !par.params().startOfAppendix(); #ifdef WITH_WARNINGS -#warning The code below only makes sense a top level. +#warning The code below only makes sense at top level. // Should LFUN_APPENDIX be restricted to top-level paragraphs? #endif // ensure that we have only one start_of_appendix in this document @@ -715,19 +713,6 @@ void LyXText::dispatch(LCursor & cur, Fu break; } - case LFUN_INSET_APPLY: { - string const name = cmd.getArg(0); - InsetBase * inset = bv->owner()->getDialogs().getOpenInset(name); - if (inset) { - FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument); - inset->dispatch(cur, fr); - } else { - FuncRequest fr(LFUN_INSET_INSERT, cmd.argument); - dispatch(cur, fr); - } - break; - } - case LFUN_INSET_INSERT: { recordUndo(cur); InsetBase * inset = createInset(bv, cmd); @@ -1728,6 +1717,14 @@ bool LyXText::getStatus(LCursor & cur, F case LFUN_INSET_DIALOG_SHOW: break; + case LFUN_INSET_MODIFY: + // We need to disable this, because we may get called for a + // tabular cell via + // InsetTabular::getStatus() -> InsetText::getStatus() + // and we don't handle LFUN_INSET_MODIFY. + enable = false; + break; + case LFUN_EMPH: flag.setOnOff(font.emph() == LyXFont::ON); break; @@ -1789,7 +1786,6 @@ bool LyXText::getStatus(LCursor & cur, F case LFUN_BREAKPARAGRAPHKEEPLAYOUT: case LFUN_BREAKPARAGRAPH_SKIP: case LFUN_PARAGRAPH_SPACING: - case LFUN_INSET_APPLY: case LFUN_INSET_INSERT: case LFUN_NEXT_INSET_TOGGLE: case LFUN_UPCASE_WORD: diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/frontends/ChangeLog lyx-1.4-cvs/src/frontends/ChangeLog --- lyx-1.4-clean/src/frontends/ChangeLog 2005-03-06 12:46:00.000000000 +0100 +++ lyx-1.4-cvs/src/frontends/ChangeLog 2005-03-29 09:53:15.000000000 +0200 @@ -1,3 +1,8 @@ +2005-04-10 Georg Baum <[EMAIL PROTECTED]> + + * Dialogs.[Ch] (checkStatus): new + * LyXView.C (updateToolbars): call Dialogs::checkStatus + 2005-03-06 Lars Gullik Bjonnes <[EMAIL PROTECTED]> * Makefile.am (DIST_SUBDIRS): remove gnome diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/frontends/Dialogs.C lyx-1.4-cvs/src/frontends/Dialogs.C --- lyx-1.4-clean/src/frontends/Dialogs.C 2005-02-22 20:44:19.000000000 +0100 +++ lyx-1.4-cvs/src/frontends/Dialogs.C 2005-03-28 17:08:12.000000000 +0200 @@ -231,3 +240,16 @@ void Dialogs::redraw() const it->second->redraw(); } } + + +void Dialogs::checkStatus() +{ + std::map<string, DialogPtr>::const_iterator it = dialogs_.begin(); + std::map<string, DialogPtr>::const_iterator end = dialogs_.end(); + + for(; it != end; ++it) { + Dialog * const dialog = it->second.get(); + if (dialog->isVisible()) + dialog->checkStatus(); + } +} diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/frontends/Dialogs.h lyx-1.4-cvs/src/frontends/Dialogs.h --- lyx-1.4-clean/src/frontends/Dialogs.h 2005-02-22 20:44:19.000000000 +0100 +++ lyx-1.4-cvs/src/frontends/Dialogs.h 2005-03-28 15:18:26.000000000 +0200 @@ -42,6 +42,15 @@ public: */ static boost::signal<void()> & redrawGUI(); + /** Check the status of all visible dialogs and disable or reenable + * them as appropriate. + * + * Disabling is needed for example when a dialog is open and the + * cursor moves to a position where the corresponding inset is not + * allowed. + */ + void checkStatus(); + /// Toggle tooltips on/off in all dialogs. static void toggleTooltips(); diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/frontends/gtk/GParagraph.h lyx-1.4-cvs/src/frontends/gtk/GParagraph.h --- lyx-1.4-clean/src/frontends/gtk/GParagraph.h 2004-10-01 20:59:36.000000000 +0200 +++ lyx-1.4-cvs/src/frontends/gtk/GParagraph.h 2005-04-10 14:44:27.000000000 +0200 @@ -4,7 +4,7 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * - * \auther John Spray + * \author John Spray * * Full author contact details are available in file CREDITS. */ diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/frontends/LyXView.C lyx-1.4-cvs/src/frontends/LyXView.C --- lyx-1.4-clean/src/frontends/LyXView.C 2005-02-08 20:28:48.000000000 +0100 +++ lyx-1.4-cvs/src/frontends/LyXView.C 2005-03-31 12:58:05.000000000 +0200 @@ -112,6 +112,10 @@ void LyXView::updateToolbars() bool const table = getLyXFunc().getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled(); toolbars_->update(math, table); + // update redaonly status of open dialogs. This could also be in + // updateMenubar(), but since updateToolbars() and updateMenubar() + // are always called together it is only here. + getDialogs().checkStatus(); } diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/frontends/controllers/ChangeLog lyx-1.4-cvs/src/frontends/controllers/ChangeLog --- lyx-1.4-clean/src/frontends/controllers/ChangeLog 2005-03-27 18:00:18.000000000 +0200 +++ lyx-1.4-cvs/src/frontends/controllers/ChangeLog 2005-03-28 17:11:42.000000000 +0200 @@ -1,3 +1,7 @@ +2005-04-10 Georg Baum <[EMAIL PROTECTED]> + + * Dialog.[Ch] (checkStatus): new + 2005-03-27 MArtin Vermeer <[EMAIL PROTECTED]> * ControlDocument.C (dispatch_bufferparams): fix bug 1843 diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/frontends/controllers/Dialog.C lyx-1.4-cvs/src/frontends/controllers/Dialog.C --- lyx-1.4-clean/src/frontends/controllers/Dialog.C 2004-05-21 08:55:40.000000000 +0200 +++ lyx-1.4-cvs/src/frontends/controllers/Dialog.C 2005-04-04 21:27:01.000000000 +0200 @@ -15,6 +15,12 @@ #include "ButtonController.h" #include "BCView.h" +#include "frontends/LyXView.h" + +#include "funcrequest.h" +#include "FuncStatus.h" +#include "lyxfunc.h" + using std::string; @@ -167,6 +177,17 @@ void Dialog::setView(View * v) } +void Dialog::checkStatus() +{ + FuncRequest const fr(LFUN_INSET_APPLY, name()); + FuncStatus const fs(kernel().lyxview().getLyXFunc().getStatus(fr)); + if (fs.enabled()) + bc().readOnly(kernel().isBufferReadonly()); + else + bc().readOnly(true); +} + + Dialog::Controller::Controller(Dialog & parent) : parent_(parent) {} diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/frontends/controllers/Dialog.h lyx-1.4-cvs/src/frontends/controllers/Dialog.h --- lyx-1.4-clean/src/frontends/controllers/Dialog.h 2004-05-21 08:55:40.000000000 +0200 +++ lyx-1.4-cvs/src/frontends/controllers/Dialog.h 2005-03-28 15:29:18.000000000 +0200 @@ -70,6 +75,12 @@ public: void redraw(); //@} + /** Check wether we may apply our data. + * + * The buttons are disabled if not and (re-)enabled if yes. + */ + void checkStatus(); + /** When applying, it's useful to know whether the dialog is about * to close or not (no point refreshing the display for example). */ diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/frontends/controllers/Kernel.h lyx-1.4-cvs/src/frontends/controllers/Kernel.h --- lyx-1.4-clean/src/frontends/controllers/Kernel.h 2004-11-08 19:45:42.000000000 +0100 +++ lyx-1.4-cvs/src/frontends/controllers/Kernel.h 2005-04-10 12:52:20.000000000 +0200 @@ -33,7 +33,7 @@ public: /// \param lv is the access point for the dialog to the LyX kernel. Kernel(LyXView & lv); - /** This method is the primary puypose of the class. It provides + /** This method is the primary purpose of the class. It provides * the "gateway" by which the dialog can send a request (of a * change in the data, for more information) to the kernel. * \param fr is the encoding of the request. @@ -41,7 +41,7 @@ public: void dispatch(FuncRequest const & fr) const; /** The dialog has received a request from the user - * (who pressed the "Restore" buuton) to update contents. + * (who pressed the "Restore" button) to update contents. * It must, therefore, ask the kernel to provide this information. * \param name is used to identify the dialog to the kernel. */ diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/insets/ChangeLog lyx-1.4-cvs/src/insets/ChangeLog --- lyx-1.4-clean/src/insets/ChangeLog 2005-04-07 20:34:08.000000000 +0200 +++ lyx-1.4-cvs/src/insets/ChangeLog 2005-04-10 14:42:47.000000000 +0200 @@ -1,3 +1,11 @@ +2005-04-10 Georg Baum <[EMAIL PROTECTED]> + + * insetbase.C (getStatus): handle LFUN_INSET_MODIFY and + LFUN_INSET_INSERT + * insetbase.h (getStatus): add more documentation + * insettabular.C (getStatus): disable LFUN_INSET_INSERT with multiple + cells selected + 2005-04-05 Martin Vermeer <[EMAIL PROTECTED]> * insetexternal.C (validate): diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/insets/insetbase.C lyx-1.4-cvs/src/insets/insetbase.C --- lyx-1.4-clean/src/insets/insetbase.C 2005-02-01 20:15:55.000000000 +0100 +++ lyx-1.4-cvs/src/insets/insetbase.C 2005-04-10 15:41:53.000000000 +0200 @@ -20,6 +20,8 @@ #include "debug.h" #include "dimension.h" #include "dispatchresult.h" +#include "funcrequest.h" +#include "FuncStatus.h" #include "gettext.h" #include "lyxtext.h" #include "metricsinfo.h" @@ -136,9 +143,38 @@ void InsetBase::doDispatch(LCursor & cur } -bool InsetBase::getStatus(LCursor &, FuncRequest const &, FuncStatus &) const +bool InsetBase::getStatus(LCursor &, FuncRequest const & cmd, + FuncStatus & flag) const { - return false; + // LFUN_INSET_APPLY is sent from the dialogs when the data should + // be applied. This is either changed to LFUN_INSET_MODIFY (if the + // dialog belongs to us) or LFUN_INSET_INSERT (if the dialog does + // not belong to us, i. e. the dialog was open, and the user moved + // the cursor in our inset) in LyXFunc::getStatus(). + // Dialogs::checkStatus() ensures that the dialog is deactivated if + // LFUN_INSET_APPLY is disabled. + + switch (cmd.action) { + case LFUN_INSET_MODIFY: + // Only allow modification of our own data. + // This needs to be handled in the doDispatch method of our + // instantiatable children. + if (lyxCode() == translate(cmd.getArg(0))) { + flag.enabled(true); + return true; + } + return false; + + case LFUN_INSET_INSERT: + // Don't allow insertion of new insets. + // Every inset that wants to allow new insets from open + // dialogs needs to override this. + flag.enabled(false); + return true; + + default: + return false; + } } diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/insets/insetbase.h lyx-1.4-cvs/src/insets/insetbase.h --- lyx-1.4-clean/src/insets/insetbase.h 2005-01-06 20:28:34.000000000 +0100 +++ lyx-1.4-cvs/src/insets/insetbase.h 2005-04-10 16:11:49.000000000 +0200 @@ -85,6 +85,18 @@ public: * \returns true if this function made a definitive decision on * whether the inset wants to handle the request \p cmd or not. * The result of this decision is put into \p status. + * + * Every request that is enabled in this method needs to be handled + * in doDispatch(). Normally we have a 1:1 relationship between the + * requests handled in getStatus() and doDispatch(), but there are + * some exceptions: + * - A request that is disabled in getStatus() does not need to + * appear in doDispatch(). It is guaranteed that doDispatch() + * is never called with this request. + * - A few requests are en- or disabled in InsetBase::getStatus(). + * These need to be handled in the doDispatch() methods of the + * derived insets, since InsetBase::doDispatch() has not enough + * information to handle them. */ virtual bool getStatus(LCursor & cur, FuncRequest const & cmd, FuncStatus & status) const; @@ -144,8 +156,8 @@ public: virtual bool idxDelete(idx_type &) { return false; } /// pulls cell after pressing erase virtual void idxGlue(idx_type) {} - // returns list of cell indices that are "between" from and to for - // selection purposes + /// returns list of cell indices that are "between" from and to for + /// selection purposes virtual bool idxBetween(idx_type idx, idx_type from, idx_type to) const; /// to which column belongs a cell with a given index? @@ -388,7 +404,8 @@ public: protected: InsetBase(); InsetBase(InsetBase const &); - // the real dispatcher + /// the real dispatcher. + /// \sa getStatus virtual void doDispatch(LCursor & cur, FuncRequest & cmd); private: virtual std::auto_ptr<InsetBase> doClone() const = 0; diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/insets/insettabular.C lyx-1.4-cvs/src/insets/insettabular.C --- lyx-1.4-clean/src/insets/insettabular.C 2005-03-22 20:53:03.000000000 +0100 +++ lyx-1.4-cvs/src/insets/insettabular.C 2005-04-10 11:08:20.000000000 +0200 @@ -965,6 +967,7 @@ bool InsetTabular::getStatus(LCursor & c return true; // disable these with multiple cells selected + case LFUN_INSET_INSERT: case LFUN_INSERT_CHARSTYLE: case LFUN_INSET_FLOAT: case LFUN_INSET_WIDE_FLOAT: