Index: mythcontrols/mythcontrols/mythcontrols.cpp
===================================================================
--- mythcontrols/mythcontrols/mythcontrols.cpp	(revision 6810)
+++ mythcontrols/mythcontrols/mythcontrols.cpp	(working copy)
@@ -50,7 +50,7 @@
 
 /**
  * @class ConflictResolver
- * @brief A MythDialog that notifies the user of conflicts. 
+ * @brief A MythDialog that notifies the user of conflicts.
  */
 class ConflictResolver : public MythPopupBox
 {
@@ -392,6 +392,23 @@
     context_tree = new GenericTree(hostname, 0, false);
     QStringList context_names = key_bindings->getContexts();
 
+    /* Alphabetic order, except... */
+    context_names.sort();
+
+    /* jump points go first*/
+    if (context_names.contains(JUMP_CONTEXT))
+    {
+	context_names.remove(JUMP_CONTEXT);
+	context_names.insert(context_names.begin(), 1, JUMP_CONTEXT);
+    }
+
+    /* followed by global */
+    if (context_names.contains(GLOBAL_CONTEXT))
+    {
+	context_names.remove(GLOBAL_CONTEXT);
+	context_names.insert(++(context_names.begin()), 1, GLOBAL_CONTEXT);
+    }
+
     for (size_t i = 0; i < context_names.size(); i++) {
 
 	GenericTree *context_node = new GenericTree(context_names[i], i, true);
@@ -400,6 +417,7 @@
 	context_tree->addNode(context_node);
 
 	QStringList action_names = key_bindings->getActions(context_names[i]);
+	action_names.sort();
 
 	/* add all actions to the context */
 	for (size_t j = 0; j < action_names.size(); j++)
@@ -412,6 +430,7 @@
 
 
 
+/* comments in header */
 void MythControls::killPopup()
 {
     if (this->popup == NULL) return;
@@ -461,10 +480,21 @@
     QStringList keys = key_bindings->getActionKeys(context, action);
     if (b < keys.count())
     {
+	cerr << "DELETING" << endl;
 	if (!key_bindings->removeActionKey(context, action, keys[b]))
 	{
-	    this->popup = new ConflictResolver(gContext->GetMainWindow());
-	    this->popup->ExecPopup(this, SLOT(killPopup()));
+	  /* create the popup */
+	  popup = new MythPopupBox(gContext->GetMainWindow(),
+				   "conflictresolver");
+
+	  QString warning = "This action is manditory and needs at least one "
+	    "key bound to it.  Instead, try rebinding with another key.";
+	    
+	  popup->addLabel("Manditory Action", MythPopupBox::Large, false);
+	  popup->addLabel(warning, MythPopupBox::Small, true);
+
+	  /*this->popup = new ConflictResolver(gContext->GetMainWindow());*/
+	  this->popup->ExecPopup(this, SLOT(killPopup()));
 	}
 	else refreshKeyInformation();
     }
@@ -472,6 +502,43 @@
 
 
 
+/* method description in header */
+bool MythControls::resolveConflict(ActionID *conflict, int level)
+{
+    MythMainWindow *window = gContext->GetMainWindow();
+
+    /* prevent a fatal binding */
+    if (level == KeyBindings::Error)
+    {
+	this->popup = new MythPopupBox(window, "conflictresolver");
+	QString warning;
+	warning = "This action is manditory and needs at least one key "
+	    "bound to it.  Instead, try rebinding with another key.";
+	    
+	popup->addLabel("Manditory Action", MythPopupBox::Large, false);
+	popup->addLabel(warning, MythPopupBox::Small, true);
+
+	this->popup->ExecPopup();
+	return false;
+    }
+    else
+    {
+	/* warn the user that this could conflict */
+	QString message = "This kebinding may conflict with ";
+	message += conflict->action() + " in the " + conflict->context();
+	message += " context.  Do you want to bind it anyways?";
+
+	if (MythPopupBox::show2ButtonPopup(window, "Conflict Warning",
+					   message,"Bind Key","Cancel",0))
+	    return false;
+    }
+
+    return true;
+}
+
+
+
+/* method description in header */
 void MythControls::addKeyToAction(void)
 {
     size_t b = focusedButton();
@@ -483,35 +550,27 @@
     /* having got the key, kill the key grabber */
     killPopup();
 
+    /* dont bother if its the same key */
+    if (keys[b] == newkey) return;
+
+    bool bind = true;
+    int level;
+
+    /* get the potential conflict */
+    if ((conflict = key_bindings->conflicts(context, newkey, level)))
+	bind = resolveConflict(conflict, level);
+
+    delete conflict;
+
+    /* dont bind */
+    if (!bind) return;
+
+    /* */
     if (b < keys.count())
-    {
-	/* dont replace with the same key */
-	if (keys[b] != newkey) {
-	    if ((conflict = key_bindings->conflicts(context, newkey)))
-	    {
-		this->popup = new ConflictResolver(gContext->GetMainWindow(),
-						   conflict);
-		this->popup->ExecPopup(this, SLOT(killPopup()));
-	    }
-	    else key_bindings->replaceActionKey(context,action,newkey,keys[b]);
-	}
-    }
-    else {
-	if ((conflict = key_bindings->conflicts(context, newkey)))
-	{
-	    this->popup = new ConflictResolver(gContext->GetMainWindow(),
-					       conflict);
-	    this->popup->ExecPopup(this, SLOT(killPopup()));
-	}
-	else key_bindings->addActionKey(context, action, newkey);
-    }
+	key_bindings->replaceActionKey(context,action,newkey,keys[b]);
+    else
+	key_bindings->addActionKey(context, action, newkey);
 
-    /* delete the conflict and hide the popup*/
-    if (conflict) {
-	delete conflict;
-	killPopup();
-    }
-
     refreshKeyInformation();
 }
 
Index: mythcontrols/mythcontrols/keybindings.cpp
===================================================================
--- mythcontrols/mythcontrols/keybindings.cpp	(revision 6810)
+++ mythcontrols/mythcontrols/keybindings.cpp	(working copy)
@@ -49,7 +49,7 @@
 
 
 ActionID * KeyBindings::conflicts(const QString & context_name,
-				  const QString & key) const
+				  const QString & key, int &level) const
 {
     const ActionList &ids = actionset.getActions(key);
 
@@ -60,8 +60,19 @@
     /* check the contexts of the other bindings */
     for (size_t i = 0; i < ids.count(); i++)
     {
-	if (ids[i].context() == JUMP_CONTEXT) return new ActionID(ids[i]);
-	else if (ids[i].context() == context_name) return new ActionID(ids[i]);
+	/* jump points, then global, then the same context */
+	if (ids[i].context() == JUMP_CONTEXT) {
+	    level = KeyBindings::Error;
+	    return new ActionID(ids[i]);
+	}
+	else if (ids[i].context() == context_name) {
+	    level = KeyBindings::Error;
+	    return new ActionID(ids[i]);
+	}
+	else if (ids[i].context()==GLOBAL_CONTEXT) {
+	    level = KeyBindings::Warning;
+	    return new ActionID(ids[i]);
+	}
     }
 
     /* no conflicts */
@@ -70,6 +81,23 @@
 
 
 
+/* method description in header */
+bool KeyBindings::removeActionKey(const QString & context_name,
+		     const QString & action_name,
+		     const QString & key) {
+
+    ActionID id(context_name, action_name);
+
+    /* dont remove the last manditory binding */
+    if (getManditoryBindings().contains(id)&&(actionset.getKeys(id).count()<2))
+	return false;
+    else
+	return this->actionset.remove(id,key);
+}
+
+
+
+/* method description in header */
 void KeyBindings::commitAction(const ActionID & id)
 {
 
Index: mythcontrols/mythcontrols/mythcontrols.h
===================================================================
--- mythcontrols/mythcontrols/mythcontrols.h	(revision 6810)
+++ mythcontrols/mythcontrols/mythcontrols.h	(working copy)
@@ -125,6 +125,13 @@
      */
     size_t focusedButton(void) const;
 
+    /**
+     * @brief Resolve a potential conflict.
+     * @return true if the conflict should be bound, otherwise, false
+     * is returned.
+     */
+    bool resolveConflict(ActionID *conflict, int level);
+
  private slots:
 
      /**
Index: mythcontrols/mythcontrols/keybindings.h
===================================================================
--- mythcontrols/mythcontrols/keybindings.h	(revision 6810)
+++ mythcontrols/mythcontrols/keybindings.h	(working copy)
@@ -29,7 +29,6 @@
 #include "actionid.h"
 #include "actionset.h"
 
-
 /**
  * @class KeyBindings.
  * @brief Information about the current keybindings.
@@ -43,6 +42,14 @@
  public:
 
   /**
+   * @brief Levels of conflict 
+   * @li None: Does not conflict
+   * @li Potential: May conflict.
+   * @li Fatal: Frontend will become inoperable.
+   */
+  enum ConflictLevels { Warning, Error};
+
+  /**
    * @brief Create a new KeyBindings instance.
    * @param hostname The host for which to create the key bindings.
    */
@@ -111,15 +118,23 @@
    * @brief Determine if adding a key would cause a conflict.
    * @param context_name The name of the context.
    * @param key The key to add.
+   * @param level The level of conflict.  Check this if the return
+   * value is not NULL
    * @return true if adding the key would cause a conflict.
    *
    * Conflicts occur if:
    * @li the key is a jump point, but is bound elsewhere
    * @li the key is already bound to a jumppoint.
+   * @li the key is bound to something in the global context.
    * @li the key is bound to something else in the specified context
+   *
+   * If the method does not return NULL, check the value given to
+   * level.  Warnings can be ignored (at the users disgression), but
+   * errors should be prevented no matter what.  If they dont like it,
+   * they can learn SQL.
    */
   ActionID * conflicts(const QString & context_name,
-		       const QString & key) const;
+		       const QString & key, int &level) const;
 
   /**
    * @brief Replace a key in an action.
@@ -152,9 +167,7 @@
    */
   bool removeActionKey(const QString & context_name,
 		       const QString & action_name,
-		       const QString & key) {
-      return this->actionset.remove(ActionID(context_name, action_name),key);
-  }
+		       const QString & key);
 
   /**
    * @brief Set the manditory bindings to their defaults.
Index: mythcontrols/mythcontrols/mythcontrols.pro
===================================================================
--- mythcontrols/mythcontrols/mythcontrols.pro	(revision 6810)
+++ mythcontrols/mythcontrols/mythcontrols.pro	(working copy)
@@ -1,7 +1,7 @@
 include ( ../../settings.pro )
 
 TEMPLATE = lib
-CONFIG += plugin thread warn_on debug
+CONFIG += plugin thread
 TARGET = mythcontrols
 target.path = $${PREFIX}/lib/mythtv/plugins
 INSTALLS += target
