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:

Reply via email to