Index: mythcontrols/mythcontrols/mythcontrols.cpp
===================================================================
--- mythcontrols/mythcontrols/mythcontrols.cpp	(revision 6860)
+++ mythcontrols/mythcontrols/mythcontrols.cpp	(working copy)
@@ -36,70 +36,39 @@
 
 /* MythTV includes */
 #include <mythtv/mythcontext.h>
-#include <mythtv/uitypes.h>
 #include <mythtv/mythdialogs.h>
-#include <mythtv/dialogbox.h>
-#include <mythtv/xmlparse.h>
 #include <mythtv/themedmenu.h>
-#include <mythtv/mythdbcon.h>
 
 using namespace std;
 
 #include "mythcontrols.h"
 #include "keygrabber.h"
 
-/**
- * @class ConflictResolver
- * @brief A MythDialog that notifies the user of conflicts. 
- */
-class ConflictResolver : public MythPopupBox
-{
 
-public:
-    ConflictResolver(MythMainWindow *window, ActionID *conflict)
-	: MythPopupBox(window, "conflictresolver")
-    {
-	QString warning = "The key you have chosen is already bound to "
-	    + conflict->action() + " in the " + conflict->context()
-	    + " context; please rebind it before binding this key.";
-	
-	addLabel("Action Conflict", Large, false);
-	addLabel(warning, Small, true);
-    }
 
-
-    ConflictResolver(MythMainWindow *window)
-	: MythPopupBox(window,"conflictresolver")
-    {
-
-	QString warning;
-	warning = "This action is manditory and needs at least one key bound ";
-	warning += "to it.  Instead, try rebinding with another key.";
-	    
-	addLabel("Manditory Action", Large, false);
-	addLabel(warning, Small, true);
-    }
-};
-
-
 /* comments in header */
-MythControls::MythControls (MythMainWindow *parent, const char *name) 
+MythControls::MythControls (MythMainWindow *parent, const char *name,
+			    bool & ui_ok) 
     :MythThemedDialog(parent, "controls", "controls-", name)
 {
+    /* Nullify keybindings so the deconstructor knows not to delete it */
+    this->key_bindings = NULL;
+
     /* load up the ui components */
-    loadUI();
+    if ((ui_ok = loadUI()))
+    {
+	/* for starters, load this host */
+	loadHost(gContext->GetHostName());
 
-    /* for starters, load this host */
-    loadHost(gContext->GetHostName());
-
-    /* update the information */
-    refreshKeyInformation();
+	/* update the information */
+	refreshKeyInformation();
+    }
 }
 
 
 
 /* comments in header */
-MythControls::~MythControls() { delete(this->key_bindings); }
+MythControls::~MythControls() { delete this->key_bindings; }
 
 
 
@@ -109,49 +78,44 @@
     /* the return value of the method */
     bool retval = true;
 
-    /* by default, there is no popup */
-    popup = NULL;
-
     /* Get the UI widgets that we need to work with */
-    description = getUITextType("description");
-    if (!description) {
-	VERBOSE(VB_ALL, "Unable to load action_description");
+    if ((description = getUITextType("description")) == NULL)
+    {
+	VERBOSE(VB_ALL, "MythControls: Unable to load action_description");
 	retval = false;
     }
 
-    control_tree_list=getUIManagedTreeListType("controltree");
-    if (!control_tree_list)
+    if ((control_list=getUIListTreeType("controltree")) == NULL)
     {
-	VERBOSE(VB_ALL, "Unable to load controltree");
+	VERBOSE(VB_ALL, "MythControls: Unable to load controltree");
 	retval = false;
     }
     else {
 
 	/* set some parameters for the tree */
-	control_tree_list->showWholeTree(true);
-	control_tree_list->colorSelectables(true);
-	focused=control_tree_list;
+	focused=control_list;
+	control_list->setActive(true);
     }
 
     /* Check that all the buttons are there */
     if ((action_buttons[0] = getUITextButtonType("action_one")) == NULL)
     {
-	VERBOSE(VB_ALL, "Unable to load first action button");
+	VERBOSE(VB_ALL, "MythControls: Unable to load first action button");
 	retval = false;
     }
     else if ((action_buttons[1] = getUITextButtonType("action_two")) == NULL)
     {
-	VERBOSE(VB_ALL, "Unable to load second action button");
+	VERBOSE(VB_ALL, "MythControls: Unable to load second action button");
 	retval = false;
     }
     else if ((action_buttons[2] = getUITextButtonType("action_three")) == NULL)
     {
-	VERBOSE(VB_ALL, "Unable to load thrid action button");
+	VERBOSE(VB_ALL, "MythControls: Unable to load thrid action button");
 	retval = false;
     }
     else if ((action_buttons[3] = getUITextButtonType("action_four")) == NULL)
     {
-	VERBOSE(VB_ALL, "Unable to load fourth action button");
+	VERBOSE(VB_ALL, "MythControls: Unable to load fourth action button");
 	retval = false;
     }
 
@@ -177,7 +141,8 @@
     {
 	focused = action_buttons[0];
 	action_buttons[0]->takeFocus();
-	control_tree_list->looseFocus();
+	control_list->looseFocus();
+	control_list->setActive(false);
     }
     else
     {
@@ -220,46 +185,32 @@
 
 	if (action == "MENU" || action == "INFO")
 	{
-	    /* bring up the menu */
-	    this->actionMenu();
+	    OptionsMenu popup(gContext->GetMainWindow());
+	    if (popup.getOption() == OptionsMenu::SAVE) save();
 	}
 	else if (action == "SELECT")
 	{
-	    if (focused == control_tree_list)
+	    if (focused == control_list)
 	    {
-		if (control_tree_list->getActiveBin() == 1)
-		    control_tree_list->pushDown();
-		else
-		    focusButton(0);
+		if (control_list->getDepth() == 0) control_list->MoveRight();
+		else focusButton(0);
 	    }
 	    else {
-		popup = new MythPopupBox(gContext->GetMainWindow(),"decision");
-		popup->addLabel(tr("Modify Action"),MythPopupBox::Large,false);
-		popup->addButton(tr("Set Binding"),this, SLOT(captureKey()));
-		popup->addButton(tr("Remove Binding"),this, SLOT(deleteKey()));
-		popup->addButton(tr("Cancel"), this,
-				 SLOT(killPopup()))->setFocus();
-		popup->ShowPopup();
+		ActionMenu popup(gContext->GetMainWindow());
+		int result = popup.getOption();
+		if (result == ActionMenu::SET) addKeyToAction();
+		else if (result == ActionMenu::REMOVE) deleteKey();
 	    }
 	}
 	else if (action == "ESCAPE")
 	{
-	    if (focused == control_tree_list)
+	    if (focused == control_list)
 	    {
 		/* ask the user to save if there are unsaved changes*/
 		if (key_bindings->hasChanges())
 		{
-		    popup = new MythPopupBox(gContext->GetMainWindow(),
-					     "unsaged");
-		    popup->addLabel(tr("Unsaged Changes"),
-				    MythPopupBox::Large,
-				    false);
-
-		    popup->addLabel(tr("Would you like to save now?"));
-		    popup->addButton(tr("Save"), this,
-				     SLOT(save()))->setFocus();
-		    popup->addButton(tr("Exit"), this, SLOT(killPopup()));
-		    popup->ExecPopup(this, SLOT(killPopup()));
+		    UnsavedMenu popup(gContext->GetMainWindow());
+		    if (popup.getOption() == UnsavedMenu::SAVE) save();
 		}
 
 		/* let the user exit */
@@ -269,61 +220,51 @@
 	    {
 		/* take focus away from the button */
 		focused->looseFocus();
-		control_tree_list->takeFocus();
-		focused = control_tree_list;
+		focused = control_list;
+		control_list->takeFocus();
+		control_list->setActive(true);
 	    }
 	}
-	else if (action == "UP")
+	else if ((action == "UP") && (focused == control_list))
 	{
-	    if (focused == control_tree_list)
-	    {
-		control_tree_list->moveUp();
-		refreshKeyInformation();
-	    }
-	    else focusButton(-1);
+	    control_list->MoveUp();
+	    refreshKeyInformation();
 	}
-	else if (action == "DOWN")
+	else if ((action == "DOWN") && (focused == control_list))
 	{
-	    if (focused == control_tree_list)
-	    {
-		control_tree_list->moveDown();
-		refreshKeyInformation();
-	    }
-	    else focusButton(1);
+	    control_list->MoveDown();
+	    refreshKeyInformation();
 	}
 	else if (action == "LEFT")
 	{
-	    if (focused == control_tree_list)
+	    if (focused==control_list)
 	    {
-		control_tree_list->popUp();
+		control_list->MoveLeft();
 		refreshKeyInformation();
 	    }
 	    else focusButton(-1);
 	}
 	else if (action == "RIGHT")
 	{
-	    if (focused == control_tree_list)
+	    if (focused == control_list)
 	    {
-		control_tree_list->pushDown();
-		refreshKeyInformation();
+		if (control_list->getDepth() == 0)
+		{
+		    control_list->MoveRight();
+		    refreshKeyInformation();
+		}
 	    }
 	    else focusButton(1);
 	}
-	else if (action == "PAGEUP")
+	else if ((action == "PAGEUP") && (focused == control_list))
 	{
-	    if (focused == control_tree_list)
-	    {
-		control_tree_list->pageUp();
-		refreshKeyInformation();
-	    }
+	    control_list->MoveUp(UIListTreeType::MovePage);
+	    refreshKeyInformation();
 	}
-	else if (action == "PAGEDOWN")
+	else if ((action == "PAGEDOWN") && (focused == control_list))
 	{
-	    if (focused == control_tree_list)
-	    {
-		control_tree_list->pageDown();
-		refreshKeyInformation();
-	    }
+	    control_list->MoveDown(UIListTreeType::MovePage);
+	    refreshKeyInformation();
 	}
 	else handled = false;
     }
@@ -363,10 +304,11 @@
 /* comments in header */
 QString MythControls::getCurrentContext(void) const
 {
-    if (control_tree_list->getActiveBin() == 2)
-	return control_tree_list->getCurrentNode()->getParent()->getString();
-    else if (control_tree_list->getActiveBin() == 1)
-	return control_tree_list->getCurrentNode()->getString();
+    UIListGenericTree *current = control_list->GetCurrentPosition();
+    if (control_list->getDepth() == 1 )
+	return current->getParent()->getString();
+    else if (control_list->getDepth() == 0)
+	return current->getString();
     else
 	return "";
 }
@@ -376,8 +318,8 @@
 /* comments in header */
 QString MythControls::getCurrentAction(void) const
 {
-    if (control_tree_list->getActiveBin() == 2)
- 	return control_tree_list->getCurrentNode()->getString();
+    if (control_list->getDepth() == 1)
+ 	return control_list->GetCurrentPosition()->getString();
     else
 	return "";
 }
@@ -389,73 +331,43 @@
 
     /* create the key bindings and the tree */
     key_bindings = new KeyBindings(hostname);
-    context_tree = new GenericTree(hostname, 0, false);
     QStringList context_names = key_bindings->getContexts();
 
-    for (size_t i = 0; i < context_names.size(); i++) {
+    /* Alphabetic order, but jump and global at the top  */
+    context_names.sort();
+    context_names.remove(JUMP_CONTEXT);
+    context_names.remove(GLOBAL_CONTEXT);
+    context_names.insert(context_names.begin(), 1, GLOBAL_CONTEXT);
+    context_names.insert(context_names.begin(), 1, JUMP_CONTEXT);
 
-	GenericTree *context_node = new GenericTree(context_names[i], i, true);
+    UIListGenericTree *root = new UIListGenericTree(NULL, "ROOT");
 
-	/* add the context to the tree of contexts */
-	context_tree->addNode(context_node);
+    for (size_t i = 0; i < context_names.size(); i++)
+    {
+	UIListGenericTree *context_node;
+	context_node = new UIListGenericTree(root, context_names[i],
+					     context_names[i]);
 
 	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++)
-	    context_node->addNode(action_names[j], j, true);
-
-	/* put the data in the tree */
-	control_tree_list->assignTreeData(context_node);
+	{
+	    new UIListGenericTree(context_node, action_names[j],
+				  action_names[j]);
+	}
     }
-}
 
-
-
-void MythControls::killPopup()
-{
-    if (this->popup == NULL) return;
-
-    this->popup->hide();
-    delete this->popup;
-    this->popup = NULL;
-    setActiveWindow();
+    control_list->SetTree(root);
+    control_list->setActive(true);
 }
 
 
 
 /* comments in header */
-void MythControls::actionMenu()
-{
-    if (popup != NULL) return;
-
-    popup = new MythPopupBox(gContext->GetMainWindow(), "editaction");
-    popup->addButton(tr("Save Changes"), this, SLOT(save()));
-    popup->addButton(tr("Cancel"),this, SLOT(killPopup()))->setFocus();
-    popup->ShowPopup(this, SLOT(killPopup()));
-}
-
-
-
-void MythControls::captureKey()
-{
-    killPopup();
-
-    KeyGrabPopupBox * kg = new KeyGrabPopupBox(gContext->GetMainWindow());
-
-    kg->addOKButton(kg->addButton(tr("OK"), this, SLOT(addKeyToAction())));
-    kg->addButton(tr("Cancel"), this, SLOT(killPopup()));
-    this->popup = (MythPopupBox*)kg;
-    this->popup->ShowPopup(this,SLOT(killPopup()));
-}
-
-
-
 void MythControls::deleteKey()
 {
-
-    killPopup();
-
     size_t b = focusedButton();
     QString action = getCurrentAction(), context = getCurrentContext();
     QStringList keys = key_bindings->getActionKeys(context, action);
@@ -463,8 +375,8 @@
     {
 	if (!key_bindings->removeActionKey(context, action, keys[b]))
 	{
-	    this->popup = new ConflictResolver(gContext->GetMainWindow());
-	    this->popup->ExecPopup(this, SLOT(killPopup()));
+	    InvalidBindingPopup popup(gContext->GetMainWindow());
+	    popup.getOption();
 	}
 	else refreshKeyInformation();
     }
@@ -472,52 +384,77 @@
 
 
 
+/* method description in header */
+bool MythControls::resolveConflict(ActionID *conflict, int level)
+{
+    MythMainWindow *window = gContext->GetMainWindow();
+
+    /* prevent a fatal binding */
+    if (level == KeyBindings::Error)
+    {
+	InvalidBindingPopup popup(gContext->GetMainWindow(),
+				  conflict->action(),
+				  conflict->context());
+	popup.getOption();
+	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)
 {
+    /* grab a key from the user */
+    KeyGrabPopupBox *kg = new KeyGrabPopupBox(gContext->GetMainWindow());
+    int result = kg->ExecPopup(kg,SLOT(cancel()));
+    QString key = kg->getCapturedKey();
+    delete kg;
+
+    /* go no further if canceled */
+    if (result == 0) return;
+
+    /* get the keys for the selected action */
     size_t b = focusedButton();
-    QString newkey = ((KeyGrabPopupBox*)popup)->getCapturedKeyEvent();
     QString action = getCurrentAction(), context = getCurrentContext();
     QStringList keys = key_bindings->getActionKeys(context, action);
+
+    /* dont bother rebinding the same key */
+    if (keys[b] == key) return;
+
+    bool bind = false;
+    int level;
+
+    /* get the potential conflict */
     ActionID *conflict = NULL;
+    if ((conflict = key_bindings->conflicts(context, key, level)))
+	bind = resolveConflict(conflict, level);
 
-    /* having got the key, kill the key grabber */
-    killPopup();
+    delete conflict;
 
+    /* dont bind if we shouldn't bind */
+    if (!bind) return;
+
+    /* finally bind or rebind a key to the action */
     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, key, keys[b]);
+    else
+	key_bindings->addActionKey(context, action, key);
 
-    /* delete the conflict and hide the popup*/
-    if (conflict) {
-	delete conflict;
-	killPopup();
-    }
-
     refreshKeyInformation();
 }
 
-void MythControls::save(void) {
-    key_bindings->commitChanges();
-    killPopup();
-}
-
 #endif /* MYTHCONTROLS_CPP */
Index: mythcontrols/mythcontrols/keybindings.cpp
===================================================================
--- mythcontrols/mythcontrols/keybindings.cpp	(revision 6860)
+++ 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)
 {
 
@@ -169,8 +197,14 @@
     for (query.next(); query.isValid(); query.next())
     {
 	ActionID id(JUMP_CONTEXT, query.value(0).toString());
-	this->actionset.addAction(id,query.value(1).toString(),
-				  query.value(2).toString());
+
+	if (query.value(1).toString().isEmpty())
+	{
+	    actionset.addAction(id, query.value(0).toString(),
+				query.value(2).toString());
+	}
+	else actionset.addAction(id,query.value(1).toString(),
+				 query.value(2).toString());
     }
 }
 
Index: mythcontrols/mythcontrols/mythcontrols.h
===================================================================
--- mythcontrols/mythcontrols/mythcontrols.h	(revision 6860)
+++ mythcontrols/mythcontrols/mythcontrols.h	(working copy)
@@ -23,11 +23,8 @@
 #ifndef MYTHCONTROLS_H
 #define MYTHCONTROLS_H
 
-#include <stdexcept>
-
 #include <mythtv/mythdialogs.h>
-#include <mythtv/mythwidgets.h>
-#include <mythtv/uitypes.h>
+#include <mythtv/uilistbtntype.h>
 
 #include "keybindings.h"
 
@@ -47,8 +44,11 @@
      * @param parent The main myth window.
      * @param name The name of this window?  I dunno, none of the docs
      * say.
+     * @param ui_ok Will be set according to weather the UI was
+     * correctly loaded.
      */
-    MythControls(MythMainWindow *parent, const char *name=0);
+    MythControls(MythMainWindow *parent, const char *name=0,
+		 bool & ui_ok=false);
 
     /**
      * @brief Delete the myth controls object.
@@ -56,17 +56,6 @@
     ~MythControls();
 
     /**
-     * @brief Load up UI.
-     * @return true if all UI elements were loaded successfully,
-     * otherwise false it returned.
-     *
-     * This method grabs all of the UI "thingies" that are needed by
-     * mythcontrols.  If this method returns false, the plugin should
-     * exit since it will probably just core dump.
-     */
-    bool loadUI();
-
-    /**
      * @brief Get the currently selected context string.
      * @return The currently selected context string.
      *
@@ -85,6 +74,17 @@
  protected:
 
     /**
+     * @brief Load up UI.
+     * @return true if all UI elements were loaded successfully,
+     * otherwise false it returned.
+     *
+     * This method grabs all of the UI "thingies" that are needed by
+     * mythcontrols.  If this method returns false, the plugin should
+     * exit since it will probably just core dump.
+     */
+    bool loadUI();
+
+    /**
      * @brief The key press handler.
      * @param e The key event.
      */
@@ -99,11 +99,6 @@
     void refreshKeyInformation();
 
     /**
-     * @brief Launches the action menu.
-     */
-    void actionMenu();
-
-    /**
      * @brief Load the settings for a particular host.
      * @param hostname The host to load settings for.
      */
@@ -125,42 +120,37 @@
      */
     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:
 
      /**
       * @brief Add a key to the currently selected action.
       */
-     void addKeyToAction();
+     void addKeyToAction(void);
 
      /**
-      * @brief Capture a key press using the key grabber.
-      */
-     void captureKey();
-
-     /**
       * @brief Delete the currently active key.
       */
      void deleteKey();
 
      /**
-      * @brief Kill the currently visbile popup window.
-      */
-     void killPopup();
-
-     /**
       * @brief Save the settings.
       */
-     void save();
+     inline void save(void) { key_bindings->commitChanges(); }
 
  private:
 
      UIType *focused;
-     GenericTree * context_tree;
-     UIManagedTreeListType * control_tree_list;
+     UIListTreeType *control_list;
      UITextType *description;
      UITextButtonType * action_buttons[Action::MAX_KEYS];
      KeyBindings *key_bindings;
-     MythPopupBox *popup;
 };
 
 
Index: mythcontrols/mythcontrols/keybindings.h
===================================================================
--- mythcontrols/mythcontrols/keybindings.h	(revision 6860)
+++ 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/keygrabber.cpp
===================================================================
--- mythcontrols/mythcontrols/keygrabber.cpp	(revision 6860)
+++ mythcontrols/mythcontrols/keygrabber.cpp	(working copy)
@@ -27,6 +27,7 @@
 
 #include "keygrabber.h"
 
+#include <mythtv/mythcontext.h>
 
 
 KeyGrabPopupBox::KeyGrabPopupBox(MythMainWindow *window)
@@ -36,6 +37,10 @@
     this->has_captured = false;
     addLabel("Press A Key", Large, false);
     key_label = addLabel("Waiting for key press", Small, false);
+
+    ok_button = this->addButton(tr("OK"), this, SLOT(acceptBinding()));
+    this->addButton(tr("Cancel"), this, SLOT(cancel()));
+
     this->grabKeyboard();
 }
 
@@ -82,6 +87,57 @@
     /* accept events while we are capturing */
     if (this->is_capturing) e->accept();
     else MythPopupBox::keyPressEvent(e);
+}
 
-    cout << QString(QKeySequence(Qt::UNICODE_ACCEL & e->key())) << endl;
+InvalidBindingPopup::InvalidBindingPopup(MythMainWindow *window)
+    : MythPopupBox(window, "invalidbinding")
+{
+    QString warning = "This action is manditory and needs at least one key"
+	" bound to it.  Instead, try rebinding with another key.";
+    addLabel("Manditory Action", Large, false);
+    addLabel(warning, Small, true);
 }
+
+
+
+InvalidBindingPopup::InvalidBindingPopup(MythMainWindow *window,
+					 const QString &action,
+					 const QString &context)
+    : MythPopupBox(window, "invalidbinding")
+{
+    QString message = "This kebinding conflicts with ";
+    message += action + " in the " + context;
+    message += " context.";
+
+    addLabel("Conflicting Binding", Large, false);
+    addLabel(message, Small, true);
+}
+
+
+
+OptionsMenu::OptionsMenu(MythMainWindow *window)
+    : MythPopupBox(window, "optionmenu")
+{
+    addLabel(tr("Options"), Large, false);
+    addButton(tr("Save"), this, SLOT(save()));
+    addButton(tr("Cancel"), this, SLOT(cancel()))->setFocus();
+}
+    
+
+ActionMenu::ActionMenu(MythMainWindow *window)
+    : MythPopupBox(window, "actionmenu")
+{
+    addLabel(tr("Modify Action"), Large, false);
+    addButton(tr("Set Binding"), this, SLOT(set()));
+    addButton(tr("Remove Binding"), this, SLOT(remove()));
+    addButton(tr("Cancel"), this, SLOT(cancel()))->setFocus();
+}
+
+UnsavedMenu::UnsavedMenu(MythMainWindow *window)
+    : MythPopupBox(window, "unsavedmenu")
+{
+    addLabel(tr("Unsaged Changes"), Large, false);
+    addLabel(tr("Would you like to save now?"));
+    addButton(tr("Save"), this, SLOT(save()))->setFocus();
+    addButton(tr("Exit"), this, SLOT(cancel()));
+}
Index: mythcontrols/mythcontrols/keygrabber.h
===================================================================
--- mythcontrols/mythcontrols/keygrabber.h	(revision 6860)
+++ mythcontrols/mythcontrols/keygrabber.h	(working copy)
@@ -44,17 +44,27 @@
     KeyGrabPopupBox(MythMainWindow * window);
 
     /**
-     * @brief Add the OK button.
-     * @param button The button that will be hilighed once a key has
-     * been captured.
+     * @brief Get the string containing the captured key event.
      */
-    inline void addOKButton(QButton *button) { ok_button = button; }
+    inline QString getCapturedKey() { return this->captured_key_event; }
 
+ public slots:
+
     /**
-     * @brief Get the string containing the captured key event.
+     * @brief Accept the captured keybinding.
+     *
+     * The QString provided in the constructor will be set to the
+     * captured key value.
      */
-    inline QString getCapturedKeyEvent() { return this->captured_key_event; }
+    inline void acceptBinding(void) { done(1); }
 
+    /**
+     * @brief Reject the captured key binding.
+     *
+     * The QString provided in the constructor will be set to NULL.
+     */
+    inline void cancel(void) { done(0); }
+
  protected:
 
     /**
@@ -77,3 +87,159 @@
     QButton *ok_button;
     QLabel *key_label;
 };
+
+
+/**
+ * @class InvalidBindingPopup
+ * @brief Tells the user that they are being bad!!!
+ */
+class InvalidBindingPopup : public MythPopupBox
+{
+    Q_OBJECT;
+
+ public:
+
+    /**
+     * @brief Create a popup that explains that they are removing a
+     * critical key binding.
+     * @param window The main myth window.
+     */
+    InvalidBindingPopup(MythMainWindow *window);
+
+    /**
+     * @brief Tell the user that the binding conflicts with another
+     * action.
+     */
+    InvalidBindingPopup(MythMainWindow *window, const QString &action,
+			const QString &context);
+
+    /**
+     * @brief Execute the error popup
+     */
+    inline int getOption(void) { return ExecPopup(this,SLOT(finish())); }
+
+ protected slots:
+    /**
+     * @brief Close the popup.
+     */
+    inline void finish(void) { done(0); }
+};
+
+
+/**
+ * @class OptionsMenu
+ * @brief A popup containing a list of options.
+ */
+class OptionsMenu : public MythPopupBox
+{
+
+    Q_OBJECT;
+
+ public:
+
+    enum actons { SAVE, CANCEL };
+
+    /**
+     * @brief Create a new action window.
+     */
+    OptionsMenu(MythMainWindow *window);
+
+    /**
+     * @brief Execute the option popup.
+     */
+    inline int getOption(void) { return ExecPopup(this,SLOT(cancel())); }
+
+ public slots:
+
+    /**
+     * @brief Slot to connect to when the save button is pressed.
+     */
+    inline void save(void) { done(OptionsMenu::SAVE); }
+
+    /**
+     * @brief Slot to connect to when the cancel button is pressed.
+     */
+    inline void cancel(void) { done(OptionsMenu::CANCEL); }
+
+};
+
+
+
+/**
+ * @class ActionMenu
+ * @brief A popup listing ways to modify an action.
+ */
+class ActionMenu : public MythPopupBox
+{
+
+        Q_OBJECT;
+
+ public:
+
+    enum actons { SET, REMOVE, CANCEL };
+
+    /**
+     * @brief Create a new action window.
+     */
+    ActionMenu(MythMainWindow *window);
+
+    /**
+     * @brief Execute the option popup.
+     */
+    inline int getOption(void) { return ExecPopup(this,SLOT(cancel())); }
+
+ public slots:
+
+    /**
+     * @brief Slot to connect to when the set button is pressed.
+     */
+    inline void set(void) { done(ActionMenu::SET); }
+
+    /**
+     * @brief Slot to connect to when the remove button is pressed.
+     */
+    inline void remove(void) { done(ActionMenu::REMOVE); }
+
+    /**
+     * @brief Slot to connect to when the cancel button is pressed.
+     */
+    inline void cancel(void) { done(ActionMenu::CANCEL); }
+
+};
+
+/**
+ * @class OptionsMenu
+ * @brief A popup containing a list of options.
+ */
+class UnsavedMenu : public MythPopupBox
+{
+
+    Q_OBJECT;
+
+ public:
+
+    enum actons { SAVE, EXIT };
+
+    /**
+     * @brief Create a new action window.
+     */
+    UnsavedMenu(MythMainWindow *window);
+
+    /**
+     * @brief Execute the option popup.
+     */
+    inline int getOption(void) { return ExecPopup(this,SLOT(cancel())); }
+
+ public slots:
+
+    /**
+     * @brief Slot to connect to when the save button is pressed.
+     */
+    inline void save(void) { done(UnsavedMenu::SAVE); }
+
+    /**
+     * @brief Slot to connect to when the cancel button is pressed.
+     */
+    inline void cancel(void) { done(UnsavedMenu::EXIT); }
+
+};
Index: mythcontrols/mythcontrols/mythcontrols.pro
===================================================================
--- mythcontrols/mythcontrols/mythcontrols.pro	(revision 6860)
+++ 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
Index: mythcontrols/mythcontrols/main.cpp
===================================================================
--- mythcontrols/mythcontrols/main.cpp	(revision 6860)
+++ mythcontrols/mythcontrols/main.cpp	(working copy)
@@ -26,45 +26,15 @@
 using namespace std;
 
 #include "mythcontrols.h"
+#include <mythtv/mythdialogs.h>
 
 
-
 /**
- * @name Plugin API
- *
- * The following methods are required by all MythTV plugins.
+ * @brief Initializes the plugin.
+ * @param libversion The mythtv library version.
+ * @return zero if all is well, otherwise, less than zero
  */
-//@{
-extern "C" {
-
-  /**
-   * @brief Called by mythtv to initialize the plugin.
-   * @param libversion Used to make sure that the requried version of
-   * the library is being used.
-   * @return I dont really know what difference your return values makes.
-   * @todo Find out the difference this return values makes.
-   */
-  int mythplugin_init(const char *libversion);
-
-  /**
-   * @brief Runs the plugin.
-   * @return I dont really know what difference your return values makes.
-   * @todo Find out the difference this return values makes.
-   */
-  int mythplugin_run(void);
-
-  /**
-   * @brief Called to configure the plugin.
-   * @return I dont really know what difference your return values makes.
-   * @todo Find out the difference this return values makes.
-   */
-  int mythplugin_config(void);
-}
-//@}
-
-
-/* documented above */
-int mythplugin_init(const char *libversion)
+extern "C" int mythplugin_init(const char *libversion)
 {
     if (!gContext->TestPopupVersion("mythcontrols", libversion,
 				    MYTH_BINARY_VERSION)) return -1;
@@ -73,28 +43,42 @@
 
 
 
-/* documented above */
-int mythplugin_run (void)
+/**
+ * @brief Runs the plugin.
+ * @return zero if all is well, otherwise, less than zero
+ */
+extern "C" int mythplugin_run (void)
 {
-    MythControls controls(gContext->GetMainWindow(), "controls");
+    bool uiloaded;
+    MythMainWindow *window = gContext->GetMainWindow();
 
+    /* create the keybinding plugin.  uiloaded will be set to false
+     * if the theme was not correct */
+    MythControls controls(window, "controls", uiloaded);
+
     /* if the UI is successfully loaded, just giv'er*/
-    if (controls.loadUI())
+    if (uiloaded)
     {
 	controls.exec();
 	return 0;    
     }
     else
     {
-	VERBOSE(VB_ALL, "Unable to load theme, exiting");
+	MythPopupBox::showOkPopup(window, "Theme Error", "Could not load the "
+				  "keybinding plugin's theme.  Check the "
+				  "console for detailed output.");
+
 	return -1;
     }
 }
 
 
 
-/* documented above*/
-int mythplugin_config (void) { return 0; }
+/**
+ * @brief Configures the plugin.
+ * @return zero.
+ */
+extern "C" int mythplugin_config (void) { return 0; }
 
 
 
Index: mythcontrols/mythcontrols/actionset.cpp
===================================================================
--- mythcontrols/mythcontrols/actionset.cpp	(revision 6860)
+++ mythcontrols/mythcontrols/actionset.cpp	(working copy)
@@ -22,8 +22,6 @@
 #ifndef ACTIONSET_CPP
 #define ACTIONSET_CPP
 
-#include <iostream>
-
 #include <qmap.h>
 #include <qdict.h>
 #include <qvaluelist.h>
@@ -36,7 +34,6 @@
 #include "actionset.h"
 
 
-
 /* method description in header */
 bool ActionSet::add(const ActionID &id, const QString &key)
 {
@@ -54,8 +51,8 @@
 	    ids.push_back(id);
 	    this->modify(id);	
 	    return true;
-	} else cerr << "Key not added" << endl;
-    } else cerr << "No action" << endl;
+	}
+    }
 
     return false;
 }
Index: mythcontrols/mythcontrols/controls-ui.xml
===================================================================
--- mythcontrols/mythcontrols/controls-ui.xml	(revision 6860)
+++ mythcontrols/mythcontrols/controls-ui.xml	(working copy)
@@ -3,152 +3,90 @@
 
  <window name="controls">
 
-   <font name="selected" face="Arial">
-     <color>#ffffff</color>
-     <size>14</size>
-     <bold>yes</bold>
-   </font>
+  <font name="active" face="Arial">
+   <color>#ffffff</color>
+   <size>14</size>
+   <bold>yes</bold>
+  </font>
 
-   <font name="active" face="Arial">
-     <color>#aaaaaa</color>
-     <size>14</size>
-     <bold>yes</bold>
-   </font>
+  <font name="inactive" face="Arial">
+   <color>#9999cc</color>
+   <size>14</size>
+   <bold>yes</bold>
+  </font>
 
-   <font name="inactive" face="Arial">
-     <color>#9999cc</color>
-     <size>14</size>
-     <bold>yes</bold>
-   </font>
+  <font name="keys" face="Arial">
+   <color>#000000</color>
+   <size>18</size>
+   <shadow>1,1</shadow>
+   <bold>yes</bold>
+  </font>
 
-   <font name="selectable" face="Arial">
-     <color>#8cdeff</color>
-     <size>14</size>
-     <bold>yes</bold>
-   </font>
+  <font name="info" face="Arial">
+   <color>#ffffff</color>
+   <size>18</size>
+   <shadow>1,1</shadow>
+   <bold>yes</bold>
+  </font>
 
-   <font name="labels" face="Arial">
-     <color>#ffffff</color>
-     <size>16</size>
-     <shadow>1,1</shadow>
-     <bold>yes</bold>
-   </font>
+  <font name="infotitle" face="Arial">
+   <color>#ffffff</color>
+   <size>24</size>
+   <shadow>10,10</shadow>
+   <bold>yes</bold>
+  </font>
 
-   <font name="keys" face="Arial">
-     <color>#000000</color>
-     <size>18</size>
-     <shadow>1,1</shadow>
-     <bold>yes</bold>
-   </font>
+  <container name="controls">
+   <area>20,20,780,380</area>
+   <listtreearea name="controltree" draworder="0">
+    <area>0,0,760,360</area>
+    <listsize>0,0,370,360</listsize>
+    <leveloffset>15</leveloffset>
+    <gradient type="unselected" start="#505050" end="#000000" alpha="100"/>
+    <gradient type="selected" start="#52CA38" end="#349838" alpha="255"/>
+    <fcnfont name="active" function="active"/>
+    <fcnfont name="inactive" function="inactive"/>
+   </listtreearea>
+  </container>
 
-   <font name="info" face="Arial">
-     <color>#ffffff</color>
-     <size>18</size>
-     <shadow>1,1</shadow>
-     <bold>yes</bold>
-   </font>
+  <container name="keys">
+   <area>20,400,780,180</area>
 
-   <font name="infotitle" face="Arial">
-     <color>#ffffff</color>
-     <size>24</size>
-     <shadow>10,10</shadow>
-     <bold>yes</bold>
-   </font>
+   <textbutton name="action_one" draworder="0">
+    <position>20,20</position>
+    <image function="on" filename="kb-button-on.png"/>
+    <image function="off" filename="kb-button-off.png"/>
+    <font>keys</font>
+   </textbutton>
 
-   <font name="message" face="Arial">
-     <color>#ffffff</color>
-     <size>16</size>
-     <shadow>1,1</shadow>
-     <bold>yes</bold>
-   </font>
+   <textbutton name="action_two" draworder="0">
+    <position>200,20</position>
+    <image function="on" filename="kb-button-on.png"/>
+    <image function="off" filename="kb-button-off.png"/>
+    <font>keys</font>
+   </textbutton>
 
-   <container name="controls">
-     <area>0,0,800,350</area>
+   <textbutton name="action_three" draworder="0">
+    <position>390,20</position>
+    <image function="on" filename="kb-button-on.png"/>
+    <image function="off" filename="kb-button-off.png"/>
+    <font>keys</font>
+   </textbutton>
 
-     <managedtreelist name="controltree" draworder="1" bins="2">
-       <area>0,40,800,310</area>
+   <textbutton name="action_four" draworder="0">
+    <position>580,20</position>
+    <image function="on" filename="kb-button-on.png"/>
+    <image function="off" filename="kb-button-off.png"/>
+    <font>keys</font>
+   </textbutton>
 
-       <image function="selectionbar" filename="bar.png"/>
-       <image function="uparrow" filename="scrollarrow-up.png"/>
-       <image function="downarrow" filename="scrollarrow-dn.png"/>
-       <image function="leftarrow" filename="scrollarrow-left.png"/>
-       <image function="rightarrow" filename="scrollarrow-right.png"/>
+   <textarea name="description" draworder="1" allign="left">
+    <font>info</font>
+    <area>30,100,740,140</area>
+    <multiline>yes</multiline>
+   </textarea>
 
-       <bin number="1">
-	 <area>30,14,190,250</area>
-	 <fcnfont name="active" function="active"/>
-	 <fcnfont name="inactive" function="inactive"/>
-	 <fcnfont name="selected" function="selected"/>
-	 <fcnfont name="selectable" function="selectable"/>     
-       </bin>
+  </container>
 
-       <bin number="2">
-	 <area>240,14,530,265</area>
-	 <fcnfont name="active" function="active"/>
-	 <fcnfont name="inactive" function="inactive"/>
-	 <fcnfont name="active" function="selected"/>
-	 <fcnfont name="selectable" function="selectable"/>     
-       </bin>
-
-     </managedtreelist>
-
-     <image name="showinglines" draworder="2" fleximage="yes">
-       <filename>showings.png</filename>
-       <position>0,0</position>
-     </image>
-
-   </container>
-
-   <container name="keys">
-     <area>0,300,800,320</area>
-
-     <textarea name="infotitle" draworder="0">
-       <font>infotitle</font>
-       <area>282,20,236,40</area>
-       <value>Key Bindings</value>
-     </textarea>
-
-     <textbutton name="action_one" draworder="0">
-       <position>20,100</position>
-       <image function="on" filename="kb-button-on.png"/>
-       <image function="off" filename="kb-button-off.png"/>
-       <font>keys</font>
-     </textbutton>
-
-     <textbutton name="action_two" draworder="0">
-       <position>200,100</position>
-       <image function="on" filename="kb-button-on.png"/>
-       <image function="off" filename="kb-button-off.png"/>
-       <font>keys</font>
-     </textbutton>
-
-     <textbutton name="action_three" draworder="0">
-       <position>390,100</position>
-       <image function="on" filename="kb-button-on.png"/>
-       <image function="off" filename="kb-button-off.png"/>
-       <font>keys</font>
-     </textbutton>
-
-     <textbutton name="action_four" draworder="0">
-       <position>580,100</position>
-       <image function="on" filename="kb-button-on.png"/>
-       <image function="off" filename="kb-button-off.png"/>
-       <font>keys</font>
-     </textbutton>
-
-     <image name="actionlines" draworder="1" allign="left">
-       <filename>cr-lines.png</filename>
-       <position>0,0</position>
-     </image>
-
-     <textarea name="description" draworder="1" allign="left">
-       <font>info</font>
-       <area>30,180,740,140</area>
-       <multiline>yes</multiline>
-     </textarea>
-
-     
-   </container>
-
  </window>
 </mythuitheme>
