Index: mythcontrols/actionset.h
===================================================================
--- mythcontrols/actionset.h	(revision 10595)
+++ mythcontrols/actionset.h	(working copy)
@@ -122,6 +122,24 @@
     QStringList getKeys(const ActionID &id) const;
 
     /**
+     * Get all keys that are in use.
+     * @return A string list containing all of the keys.
+     */
+    QStringList * getAllKeys(void) const;
+
+    /**
+     * Get the contexts, in which a key is bound.
+     * @return A string list containing the context names.
+     */
+    QStringList * getKeyContexts(const QString &key) const;
+
+    /**
+     * Get all of the actions that are in use.
+     * @return A string list containing all of the actions.
+     */
+    QStringList *getAllActions(void) const;
+
+    /**
      * @brief Get the description of an action.
      * @param id The action identifier.
      * @return The action description.
@@ -209,6 +227,10 @@
     QMap<QString, ActionList> _keymap;
     QDict<Context> _contexts;
     ActionList _modified;
+
+    /* map from action to the contexts it belongs to */
+    QMap<QString, QStringList> _actions;
+
 };
 
 #endif /* ACTIONSET_H */
Index: mythcontrols/mythcontrols.cpp
===================================================================
--- mythcontrols/mythcontrols.cpp	(revision 10595)
+++ mythcontrols/mythcontrols.cpp	(working copy)
@@ -54,13 +54,6 @@
         return key;
 }
 
-static const QString DisplayToKey(const QString key)
-{
-    if (key.left(1) == "[" && key != "[")
-        return "remote" + key.mid(1,key.length()-2);
-    else
-        return key;
-}
 
 /* comments in header */
 MythControls::MythControls (MythMainWindow *parent, bool& ui_ok)
@@ -69,20 +62,17 @@
     /* Nullify keybindings so the deconstructor knows not to delete it */
     this->key_bindings = NULL;
 
-    /* delete the contents when we're done */
-    m_contexts.setAutoDelete(true);
-    
+    this->view = ActionsByContext;
+
     /* load up the ui components */
     if ((ui_ok = loadUI()))
     {
-        leftType = kContextList;
-        rightType = kActionList;
-
         /* for starters, load this host */
-        loadHost(gContext->GetHostName());
+        key_bindings = new KeyBindings(gContext->GetHostName());
 
         /* update the information */
-        refreshKeyInformation();
+        setView(ActionsByContext, true);
+        refreshInformation();
 
         /* capture the signals we want */
         connect(LeftList, SIGNAL(itemSelected(UIListBtnTypeItem*)),
@@ -162,7 +152,39 @@
 }
 
 
+void MythControls::showButtons(bool shown) const
+{
+    for (size_t i = 0; i < Action::MAX_KEYS; i++)
+    {
+        shown ? ActionButtons[i]->show() : ActionButtons[i]->hide();
+    }
+}
 
+
+/* method description in mythcontrols.h */
+void MythControls::blankButtons(void) const
+{
+        for (size_t i = 0; i < Action::MAX_KEYS; i++)
+            ActionButtons[i]->setText("");
+}
+
+/* method description in mythcontrols.h */
+void MythControls::fillButtons(const QStringList & strings)
+{
+    size_t i = 0, maxstr = Action::MAX_KEYS;
+
+    if (strings.count() < Action::MAX_KEYS)
+        maxstr = strings.count();
+    
+    /* fill existing keys */
+    for (; i < maxstr; i++)
+        ActionButtons[i]->setText(KeyToDisplay(strings[i]));
+
+    /* blank the other ones */
+    for (; i < Action::MAX_KEYS; i++)
+        ActionButtons[i]->setText("");
+}
+
 /* comments in header */
 size_t MythControls::focusedButton(void) const
 {
@@ -172,11 +194,8 @@
     return Action::MAX_KEYS;
 }
 
-
 void MythControls::focusButton(int direction)
 {
-    if (leftType != kContextList || rightType != kActionList)
-        return;
     if (direction == 0)
     {
         focused = ActionButtons[0];
@@ -222,9 +241,61 @@
     focused = focus;
     focus->SetActive(true);
     focus->takeFocus();
-    refreshKeyInformation();
+    /*refreshKeyInformation();*/
+    refreshInformation();
 }
 
+/* method description in mythcontrols.h */
+void MythControls::setView(ViewMode newview, bool force)
+{
+    QStringList *lstrings = NULL, *rstrings = NULL;
+
+    /* Dont set the view to what is already is */
+    if ((newview == this->view) && (force == false))
+      return;
+
+    focused = LeftList;
+    LeftList->takeFocus();
+    
+    this->view = newview;
+
+    switch (newview) {
+    case ActionsByContext:
+        this->showButtons(true);
+        LeftDesc->SetText(tr("Contexts"));
+        RightDesc->SetText(tr("Actions"));
+        lstrings = key_bindings->getContexts();
+        rstrings = key_bindings->getActions((*lstrings)[0]);
+        break;
+    case ActionsByKey:
+        this->showButtons(false);
+        LeftDesc->SetText(tr("Keys"));
+        RightDesc->SetText(tr("Actions"));
+        lstrings = key_bindings->getAllKeys();
+        rstrings = key_bindings->getKeyActions((*lstrings)[0]);
+        break;
+    case ContextsByKey:
+        this->showButtons(false);
+        LeftDesc->SetText(tr("Keys"));
+        RightDesc->SetText(tr("Contexts"));
+        lstrings = key_bindings->getAllKeys();
+        rstrings = key_bindings->getContexts((*lstrings)[0]);
+        break;
+    }
+
+    /* refresh the keys on the left */
+    if (lstrings != NULL) {
+        refreshLeft(lstrings);
+        delete lstrings;
+    }
+
+    /* refresh the keys on the right */
+    if (rstrings != NULL) {
+        refreshRight(rstrings);
+        delete rstrings;
+    }
+}
+
 void MythControls::keyPressEvent(QKeyEvent *e)
 {
     bool handled = false;
@@ -232,6 +303,8 @@
     QStringList actions;
     gContext->GetMainWindow()->TranslateKeyPress("Controls", e, actions);
 
+    
+
     for (size_t i = 0; i < actions.size() && !handled; i++)
     {
         QString action = actions[i];
@@ -254,18 +327,20 @@
         {
             if (focused == LeftList)
                 switchListFocus(RightList, LeftList);
-            else if (focused == RightList)
-                focusButton(0);
-            else {
-                QString key = getCurrentKey();
-                if (!key.isEmpty())
-                {
-                    ActionMenu popup(gContext->GetMainWindow());
-                    int result = popup.getOption();
-                    if (result == ActionMenu::SET) addKeyToAction();
-                    else if (result == ActionMenu::REMOVE) deleteKey();
-                } else // for blank keys, no reason to ask what to do
-                    addKeyToAction();
+            else if (this->view == ActionsByContext) {
+                if (focused == RightList)
+                    focusButton(0);
+                else {
+                    QString key = getCurrentKey();
+                    if (!key.isEmpty())
+                    {
+                        ActionMenu popup(gContext->GetMainWindow());
+                        int result = popup.getOption();
+                        if (result == ActionMenu::SET) addKeyToAction();
+                        else if (result == ActionMenu::REMOVE) deleteKey();
+                    } else // for blank keys, no reason to ask what to do
+                        addKeyToAction();
+                }
             }
         }
         else if (action == "ESCAPE")
@@ -331,42 +406,9 @@
             else if (focused == RightList)
                 RightList->MoveDown(UIListBtnType::MovePage);
         }
-        else if (action == "1")
-        {
-            if (leftType != kContextList || rightType != kActionList)
-            {
-                leftType = kContextList;
-                rightType = kActionList;
-                updateLists();
-                if (focused != LeftList)
-                    switchListFocus(LeftList,
-                                    (focused == RightList) ? RightList : NULL);
-            } else handled = false;
-        }
-        else if (action == "2")
-        {
-            if (leftType != kContextList || rightType != kKeyList)
-            {
-                leftType = kContextList;
-                rightType = kKeyList;
-                updateLists();
-                if (focused != LeftList)
-                    switchListFocus(LeftList,
-                                    (focused == RightList) ? RightList : NULL);
-            } else handled = false;
-        }
-        else if (action == "3")
-        {
-            if (leftType != kKeyList || rightType != kContextList)
-            {
-                leftType = kKeyList;
-                rightType = kContextList;
-                updateLists();
-                if (focused != LeftList)
-                    switchListFocus(LeftList,
-                                    (focused == RightList) ? RightList : NULL);
-            } else handled = false;
-        }
+        else if (action == "1") setView(ActionsByContext);
+        else if (action == "2") setView(ActionsByKey);
+        else if (action == "3") setView(ContextsByKey);
         else handled = false;
     }
 
@@ -381,8 +423,12 @@
 bool MythControls::JumpTo(QKeyEvent *e)
 {
     UIListBtnType *list = NULL;
-    if (focused == LeftList && leftType == kKeyList) list = LeftList;
-    if (focused == RightList && rightType == kKeyList) list = RightList;
+
+    if (view != ActionsByContext) {
+        if (focused == LeftList) list = LeftList;
+        else list = RightList;
+    }
+
     if (!list) return false;
 
     QString key = e->text();
@@ -429,226 +475,158 @@
     refreshRightList();
     RightList->blockSignals(false);
     RightList->refresh();
+    description->SetText("");
 }
 
 void MythControls::rightSelected(UIListBtnTypeItem*)
 {
     RightList->refresh();
-    refreshKeyInformation();
+    refreshInformation();
 }
 
+void MythControls::refreshRight(QStringList * strings)
+{
+    RightList->blockSignals(true);
+    RightList->Reset();
 
+    /* sort the strings */
+    strings->sort();
 
+    for (size_t i = 0; i < strings->size(); i++) {
+        UIListBtnTypeItem *item = new UIListBtnTypeItem(RightList, (*strings)[i]);
+        item->setDrawArrow(false);
+    }
+
+    RightList->blockSignals(false);
+    RightList->refresh();
+}
+
 /* method description in header */
-void MythControls::refreshRightList()
+void MythControls::refreshLeft(QStringList * strings)
 {
-    RightList->Reset();
+    LeftList->blockSignals(true);
+    LeftList->Reset();
 
-    if (LeftList->GetItemCurrent() == NULL)
-        return;
+    /* sort the strings */
+    strings->sort();
 
-    if (leftType == kContextList)
-    {
-        if (rightType == kActionList)
-        {
-            /* add all of the actions to the context list */
-            QString context = LeftList->GetItemCurrent()->text();
-            QStringList *actions = m_contexts[context];
-            if (actions == NULL)
-            {
-                VERBOSE(VB_IMPORTANT, QString("MythControls: Unable to find actions for context %1").arg(context));
-                return;
-            }
-            UIListBtnTypeItem *item;
-            for (size_t i = 0; i < actions->size(); i++)
-                item = new UIListBtnTypeItem(RightList, (*actions)[i]);
-        }
-        else if (rightType == kKeyList)
-        {
-            /* add all of the actions to the context list */
-            QString context = LeftList->GetItemCurrent()->text();
-            BindingList *list = contextKeys[context];
-            if (list == NULL)
-            {
-                VERBOSE(VB_IMPORTANT, QString("MythControls: Unable to find keys for context %1").arg(context));
-                return;
-            }
-            UIListBtnTypeItem *item;
-            for (BindingList::iterator it = list->begin(); it != list->end(); ++it)
-            {
-                binding_t *b = *it;
-                item = new UIListBtnTypeItem(RightList, KeyToDisplay(b->key) + " => " + b->action);
-            }
-        }
-    } else if (leftType == kKeyList && rightType == kContextList)
-    {
-        QString key = DisplayToKey(LeftList->GetItemCurrent()->text());
-        BindingList *list = keyActions[key];
-        if (list == NULL)
-        {
-            VERBOSE(VB_IMPORTANT, QString("MythControls: Unable to find actions for key %1").arg(key));
-            return;
-        }
-        UIListBtnTypeItem *item;
-        BindingList::iterator it = list->begin();
-        binding_t *b = *it;
-        for (size_t i = 0; i < contexts.size(); i++)
-        {
-            QString context = contexts[i];
-            QString action = "<none>";
-            if (b && b->context == context)
-            {
-                action = b->action;
-                ++it;
-                if (it != list->end()) b = *it;
-                else b = NULL;
-            }
-            item = new UIListBtnTypeItem(RightList, context + " => " + action);
-        }
+    for (size_t i = 0; i < strings->size(); i++) {
+        UIListBtnTypeItem *item = new UIListBtnTypeItem(LeftList, (*strings)[i]);
+        item->setDrawArrow(true);
     }
+
+    LeftList->blockSignals(false);
+    LeftList->refresh();
 }
 
 
-/* comments in header */
-void MythControls::refreshKeyInformation()
+/* method description in mythcontrols.h */
+void MythControls::refreshRightList()
 {
-    /* get the description of the current action */
-    QString desc;
+    QStringList *rstrings = NULL;
+    QString lstring = LeftList->GetItemCurrent()->text();
 
-    if (focused == LeftList)
-    {
-        /* blank all keys on the context */
-        for (size_t i = 0; i < Action::MAX_KEYS; i++)
-            ActionButtons[i]->setText("");
+    /* right list, based on values from the left */
+    switch (this->view) {
+    case ActionsByContext:
+        this->showButtons(true);
+        rstrings = key_bindings->getActions(lstring);
+        break;
+    case ActionsByKey:
+        this->showButtons(false);
+        rstrings = key_bindings->getKeyActions(lstring);
+        break;
+    case ContextsByKey:
+        this->showButtons(false);
+        rstrings = key_bindings->getContexts(lstring);
+        break;
     }
-    else if (leftType == kKeyList || rightType == kKeyList)
-    { // Should show appropriate description 
-        QString action = getCurrentAction();
-        QString context = getCurrentContext();
-        /* blank all keys on the context */
-        for (size_t i = 0; i < Action::MAX_KEYS; i++)
-            ActionButtons[i]->setText("");
-        if (!action.isEmpty())
-            {
-    
-            desc = key_bindings->getActionDescription(context, action);
-    
-            BindingList *list = NULL;
-            if (leftType == kKeyList && rightType == kContextList)
-            {
-                QString key = getCurrentKey();
-                list = keyActions[DisplayToKey(key)];
-            }
-            else if (leftType == kContextList && rightType == kKeyList)
-                list = contextKeys[context];
-            if (list)
-            {
-                QString searchKey;
-                if (rightType == kContextList)
-                    searchKey = context;
-                else if (rightType == kActionList)
-                    searchKey = action;
-                else if (rightType == kKeyList)
-                    searchKey = DisplayToKey(getCurrentKey());
-                binding_t *binding = NULL;
-                for (BindingList::iterator it = list->begin(); it != list->end(); ++it)
-                {
-                    binding_t *b = *it;
-                    switch (rightType)
-                    {
-                        case kContextList:
-                            if (b->context == searchKey) binding = b;
-                            break;
-                        case kActionList:
-                            if (b->action == searchKey) binding = b;
-                            break;
-                        case kKeyList:
-                            if (b->key == searchKey) binding = b;
-                            break;
-                    }
-                    if (binding) break;
-                }
-    
-                if (binding)
-                {
-                    if (desc.isEmpty() && context != binding->contextFrom)
-                        desc = key_bindings->getActionDescription(binding->contextFrom, action);
-                    desc += "\n" + tr("Binding comes from %1 context")
-                            .arg(binding->contextFrom);
-                }
-            }
-        }
-    } else {
-        QString context = getCurrentContext();
-        QString action = getCurrentAction();
-        /* set the description */
-        desc = key_bindings->getActionDescription(getCurrentContext(),
-                                                  getCurrentAction());
 
-        /* get the bindings of the current action */
-        QStringList keys = key_bindings->getActionKeys(getCurrentContext(),
-                                                       getCurrentAction());
+    refreshRight(rstrings);
+    delete rstrings;
+}
 
-        size_t i;
 
-        /* fill existing keys */
-        for (i = 0; i < keys.count(); i++)
-            ActionButtons[i]->setText(KeyToDisplay(keys[i]));
+void MythControls::refreshBindingInformation()
+{
+    QString context = LeftList->GetItemCurrent()->text();
+    QString action = RightList->GetItemCurrent()->text();
+    QString desc = key_bindings->getActionDescription(getCurrentContext(),
+                                                      getCurrentAction());
 
-        /* blank the other ones */
-        for (; i < Action::MAX_KEYS; i++)
-            ActionButtons[i]->setText("");
-    }
+    /* get the bindings of the current action */
+    QStringList keys = key_bindings->getActionKeys(getCurrentContext(),
+                                                   getCurrentAction());
 
-    /* set the information */
+    fillButtons(keys);
+
     description->SetText(desc);
 }
 
 
+/* method description in mythcontrols.h */
+void MythControls::refreshInformation()
+{
+    switch (this->view)
+    {
+    case ActionsByContext:
+        if (focused == LeftList) {
+            blankButtons();
+            description->SetText("");
+        }
+        else refreshBindingInformation();
+        break;
+    case ActionsByKey:
+        if (focused == LeftList) description->SetText("");
+        else
+        {
+            QString key = LeftList->GetItemCurrent()->text();
+            QString action = RightList->GetItemCurrent()->text();
+            int pos = RightList->GetItemPos(RightList->GetItemCurrent());
+            QString context = key_bindings->getContext(key, action, pos);
+            QString desc = key_bindings->getActionDescription(context, action);
+            desc += "\n" + tr("Binding comes from %1 context").arg(context);
+            description->SetText(desc);
+        }
+        break;
+    case ContextsByKey:
+        if (focused == LeftList) description->SetText("");
+        else
+        {
+            QString key = LeftList->GetItemCurrent()->text();
+            QString context = RightList->GetItemCurrent()->text();
+            QString action = key_bindings->getAction(key, context);
+            QString desc = action + ": " + key_bindings->getActionDescription(context,
+                                                                              action);
+            description->SetText(desc);
+        }
+        break;
+    }
+}
 
 /* comments in header */
 QString MythControls::getCurrentContext(void) const
 {
-    if (leftType == kContextList)
-        return LeftList->GetItemCurrent()->text();
-    if (focused == LeftList) return "";
-
-    QString desc = RightList->GetItemCurrent()->text();
-    int loc = desc.find(" => ");
-    if (loc == -1) return ""; // Should not happen
-    if (rightType == kContextList) return desc.left(loc);
-    else return desc.mid(loc+4);
+    if (view == ActionsByContext) return LeftList->GetItemCurrent()->text();
+    else if ((view == ContextsByKey) && (focused == RightList))
+        return RightList->GetItemCurrent()->text();
+    else return "";
 }
 
 /* comments in header */
 QString MythControls::getCurrentAction(void) const
 {
-    if (leftType == kActionList)
-        return LeftList->GetItemCurrent()->text();
-    if (focused == LeftList) return "";
 
-    QString desc = RightList->GetItemCurrent()->text();
-    if (leftType == kContextList && rightType == kActionList)
-        return desc;
-    int loc = desc.find(" => ");
-    if (loc == -1) return ""; // Should not happen
-    if (rightType == kActionList) return desc.left(loc);
-    else
-    {
-        QString rv = desc.mid(loc+4);
-        if (rv == "<none>") return "";
-        else return rv;
-    }
+    if (((view == ActionsByContext) && (focused != LeftList)) ||
+        ((view == ActionsByKey) && (focused == RightList)))
+        return RightList->GetItemCurrent()->text();
+    else return "";
 }
 
 /* comments in header */
 QString MythControls::getCurrentKey(void) const
 {
-    if (leftType == kKeyList)
-        return LeftList->GetItemCurrent()->text();
-    if (focused == LeftList) return "";
-
-    if (leftType == kContextList && rightType == kActionList)
+    if (view == ActionsByContext)
     {
         QString context = getCurrentContext();
         QString action = getCurrentAction();
@@ -657,52 +635,17 @@
         if (b < keys.count()) return keys[b];
         else return "";
     }
-
-    QString desc = RightList->GetItemCurrent()->text();
-    int loc = desc.find(" => ");
-    if (loc == -1) return ""; // Should not happen
-    if (rightType == kKeyList) return desc.left(loc);
-    else return desc.mid(loc+4);
+    else return LeftList->GetItemCurrent()->text();
 }
 
-
 /* comments in header */
-void MythControls::loadHost(const QString & hostname) {
-
-    /* create the key bindings and the tree */
-    key_bindings = new KeyBindings(hostname);
-    contexts = *key_bindings->getContexts();
-
-    keys.clear();
-
-    /* Alphabetic order, but jump and global at the top  */
-    contexts.sort();
-    contexts.remove(JUMP_CONTEXT);
-    contexts.remove(GLOBAL_CONTEXT);
-    contexts.insert(contexts.begin(), 1, GLOBAL_CONTEXT);
-    contexts.insert(contexts.begin(), 1, JUMP_CONTEXT);
-
-    QStringList *actions;
-    for (size_t i = 0; i < contexts.size(); i++)
-    {
-        actions = key_bindings->getActions(contexts[i]);
-        actions->sort();
-        m_contexts.insert(contexts[i], actions);
-    }
-
-    refreshKeyBindings();
-    updateLists();
-}
-
-
-
-/* comments in header */
 void MythControls::deleteKey()
 {
     // This code needs work to support deleteKey in any mode exc. Context/Action
     QString context = getCurrentContext();
     QString key = getCurrentKey();
     QString action = getCurrentAction();
+
     if (context.isEmpty() || key.isEmpty() || action.isEmpty())
     {
         InvalidBindingPopup popup(gContext->GetMainWindow());
@@ -710,40 +653,17 @@
         return;
     }
 
-    BindingList *list = keyActions[key];
-    binding_t *binding = NULL;
-    for (BindingList::iterator it = list->begin(); it != list->end(); ++it)
+    if (view == ActionsByContext)
     {
-        binding_t *b = *it;
-        if (b->context == context) binding = b;
-    }
-    if (!binding)
-    {
-        InvalidBindingPopup popup(gContext->GetMainWindow());
-        popup.getOption();
-        return;
-    }
-
-    if (binding->contextFrom != context)
-    {
-        ConfirmMenu popup(gContext->GetMainWindow(), tr("Delete this key binding from context %1?").arg(binding->contextFrom));
+        ConfirmMenu popup(gContext->GetMainWindow(), tr("Delete this key binding from context %1?").arg(context));
         if (popup.getOption() != ConfirmMenu::CONFIRM) return;
-    } else {
-        ConfirmMenu popup(gContext->GetMainWindow(), tr("Delete this binding?"));
-        if (popup.getOption() != ConfirmMenu::CONFIRM) return;
+        else
+        {
+            key_bindings->removeActionKey(context, action, key);
+        }
     }
 
-    if (!key_bindings->removeActionKey(binding->contextFrom, action, key))
-    {
-        InvalidBindingPopup popup(gContext->GetMainWindow());
-        popup.getOption();
-        return;
-    }
-
-    // refreshing everything is overkill.  I tried incrementally updating, but the
-    // code was ugly.  Since this is quick in my experience, overkill away!
-    refreshKeyBindings();
-    refreshKeyInformation();
+    refreshInformation();
 }
 
 /* method description in header */
@@ -780,7 +700,6 @@
 /* method description in header */
 void MythControls::addKeyToAction(void)
 {
-    // This code needs work to support deleteKey in any mode exc. Context/Action
     /* grab a key from the user */
     KeyGrabPopupBox *kg = new KeyGrabPopupBox(gContext->GetMainWindow());
     int result = kg->ExecPopup(kg,SLOT(cancel()));
@@ -817,209 +736,9 @@
     else
         key_bindings->addActionKey(context, action, key);
 
-    refreshKeyBindings();
-    refreshKeyInformation();
+    refreshInformation();
 }
 
-
-
-void MythControls::addBindings(QDict<binding_t> &bindings,
-                               const QString &context,
-                               const QString &contextParent, int bindlevel)
-{
-    QStringList *actions = key_bindings->getActions(context);
-
-    for (size_t i = 0; i < actions->size(); i++)
-    {
-        QString action = (*actions)[i];
-        QStringList keys = key_bindings->getActionKeys(context, action);
-
-        for (size_t j = 0; j < keys.size(); j++)
-        {
-            QString key = keys[j];
-
-            binding_t *b = bindings.find(key);
-            if (!b) 
-            {
-                b = new(binding_t);
-                b->key = key;
-                b->action = action;
-                b->context = contextParent;
-                b->contextFrom = context;
-                b->bindlevel = bindlevel;
-                bindings.insert(key, b);
-            }
-            else if (b->bindlevel == bindlevel)
-            {
-                b->action += ", " + action;
-            }
-        }
-    }
-}
-
-BindingList *MythControls::getKeyBindings(const QString &context)
-{
-    QStringList keys;
-    QDict<binding_t> bindings;
-    bindings.clear();
-
-    for (size_t i = 0; i < contexts.size(); i++)
-        addBindings(bindings, contexts[i], context, i);
-
-
-    for (QDictIterator<binding_t> it(bindings); it.current(); ++it)
-    {
-        QString key = it.currentKey();
-        keys.append(key);
-    }
-
-    sortKeyList(keys);
-
-    BindingList *retval = new BindingList;
-    retval->clear();
-
-    for (QStringList::Iterator kit = keys.begin(); kit != keys.end(); ++kit)
-    {
-        QString key = *kit;
-        retval->append(bindings[key]);
-    }
-    retval->setAutoDelete(true);
-    return retval;
-}
-
-void MythControls::refreshKeyBindings()
-{
-    contextKeys.clear();
-    keyActions.clear();
-    for (size_t i = 0; i < contexts.size(); i++)
-    {
-        QString context = contexts[i];
-        BindingList *list = getKeyBindings(context);
-        contextKeys.insert(context, list);
-        for (BindingList::iterator it = list->begin(); it != list->end(); ++it)
-        {
-            binding_t *b = *it;
-            BindingList *list = keyActions.find(b->key);
-            if (!list)
-            {
-                list = new BindingList;
-                list->clear();
-                keyActions.insert(b->key, list);
-            }
-            keys.append(b->key);
-            list->append(b);
-        }
-    }
-    contextKeys.setAutoDelete(true);
-    keyActions.setAutoDelete(true);
-
-    sortKeyList(keys);
-}
-
-void MythControls::sortKeyList(QStringList &keys)
-{
-    QStringList t;
-    t.clear();
-
-    for ( QStringList::Iterator it = keys.begin(); it != keys.end(); ++it )
-    {
-        QString key = *it;
-
-        QString keydesc = "3 ";
-        if (key.left(6) == "remote")
-        {
-            keydesc = "0 ";
-        }
-        else if (key.length() == 1)
-        {
-            switch (key[0].category())
-            {
-                case QChar::Letter_Uppercase:
-                    keydesc = "2 ";
-                    break;
-                case QChar::Number_DecimalDigit:
-                    keydesc = "1 ";
-                    break;
-                default:
-                    keydesc = "5 ";
-                    break;
-            }
-        }
-        else if (key.find("+", 1) != -1)
-            keydesc = "4 ";
-
-        t.push_back(keydesc + key);
-    }
-    t.sort();
-
-    QString prev = "";
-
-    keys.clear();
-    for (QStringList::Iterator kit = t.begin(); kit != t.end(); ++kit)
-    {
-        QString cur = (*kit).mid(2);
-        if (cur != prev) 
-        {
-            keys.append(cur);
-            prev = cur;
-        }
-    }
-}
-
-QString MythControls::getTypeDesc(ListType type)
-{
-    switch (type)
-    {
-        case kContextList:
-            return tr("Contexts");
-            break;
-        case kKeyList:
-            return tr("Keys");
-            break;
-        case kActionList:
-            return tr("Actions");
-            break;
-        default:
-            return "";
-    }
-}
-
-void MythControls::updateLists()
-{
-    RightList->blockSignals(true);
-    LeftList->blockSignals(true);
-    LeftList->Reset();
-    if (leftType == kContextList)
-    {
-        UIListBtnTypeItem *item;
-        for (size_t i = 0; i < contexts.size(); i++)
-        {
-            item = new UIListBtnTypeItem(LeftList, contexts[i]);
-            item->setDrawArrow(true);
-        }
-    } else if (leftType == kKeyList)
-    {
-        UIListBtnTypeItem *item;
-        for (size_t i = 0; i < keys.size(); i++)
-        {
-            QString key = KeyToDisplay(keys[i]);
-            item = new UIListBtnTypeItem(LeftList, key);
-            item->setDrawArrow(true);
-        }
-    }
-    refreshRightList();
-    RightList->blockSignals(false);
-    LeftList->blockSignals(false);
-    LeftList->refresh();
-    RightList->refresh();
-
-    if (LeftDesc != NULL)
-        LeftDesc->SetText(getTypeDesc(leftType));
-    if (RightDesc != NULL)
-        RightDesc->SetText(getTypeDesc(rightType));
-}
-
-
 #endif /* MYTHCONTROLS_CPP */
 
 /* vim: set expandtab tabstop=4 shiftwidth=4: */
Index: mythcontrols/keybindings.cpp
===================================================================
--- mythcontrols/keybindings.cpp	(revision 10595)
+++ mythcontrols/keybindings.cpp	(working copy)
@@ -48,8 +48,51 @@
     retrieveJumppoints();
 }
 
+QStringList * KeyBindings::getKeyActions(const QString &key) const
+{
+    QStringList *strings;
+    const ActionList & al = actionset.getActions(key);
 
+    if (al.size() > 0) strings = new QStringList();
+    else return NULL;
 
+    for (size_t i = 0; i < al.size(); i++)
+    {
+        strings->push_back(al[i].action());
+    }
+
+    return strings;
+}
+
+
+QString KeyBindings::getContext(const QString & key, const QString & action,
+                                size_t anum) const
+{
+    /* The cases where unknown is returned should never happen.  If
+     * you see an unknown context, do not approach.  Call the police
+     * immediatly. */
+    const ActionList &al = actionset.getActions(key);
+    int offset = al.size() - anum;
+
+    if (offset < 0) return "UNKNOWN";
+    else if (al[anum].action() != action) return "UNKNOWN";
+    if (anum < al.size()) return al[anum].context();
+    else return "UNKNOWN";
+}
+
+QString KeyBindings::getAction(const QString & key, const QString & context) const
+{
+    const ActionList &al = actionset.getActions(key);
+
+    for (size_t i = 0; i < al.size(); i++)
+    {
+        if (al[i].context() == context) return al[i].action();
+    }
+
+    return "UNKNOWN";
+}
+
+
 ActionID * KeyBindings::conflicts(const QString & context_name,
                                   const QString & key, int &level) const
 {
Index: mythcontrols/actionset.cpp
===================================================================
--- mythcontrols/actionset.cpp	(revision 10595)
+++ mythcontrols/actionset.cpp	(working copy)
@@ -154,8 +154,36 @@
     }
 }
 
+QStringList * ActionSet::getAllKeys(void) const {
+    return new QStringList(this->_keymap.keys());
+}
 
 
+QStringList * ActionSet::getAllActions(void) const {
+    return new QStringList(this->_actions.keys());
+}
+
+
+QStringList * ActionSet::getKeyContexts(const QString &key) const
+{
+    QStringList *strings = NULL;
+    const ActionList &ids = _keymap[key];
+
+    if (ids.size() == 0) return NULL;
+
+    strings = new QStringList();
+
+    for (size_t i = 0; i < ids.size(); i++)
+    {
+        if (!strings->contains(ids[i].context())) {
+            strings->push_back(ids[i].context());
+        }
+    }
+
+    return strings;
+}
+
+
 /* method description in header */
 bool ActionSet::addAction(const ActionID &id, const QString &description,
                           const QString &keys)
@@ -173,6 +201,11 @@
         /* add the action into the dict */
         _contexts[id.context()]->insert(id.action(), a);
 
+        /* if the action doesn't already exist, then add it */
+        QStringList &contexts = _actions[id.action()];
+        if (!contexts.contains(id.context()))
+            contexts.push_back(id.context());
+
         /* get the actions keys */
         const QStringList &keys = a->getKeys();
         for (size_t i = 0; i < keys.count(); i++)
@@ -182,7 +215,31 @@
             ActionList &ids = _keymap[keys[i]];
 
             /* add this action id to the list of actions bound to this key */
-            ids.push_back(id);
+            if (ids.size() == 0) ids.push_back(id);
+            else
+            {
+                bool added = false;
+                ActionList::iterator it;
+
+                /* keep list sorted by action, then by context.  You
+                 * must sort this stuff because multiple actions from
+                 * different contexts can be added. Otherwise, we get
+                 * into trouble in keybindings.cpp and
+                 * mythcontrols.cpp when trying to delete based on
+                 * action (displayed by key) */
+                for (it = ids.begin(); (it != ids.end()) && (added == false); ++it)
+                {
+                    if ((QString::compare(id.action(), (*it).action()) < 0) ||
+                        ((QString::compare(id.action(), (*it).action()) == 0) &&
+                         (QString::compare(id.context(), (*it).context()) < 0))
+                        )
+                    {
+                        ids.insert(it, id);
+                        added = true;
+                    }
+                }
+                if (added == false) ids.push_back(id);
+            }
         }
 
         return true;
@@ -225,7 +282,6 @@
 }
 
 
-
 const QString & ActionSet::getDescription(const ActionID &id) const
 {
     Context *c;
Index: mythcontrols/mythcontrols.h
===================================================================
--- mythcontrols/mythcontrols.h	(revision 10595)
+++ mythcontrols/mythcontrols.h	(working copy)
@@ -93,6 +93,10 @@
     
 protected:
 
+
+    /** The view mode */
+    typedef enum { ActionsByContext, ActionsByKey, ContextsByKey } ViewMode;
+
     /**
      * @brief Load up UI.
      * @return true if all UI elements were loaded successfully,
@@ -105,27 +109,66 @@
     bool loadUI();
 
     /**
+     * Show or hide the buttons at the bottom.
+     *
+     * @param shown Should the buttons be shown?
+     */
+    void showButtons(bool shown) const;
+
+    /**
+     * Blank the text in the bottom buttons.
+     */
+    void blankButtons(void) const;
+
+    /**
+     * Fill the buttons with the strings in a string list.
+     * @param strings The string list.
+     */
+    void fillButtons(const QStringList & strings);
+
+    /**
+     * Set the viewing mode of the plugin.
+     *
+     * @param view The view mode.
+     * @param force Force the view to be set (or reset)
+     */
+    void setView(ViewMode newview, bool force=false);
+
+    /**
      * @brief The key press handler.
      * @param e The key event.
      */
     void keyPressEvent(QKeyEvent *e);
 
     /**
-     * @brief Redraw the key information
-     *
-     * Updates the list of keys that are shown and the description of
-     * the action.
+     * Refresh the action description and key binding buttons.
      */
-    void refreshKeyInformation();
+    void refreshBindingInformation();
 
     /**
-     * @brief Load the appropriate actions into the action list.
-     * @param context The context, from which actions will be
-     * displayed.
+     * @brief Redraw the information at the bottom.
      */
-    void refreshRightList(void);
+    void refreshInformation();
 
     /**
+     * Refresh the right list.
+     * @param strings The strings to place in the right list.
+     */
+    void refreshRight(QStringList * strings);
+
+    /**
+     * Refresh the left list.
+     * @param string The strings to place in the left list.
+     */
+    void refreshLeft(QStringList * strings);
+
+    /**
+     * @brief Load the appropriate information into the right list.
+     * @param strings The strings to load into the right list.
+     */
+    void refreshRightList();
+
+    /**
      * @brief Redisplay both the left and right lists and fix focus
      */
     void updateLists(void);
@@ -183,10 +226,10 @@
 
 private slots:
 
-/**
- * @brief Add a key to the currently selected action.
- */
-void addKeyToAction(void);
+	/**
+     * @brief Add a key to the currently selected action.
+     */
+	void addKeyToAction(void);
 
     /**
      * @brief Delete the currently active key.
@@ -239,16 +282,16 @@
     KeyBindings *key_bindings;
     LayerSet *container;
 
-    QStringList contexts; ///< sorted list of contexts
-    QStringList keys; ///< sorted list of keys
 
-    QDict<QStringList> m_contexts; ///< actions for a given context
     QDict<BindingList> contextKeys; ///< key bindings for a given context
     QDict<BindingList> keyActions; ///< actions in each context for a given key
 
     typedef enum { kContextList, kKeyList, kActionList } ListType;
+
     ListType leftType, rightType;
 
+    ViewMode view;
+
     QString getTypeDesc(ListType type);
 
 };
Index: mythcontrols/keybindings.h
===================================================================
--- mythcontrols/keybindings.h	(revision 10595)
+++ mythcontrols/keybindings.h	(working copy)
@@ -30,6 +30,7 @@
 #include "actionid.h"
 #include "actionset.h"
 
+
 /**
  * @class KeyBindings.
  * @brief Information about the current keybindings.
@@ -63,10 +64,19 @@
     inline const QString & getHostname() const { return this->_hostname; }
 
     /**
+     * Determine the context belonging to the key and action
+     *
+     * @param action The action.
+     * @param anum The action number (in the list of all of a keys actions).
+     *
+     * This method falls apart if the actionset class doesn't sort it
+     * the actions lists in the _kemap variable.
+     */
+    QString getContext(const QString & key, const QString & action, size_t anum) const;
+
+    /**
      * @brief Get a list of the context names.
      * @return A list of the context names.
-     * @note The returned list is a copy and can be modified without
-     * side-effects.
      */
     inline QStringList * getContexts() const
     {
@@ -74,6 +84,16 @@
     }
 
     /**
+     * Get the contexts in which a key is bound.
+     * @param key The key.
+     * @return A string list containing the context names.
+     */
+    inline QStringList * getContexts(const QString & key) const
+    {
+        return actionset.getKeyContexts(key);
+    }
+
+    /**
      * @brief Get a list of the actions in a context.
      * @param context The name of the context.
      * @return A list of action (names) for the target context.
@@ -86,16 +106,28 @@
     }
 
     /**
+     * Get the action bound to a key in a particular context.
+     *
+     * @param key The key.
+     * @param context The context.
+     * @return The action.
+     */
+    QString getAction(const QString & key, const QString & context) const;
+
+    /**
+     * Get all bound keys.
+     * @return A string list of the bound keys.
+     */
+    inline QStringList * getAllKeys() const { return actionset.getAllKeys(); }
+
+    /**
      * @brief Get a list of the actions in a context.
      * @param context The name of the context.
      * @return A list of action (names) for the target context.
      * @note Store this instead of calling repeatedly.  Every time you
      * do, ActionSet has to iterate over all contexts and actions.
      */
-    inline void getKeyActions(const QString &key, ActionList &list) const
-    {
-        list = actionset.getActions(key);
-    }
+    QStringList * getKeyActions(const QString &key) const;
 
     /**
      * @brief Get an action's keys.
@@ -187,7 +219,7 @@
      * @param key The key to remove.
      * @return true if the key was removed, or false if it was not.
      *
-     * Unless the action is manditory there is only one key in the
+     * Unless the action is manditory and there is only one key in the
      * action, this method should return true.
      */
     bool removeActionKey(const QString & context_name,
