Ticket #2078: 2078-v1.patch

File 2078-v1.patch, 36.9 KB (added by danielk, 17 years ago)

Cleanup of ui_and_logic_again.diff

  • mythcontrols/actionset.h

     
    5858    QStringList GetActionStrings(const QString &context_name) const;
    5959    QString     GetKeyString(const ActionID &id) const;
    6060    QStringList GetKeys(const ActionID &id) const;
     61    QStringList GetContextKeys(const QString &context_name) const;
     62    QStringList GetAllKeys(void) const;
    6163    QString     GetDescription(const ActionID &id) const;
    6264    const ActionList& GetActions(const QString &key) const;
    6365    /// \brief Returns the appropriate container of modified actions
  • mythcontrols/keygrabber.h

     
    9494    Q_OBJECT
    9595
    9696  public:
    97     enum actions { kSave, kCancel, };
     97    enum actions { kSave, kChangeView, kCancel, };
    9898
    9999    /// \brief Create a new action window. Does not pop-up menu.
    100100    OptionsMenu(MythMainWindow *window);
     
    103103    int GetOption(void) { return ExecPopup(this,SLOT(Cancel())); }
    104104
    105105  public slots:
    106     void Save(void)     { done(OptionsMenu::kSave);   }
    107     void Cancel(void)   { done(OptionsMenu::kCancel); }
     106    void Save(void)       { done(OptionsMenu::kSave);       }
     107    void ChangeView(void) { done(OptionsMenu::kChangeView); }
     108    void Cancel(void)     { done(OptionsMenu::kCancel);     }
    108109};
    109110
    110111
  • mythcontrols/mythcontrols.cpp

     
    22/**
    33 * @file mythcontrols.cpp
    44 * @author Micah F. Galizia <mfgalizi@csd.uwo.ca>
    5  * @brief Main header for mythcontrols.
     5 * @brief Main mythcontrols class.
    66 *
    77 * Note that the keybindings are fetched all at once, and cached for
    88 * this host.  This avoids pelting the database everytime the user
     
    4040#include "mythcontrols.h"
    4141#include "keygrabber.h"
    4242
    43 static QString key_to_display(const QString &key);
    44 static QString display_to_key(const QString &key);
    45 
    4643#define LOC QString("MythControls: ")
    4744#define LOC_ERR QString("MythControls, Error: ")
    4845
     
    5350 */
    5451MythControls::MythControls(MythMainWindow *parent, bool &ok)
    5552    : MythThemedDialog(parent, "controls", "controls-", "controls"),
     53      m_currentView(kActionsByContext),
    5654      m_focusedUIElement(NULL),
    5755      m_leftList(NULL),        m_rightList(NULL),
    5856      m_description(NULL),
     
    7169    m_rightListType = kActionList;
    7270
    7371    LoadData(gContext->GetHostName());
    74     RefreshKeyInformation();
    7572
     73    /* start off with the actions by contexts view */
     74    m_currentView = kActionsByContext;
     75    SetListContents(m_leftList, m_bindings->GetContexts(), true);
     76    UpdateRightList();
     77
    7678    connect(m_leftList,  SIGNAL(itemSelected( UIListBtnTypeItem*)),
    7779            this,        SLOT(  LeftSelected( UIListBtnTypeItem*)));
    7880    connect(m_rightList, SIGNAL(itemSelected( UIListBtnTypeItem*)),
     
    221223    RefreshKeyInformation();
    222224}
    223225
     226/// \brief Chagne the view.
     227void MythControls::ChangeView(void)
     228{
     229    ViewMenu popup(gContext->GetMainWindow(), m_currentView);
     230    QStringList contents;
     231
     232    switch(popup.GetOption())
     233    {
     234        case ViewMenu::kContextAction:
     235            m_currentView = kActionsByContext;
     236            contents = m_bindings->GetContexts();
     237            break;
     238        case ViewMenu::kContextKey:
     239            m_currentView = kKeysByContext;
     240            contents = m_bindings->GetContexts();
     241            break;
     242        case ViewMenu::kKeyContext:
     243            m_currentView = kContextsByKey;
     244            contents = m_bindings->GetKeys();
     245            break;
     246        default:
     247            break;
     248    }
     249
     250    SetListContents(m_leftList, contents, true);
     251    RefreshKeyInformation();
     252    UpdateRightList();
     253
     254    if (m_focusedUIElement != m_leftList)
     255    {
     256        m_focusedUIElement->looseFocus();
     257        m_focusedUIElement = m_leftList;
     258        m_focusedUIElement->takeFocus();
     259    }
     260}
     261
    224262void MythControls::keyPressEvent(QKeyEvent *e)
    225263{
    226264    bool handled = false;
     
    238276            m_focusedUIElement->looseFocus();
    239277
    240278            OptionsMenu popup(gContext->GetMainWindow());
    241             if (OptionsMenu::kSave == popup.GetOption())
    242                 Save();
    243279
     280            switch(popup.GetOption())
     281            {
     282                case OptionsMenu::kSave:
     283                    Save();
     284                    break;
     285                case OptionsMenu::kChangeView:
     286                    ChangeView();
     287                    break;
     288                default:
     289                    break;
     290            }
     291
    244292            m_focusedUIElement->takeFocus();
    245293        }
    246294        else if (action == "SELECT")
     
    327375            else if (m_focusedUIElement == m_rightList)
    328376                m_rightList->MoveDown(UIListBtnType::MovePage);
    329377        }
    330         else if (action == "1")
    331         {
    332             if ((m_leftListType  != kContextList) ||
    333                 (m_rightListType != kActionList))
    334             {
    335                 m_leftListType  = kContextList;
    336                 m_rightListType = kActionList;
    337                 UpdateLists();
    338 
    339                 if (m_focusedUIElement != m_leftList)
    340                 {
    341                     ChangeListFocus(m_leftList,
    342                                     (m_focusedUIElement == m_rightList) ?
    343                                     m_rightList : NULL);
    344                 }
    345             }
    346             else
    347             {
    348                 handled = false;
    349             }
    350         }
    351         else if (action == "2")
    352         {
    353             if ((m_leftListType  != kContextList) ||
    354                 (m_rightListType != kKeyList))
    355             {
    356                 m_leftListType  = kContextList;
    357                 m_rightListType = kKeyList;
    358                 UpdateLists();
    359 
    360                 if (m_focusedUIElement != m_leftList)
    361                 {
    362                     ChangeListFocus(m_leftList,
    363                                     (m_focusedUIElement == m_rightList) ?
    364                                     m_rightList : NULL);
    365                 }
    366             }
    367             else
    368             {
    369                 handled = false;
    370             }
    371         }
    372         else if (action == "3")
    373         {
    374             if ((m_leftListType  != kKeyList) ||
    375                 (m_rightListType != kContextList))
    376             {
    377                 m_leftListType  = kKeyList;
    378                 m_rightListType = kContextList;
    379                 UpdateLists();
    380 
    381                 if (m_focusedUIElement != m_leftList)
    382                 {
    383                     ChangeListFocus(m_leftList,
    384                                     (m_focusedUIElement == m_rightList) ?
    385                                     m_rightList : NULL);
    386                 }
    387             }
    388             else
    389             {
    390                 handled = false;
    391             }
    392         }
    393378        else
    394379        {
    395380            handled = false;
     
    397382    }
    398383
    399384    if (!handled)
    400     {
    401         handled |= (!escape && JumpTo(e));
    402         if (!handled)
    403             MythThemedDialog::keyPressEvent(e);
    404     }
     385        MythThemedDialog::keyPressEvent(e);
    405386}
    406387
    407 /** \fn MythControls::JumpTo(QKeyEvent*)
    408  *  \brief Jump to a particular key binding
    409  *  \param e key event to use as jump
    410  */
    411 bool MythControls::JumpTo(QKeyEvent *e)
    412 {
    413     UIListBtnType *list = NULL;
    414 
    415     list = ((m_focusedUIElement == m_leftList) &&
    416             (m_leftListType     == kKeyList)) ? m_leftList  : list;
    417     list = ((m_focusedUIElement == m_rightList) &&
    418             (m_rightListType    == kKeyList)) ? m_rightList : list;
    419 
    420     if (!list)
    421         return false;
    422 
    423     QString key = e->text();
    424     if (key.left(6) == "remote")
    425     {
    426         key = key_to_display(key);
    427     }
    428     else
    429     {
    430         key = QString(QKeySequence(e->key()));
    431 
    432         if (key.isEmpty())
    433             return false;
    434 
    435         QString modifiers = "";
    436 
    437         if (e->state() & Qt::ShiftButton)
    438             modifiers += "Shift+";
    439         if (e->state() & Qt::ControlButton)
    440             modifiers += "Ctrl+";
    441         if (e->state() & Qt::AltButton)
    442             modifiers += "Alt+";
    443         if (e->state() & Qt::MetaButton)
    444             modifiers += "Meta+";
    445 
    446         key = modifiers + key;
    447     }
    448 
    449     uint len = 1024; // infinity
    450     if (list == m_rightList)
    451     {
    452         key = key + " ";
    453         len = key.length();
    454     }
    455 
    456     UIListBtnTypeItem *b;
    457     for (b = list->GetItemFirst(); b; b = list->GetItemNext(b))
    458     {
    459         if (b->text().left(len) == key)
    460             break;
    461     }
    462 
    463     if (!b)
    464         return false;
    465 
    466     int curpos = list->GetItemPos(list->GetItemCurrent());
    467     int newpos = list->GetItemPos(b);
    468 
    469     if (newpos > curpos)
    470         list->MoveDown(newpos - curpos);
    471     else if (newpos < curpos)
    472         list->MoveUp(curpos - newpos);
    473 
    474     return true;
    475 }
    476 
    477388/** \fn MythControls::LeftSelected(UIListBtnTypeItem*)
    478389 *  \brief Refreshes the right list when an item in the
    479390 *         left list is selected
     
    482393{
    483394    m_leftList->refresh();
    484395    m_rightList->blockSignals(true);
    485     RefreshRightList();
     396    UpdateRightList();
    486397    m_rightList->blockSignals(false);
    487398    m_rightList->refresh();
    488399}
     
    497408    RefreshKeyInformation();
    498409}
    499410
    500 /** \fn MythControls::RefreshRightList(void)
    501  *  \brief Load the appropriate actions into the action list
     411
     412/** \brief Set the contents of a list.
     413 *  \param list The list being changed.
     414 *  \param contents The contents of the list.
     415 *  \param arrows True to draw with arrows, otherwise arrows are not drawn.
    502416 */
    503 void MythControls::RefreshRightList(void)
     417void MythControls::SetListContents(
     418    UIListBtnType *uilist, const QStringList &contents, bool arrows)
    504419{
    505     m_rightList->Reset();
     420    uilist->blockSignals(true);
    506421
    507     if (!m_leftList->GetItemCurrent())
    508         return;
     422    // remove all strings from the current list
     423    uilist->Reset();
    509424
    510     if (m_leftListType == kContextList)
     425    // add each new string
     426    for (size_t i = 0; i < contents.size(); i++)
    511427    {
    512         if (m_rightListType == kActionList)
    513         {
    514             /* add all of the actions to the context list */
    515             QString context = m_leftList->GetItemCurrent()->text();
    516             QStringList *actions = m_contexts[context];
    517             if (!actions || actions->empty())
    518             {
    519                 VERBOSE(VB_IMPORTANT, LOC_ERR +
    520                         QString("Unable to find actions for context %1")
    521                         .arg(context));
    522 
    523                 return;
    524             }
    525 
    526             for (uint i = 0; i < actions->size(); i++)
    527                 new UIListBtnTypeItem(m_rightList, (*actions)[i]);
    528         }
    529         else if (m_rightListType == kKeyList)
    530         {
    531             /* add all of the actions to the context list */
    532             QString context = m_leftList->GetItemCurrent()->text();
    533             const BindingList *list = m_contextToBindingsMap[context];
    534             if (!list)
    535             {
    536                 VERBOSE(VB_IMPORTANT, LOC_ERR+
    537                         QString("Unable to find keys for context %1")
    538                         .arg(context));
    539 
    540                 return;
    541             }
    542 
    543             BindingList::const_iterator it = list->begin();
    544             for (; it != list->end(); ++it)
    545             {
    546                 new UIListBtnTypeItem(
    547                     m_rightList,
    548                     key_to_display((*it)->key) + " => " + (*it)->action);
    549             }
    550         }
     428        UIListBtnTypeItem *item = new UIListBtnTypeItem(uilist, contents[i]);
     429        item->setDrawArrow(arrows);
    551430    }
    552     else if ((m_leftListType == kKeyList) && (m_rightListType == kContextList))
    553     {
    554         QString key = display_to_key(m_leftList->GetItemCurrent()->text());
    555         const BindingList *list = m_keyToBindingsMap[key];
    556         if (!list)
    557         {
    558             VERBOSE(VB_IMPORTANT, LOC + QString(
    559                         "Unable to find actions for key %1").arg(key));
    560             return;
    561         }
    562431
    563         BindingList::const_iterator it = list->begin();
    564         const Binding *b = *it;
    565         for (uint i = 0; i < m_sortedContexts.size(); i++)
    566         {
    567             const QString context = m_sortedContexts[i];
    568             QString action  = "<none>";
    569 
    570             if (b && b->context == context)
    571             {
    572                 action = b->action;
    573                 ++it;
    574                 b = (it != list->end()) ? *it : NULL;
    575             }
    576 
    577             new UIListBtnTypeItem(m_rightList, context + " => " + action);
    578         }
    579     }
     432    uilist->blockSignals(false);
     433    uilist->refresh();
    580434}
    581435
    582 QString MythControls::RefreshKeyInformationKeyList(void)
     436/** \brief Update the right list. */
     437void MythControls::UpdateRightList(void)
    583438{
    584     if ((m_leftListType != kKeyList) && (m_rightListType != kKeyList))
    585         return "";
     439    // get the selected item in the right list.
     440    QString rtstr = m_leftList->GetItemCurrent()->text();
    586441
    587     QString action  = GetCurrentAction();
    588     QString context = GetCurrentContext();
    589 
    590     if (action.isEmpty())
    591         return "";
    592 
    593     QString desc = m_bindings->GetActionDescription(context, action);
    594    
    595     BindingList *list = NULL;
    596     if (m_leftListType == kKeyList && m_rightListType == kContextList)
     442    switch(m_currentView)
    597443    {
    598         list = m_keyToBindingsMap[display_to_key(GetCurrentKey())];
    599     }
    600     else if (m_leftListType == kContextList && m_rightListType == kKeyList)
    601     {
    602         list = m_contextToBindingsMap[context];
    603     }
    604 
    605     if (!list)
    606         return desc;
    607 
    608     QString searchKey = QString::null;
    609     if (m_rightListType == kContextList)
    610     {
    611         searchKey = context;
    612     }
    613     else if (m_rightListType == kActionList)
    614     {
    615         searchKey = action;
    616     }
    617     else if (m_rightListType == kKeyList)
    618     {
    619         searchKey = display_to_key(GetCurrentKey());
    620     }
    621 
    622     const Binding *binding = NULL;
    623     for (BindingList::const_iterator it = list->begin();
    624          it != list->end(); ++it)
    625     {
    626         switch (m_rightListType)
    627         {
    628             case kContextList:
    629                 if ((*it)->context == searchKey)
    630                     binding = *it;
    631                 break;
    632             case kActionList:
    633                 if ((*it)->action == searchKey)
    634                     binding = *it;
    635                 break;
    636             case kKeyList:
    637                 if ((*it)->key == searchKey)
    638                     binding = *it;
    639                 break;
    640         }
    641 
    642         if (binding)
     444        case kActionsByContext:
     445            SetListContents(m_rightList, *(m_contexts[rtstr]));
    643446            break;
     447        case kKeysByContext:
     448            SetListContents(m_rightList, m_bindings->GetContextKeys(rtstr));
     449            break;
     450        case kContextsByKey:
     451            SetListContents(m_rightList, m_bindings->GetKeyContexts(rtstr));
     452            break;
    644453    }
    645    
    646     if (!binding)
    647         return desc;
    648 
    649 
    650     if (desc.isEmpty() && (context != binding->contextFrom))
    651     {
    652         desc = m_bindings->GetActionDescription(
    653             binding->contextFrom, action);
    654     }
    655 
    656     desc += "\n" + tr("Binding comes from %1 context")
    657         .arg(binding->contextFrom);
    658 
    659     return desc;
    660454}
    661455
    662456/** \fn MythControls::RefreshKeyInformation(void)
     
    674468        return;
    675469    }
    676470
    677     if ((m_leftListType == kKeyList) || (m_rightListType == kKeyList))
    678     {
    679         m_description->SetText(RefreshKeyInformationKeyList());
    680         return;
    681     }
    682 
    683471    const QString context = GetCurrentContext();
    684472    const QString action  = GetCurrentAction();
    685473
     
    690478    for (uint i = 0; (i < keys.count()) &&
    691479             (i < Action::kMaximumNumberOfBindings); i++)
    692480    {
    693         m_actionButtons[i]->setText(key_to_display(keys[i]));
     481        m_actionButtons[i]->setText(keys[i]);
    694482    }
    695483}
    696484
     
    731519QString MythControls::GetCurrentAction(void) const
    732520{
    733521    if (m_leftListType == kActionList)
    734         return m_leftList->GetItemCurrent()->text();
     522    {
     523        if (m_leftList && m_leftList->GetItemCurrent())
     524            return QDeepCopy<QString>(m_leftList->GetItemCurrent()->text());
     525        return QString::null;
     526    }
    735527
    736528    if (m_focusedUIElement == m_leftList)
    737529        return QString::null;
    738530
     531    if (!m_rightList || !m_rightList->GetItemCurrent())
     532        return QString::null;
     533
    739534    QString desc = m_rightList->GetItemCurrent()->text();
    740535    if (m_leftListType == kContextList && m_rightListType == kActionList)
    741         return desc;
     536        return QDeepCopy<QString>(desc);
    742537
    743538    int loc = desc.find(" => ");
    744539    if (loc == -1)
     
    794589    return desc.mid(loc + 4);
    795590}
    796591
    797 /** \fn MythControls::LoadAll(const QString&)
     592/** \fn MythControls::LoadData(const QString&)
    798593 *  \brief Load the settings for a particular host.
    799594 *  \param hostname The host to load settings for.
    800595 */
     
    804599    m_bindings = new KeyBindings(hostname);
    805600    m_sortedContexts = m_bindings->GetContexts();
    806601
    807     m_sortedKeys.clear();
    808 
    809602    /* Alphabetic order, but jump and global at the top  */
    810603    m_sortedContexts.sort();
    811604    m_sortedContexts.remove(ActionSet::kJumpContext);
     
    822615        actions.sort();
    823616        m_contexts.insert(m_sortedContexts[i], new QStringList(actions));
    824617    }
    825 
    826     RefreshKeyBindings();
    827     UpdateLists();
    828618}
    829619
    830620/** \fn MythControls::DeleteKey(void)
     
    846636        return;
    847637    }
    848638
    849     BindingList *list = m_keyToBindingsMap[key];
    850     Binding *binding = NULL;
     639    ConfirmMenu popup(gContext->GetMainWindow(), tr("Delete this binding?"));
    851640
    852     for (BindingList::iterator it = list->begin(); it != list->end(); ++it)
    853     {
    854         Binding *b = *it;
    855         if (b->context == context)
    856             binding = b;
    857     }
    858 
    859     if (!binding)
    860     {
    861         InvalidBindingPopup popup(gContext->GetMainWindow());
    862         popup.GetOption();
     641    if (popup.GetOption() != ConfirmMenu::kConfirm)
    863642        return;
    864     }
    865643
    866     if (binding->contextFrom != context)
     644    if (!m_bindings->RemoveActionKey(context, action, key))
    867645    {
    868         ConfirmMenu popup(gContext->GetMainWindow(),
    869                           tr("Delete this key binding from context %1?")
    870                           .arg(binding->contextFrom));
    871 
    872         if (popup.GetOption() != ConfirmMenu::kConfirm)
    873             return;
    874     }
    875     else
    876     {
    877         ConfirmMenu popup(gContext->GetMainWindow(),
    878                           tr("Delete this binding?"));
    879 
    880         if (popup.GetOption() != ConfirmMenu::kConfirm)
    881             return;
    882     }
    883 
    884     if (!m_bindings->RemoveActionKey(binding->contextFrom, action, key))
    885     {
    886646        InvalidBindingPopup popup(gContext->GetMainWindow());
    887647        popup.GetOption();
    888648        return;
    889649    }
    890650
    891     RefreshKeyBindings();
    892651    RefreshKeyInformation();
    893652}
    894653
     
    977736        m_bindings->AddActionKey(context, action, key);
    978737    }
    979738
    980     RefreshKeyBindings();
    981739    RefreshKeyInformation();
    982740}
    983741
    984 /** \fn MythControls::AddBindings(QDict<Binding>&, const QString&,
    985                                   const QString&, int)
    986  *  \brief Add bindings to QDict<Binding> for specified context
    987  *  \param bindings the QDict to which to add the bindings
    988  *  \param context the context to grab keybindings from
    989  *  \param contextParent the context whose keybindings are being calculated
    990  *  \param bindlevel the bind level associated with this context
     742/** \fn ViewMenu::ViewMenu(MythMainWindow*, ViewType)
     743 *  \brief Creates a new view dialog box.
     744 *  \param window The main MythTV window.
     745 *  \param first The first button's caption
     746 *  \param second The second button's caption
    991747 */
    992 void MythControls::AddBindings(QDict<Binding> &bindings,
    993                                const QString    &context,
    994                                const QString    &contextParent,
    995                                int               bindlevel)
     748ViewMenu::ViewMenu(MythMainWindow *window, ViewType current) :
     749    MythPopupBox(window, "mcviewmenu")
    996750{
    997     QStringList actions = m_bindings->GetActions(context);
     751    addLabel(tr("Change View"), Large, false);
    998752
    999     for (uint i = 0; i < actions.size(); i++)
     753    switch(current)
    1000754    {
    1001         QString action = actions[i];
    1002         QStringList keys = m_bindings->GetActionKeys(context, action);
    1003 
    1004         for (uint j = 0; j < keys.size(); j++)
    1005         {
    1006             Binding *b = bindings.find(keys[j]);
    1007 
    1008             if (!b)
    1009             {
    1010                 b = new Binding(keys[j], contextParent,
    1011                                 context, action, bindlevel);
    1012 
    1013                 bindings.insert(keys[j], b);
    1014             }
    1015             else if (b->bindlevel == bindlevel)
    1016             {
    1017                 b->action += ", " + action;
    1018             }
    1019         }
    1020     }
    1021 }
    1022 
    1023 /** \fn MythControls::GetKeyBindings(const QString&)
    1024  *  \brief Create a BindingList for the specified context
    1025  *  \param context the context for which a BindingList should be created
    1026  *  \return a BindingList with "auto delete" property enabled.
    1027  */
    1028 BindingList *MythControls::GetKeyBindings(const QString &context)
    1029 {
    1030     QDict<Binding> bindings;
    1031     for (uint i = 0; i < m_sortedContexts.size(); i++)
    1032         AddBindings(bindings, m_sortedContexts[i], context, i);
    1033 
    1034     QStringList keys;
    1035     for (QDictIterator<Binding> it(bindings); it.current(); ++it)
    1036         keys.append(it.currentKey());
    1037 
    1038     SortKeyList(keys);
    1039 
    1040     BindingList *blist = new BindingList();
    1041     blist->setAutoDelete(true);
    1042 
    1043     QStringList::const_iterator kit = keys.begin();
    1044     for (; kit != keys.end(); ++kit)
    1045         blist->append(bindings[*kit]);
    1046 
    1047     return blist;
    1048 }
    1049 
    1050 /** \fn MythControls::RefreshKeyBindings(void)
    1051  *  \brief Refresh binding information
    1052  */
    1053 void MythControls::RefreshKeyBindings(void)
    1054 {
    1055     m_contextToBindingsMap.clear();
    1056     m_keyToBindingsMap.clear();
    1057     m_contextToBindingsMap.setAutoDelete(true);
    1058     m_keyToBindingsMap.setAutoDelete(true);
    1059 
    1060     for (uint i = 0; i < m_sortedContexts.size(); i++)
    1061     {
    1062         QString context = m_sortedContexts[i];
    1063         BindingList *list = GetKeyBindings(context);
    1064         m_contextToBindingsMap.insert(context, list);
    1065 
    1066         BindingList::const_iterator it = list->begin();
    1067         for (; it != list->end(); ++it)
    1068         {
    1069             BindingList *list = m_keyToBindingsMap.find((*it)->key);
    1070 
    1071             if (!list)
    1072             {
    1073                 list = new BindingList();
    1074                 m_keyToBindingsMap.insert((*it)->key, list);
    1075             }
    1076 
    1077             m_sortedKeys.append((*it)->key);
    1078             list->append(*it);
    1079         }
    1080     }
    1081 
    1082     SortKeyList(m_sortedKeys);
    1083 }
    1084 
    1085 /** \fn MythControls::SortKeyList(QStringList&)
    1086  *  \brief Sort a list of keys, removing duplicates
    1087  *  \param keys the list of keys to sort
    1088  */
    1089 void MythControls::SortKeyList(QStringList &keys)
    1090 {
    1091     QStringList tmp;
    1092     QStringList::const_iterator it = keys.begin();
    1093     for (; it != keys.end(); ++it)
    1094     {
    1095         QString key     = *it;
    1096         QString keydesc = (key.left(6) == "remote") ? "0 " : "3 ";
    1097 
    1098         keydesc = ((key.length() > 1) && !(key.left(6) == "remote") &&
    1099                    (key.find("+", 1) >= 0)) ? "4 " : keydesc;
    1100 
    1101         if (key.length() == 1)
    1102         {
    1103             QChar::Category cat = key[0].category();
    1104             keydesc = (QChar::Letter_Uppercase    == cat) ? "2 " : "5 ";
    1105             keydesc = (QChar::Number_DecimalDigit == cat) ? "1 " : keydesc;
    1106         }
    1107 
    1108         tmp.push_back(keydesc + key);
    1109     }
    1110     tmp.sort();
    1111 
    1112     keys.clear();
    1113 
    1114     QString prev = QString::null;
    1115     for (it = tmp.begin(); it != tmp.end(); ++it)
    1116     {
    1117         QString cur = (*it).mid(2);
    1118         if (cur != prev)
    1119         {
    1120             keys.append(cur);
    1121             prev = cur;
    1122         }
    1123     }
    1124 }
    1125 
    1126 /// NOTE: This can not be a static method because the QObject::tr()
    1127 ///       translations do not work reliably in static initializers.
    1128 QString MythControls::GetTypeDesc(ListType type) const
    1129 {
    1130     switch (type)
    1131     {
    1132         case kContextList:
    1133             return tr("Contexts");
     755        case kKeysByContext:
     756            addButton(tr("Actions By Context"),
     757                      this, SLOT(ActionsByContext()));
     758            addButton(tr("Contexts By Key"),
     759                      this, SLOT(ContextsByKey()));
    1134760            break;
    1135         case kKeyList:
    1136             return tr("Keys");
     761        case kContextsByKey:
     762            addButton(tr("Actions By Context"),
     763                      this, SLOT(ActionsByContext()));
     764            addButton(tr("Keys By Context"),
     765                      this, SLOT(KeysByContext()));
    1137766            break;
    1138         case kActionList:
    1139             return tr("Actions");
    1140             break;
    1141767        default:
    1142             return "";
     768            addButton(tr("Keys By Context"),
     769                      this, SLOT(KeysByContext()));
     770            addButton(tr("Contexts By Key"),
     771                      this, SLOT(ContextsByKey()));
     772            break; 
    1143773    }
    1144 }
    1145774
    1146 /** \fn MythControls::UpdateLists(void)
    1147  *  \brief Redisplays both the left and right lists and fixes focus issues.
    1148  */
    1149 void MythControls::UpdateLists(void)
    1150 {
    1151     m_rightList->blockSignals(true);
    1152     m_leftList->blockSignals(true);
    1153     m_leftList->Reset();
    1154 
    1155     if (m_leftListType == kContextList)
    1156     {
    1157         for (uint i = 0; i < m_sortedContexts.size(); i++)
    1158         {
    1159             UIListBtnTypeItem *item = new UIListBtnTypeItem(
    1160                 m_leftList, m_sortedContexts[i]);
    1161 
    1162             item->setDrawArrow(true);
    1163         }
    1164     }
    1165     else if (m_leftListType == kKeyList)
    1166     {
    1167         for (uint i = 0; i < m_sortedKeys.size(); i++)
    1168         {
    1169             UIListBtnTypeItem *item = new UIListBtnTypeItem(
    1170                 m_leftList, key_to_display(m_sortedKeys[i]));
    1171 
    1172             item->setDrawArrow(true);
    1173         }
    1174     }
    1175 
    1176     RefreshRightList();
    1177 
    1178     m_rightList->blockSignals(false);
    1179     m_leftList->blockSignals(false);
    1180 
    1181     m_leftList->refresh();
    1182     m_rightList->refresh();
    1183 
    1184     if (m_leftDescription)
    1185         m_leftDescription->SetText(GetTypeDesc(m_leftListType));
    1186 
    1187     if (m_rightDescription)
    1188         m_rightDescription->SetText(GetTypeDesc(m_rightListType));
     775    addButton(tr("Cancel"), this, SLOT(Cancel()))->setFocus();
    1189776}
    1190777
    1191 static QString key_to_display(const QString &key)
    1192 {
    1193     if (key.left(6) == "remote")
    1194         return "[" + key.mid(6) + "]";
    1195 
    1196     return key;
    1197 }
    1198 
    1199 static QString display_to_key(const QString &key)
    1200 {
    1201     if (key.left(1) == "[" && key != "[")
    1202         return "remote" + key.mid(1, key.length() - 2);
    1203 
    1204     return key;
    1205 }
    1206 
    1207778/* vim: set expandtab tabstop=4 shiftwidth=4: */
  • mythcontrols/keybindings.cpp

     
    4949    LoadJumppoints();
    5050}
    5151
     52/** \brief Returns a list of all keys bound to an action. */
     53QStringList KeyBindings::GetKeys(void) const
     54{
     55    return m_actionSet.GetAllKeys();
     56}
     57
    5258/** \fn KeyBindings::GetContexts(void) const
    5359 *  \brief Returns a list of the context names.
    5460 *  \note The returned list is a copy and can be modified without side-effects.
    5561 */
    5662QStringList KeyBindings::GetContexts(void) const
    5763{
    58     return QDeepCopy<QStringList>(m_actionSet.GetContextStrings());
     64    QStringList ctxts =
     65        QDeepCopy<QStringList>(m_actionSet.GetContextStrings());
     66    ctxts.sort();
     67    return ctxts;
    5968}
    6069
    6170/** \fn KeyBindings::GetActions(const QString&) const
     
    95104        (m_actionSet.GetKeys(ActionID(context_name, action_name)));
    96105}
    97106
     107/** \fn KeyBindings::GetContextKeys(const QString &) const
     108 *  \brief Get the keys within a context.
     109 *  \param context The context name.
     110 *  \return A list of the keys in the context.
     111 */
     112QStringList KeyBindings::GetContextKeys(const QString &context) const
     113{
     114    return m_actionSet.GetContextKeys(context);
     115}
     116
     117/** \fn KeyBindings::GetKeyContexts(const QString &) const
     118 *  \brief Get the context names in which a key is bound.
     119 *  \return A list of context names in which a key is bound.
     120 */
     121QStringList KeyBindings::GetKeyContexts(const QString &key) const
     122{
     123    ActionList actions = m_actionSet.GetActions(key);
     124    QStringList contexts;
     125
     126    for (size_t i = 0; i < actions.size(); i++)
     127    {
     128        QString context = actions[i].GetContext();
     129        if (!contexts.contains(context))
     130            contexts.push_back(context);
     131    }
     132
     133    return contexts;
     134}
     135
    98136/** \fn KeyBindings::GetActionDescription(const QString&,const QString&) const
    99137 *  \brief Get an action's description.
    100138 *  \param context_name The name of the context.
  • mythcontrols/actionset.cpp

     
    6262
    6363    ActionList &ids = m_keyToActionMap[key];
    6464    ids.push_back(id);
    65     SetModifiedFlag(id, true); 
     65    SetModifiedFlag(id, true);
    6666
    6767    return true;
    6868}
     
    7575 *
    7676 *  \param id The action identifier to remove from.
    7777 *  \param key The key to remove.
     78 *
     79 *  \todo Remove the actionlist from the m_keyToActionMap if the key
     80 *        is no longer bound to any actions.
    7881 */
    7982bool ActionSet::Remove(const ActionID &id, const QString &key)
    8083{
     
    8790        return false;
    8891
    8992    m_keyToActionMap[key].remove(id);
     93
     94    // remove the key if there isn't anything bound to it.
     95    if (m_keyToActionMap[key].isEmpty())
     96        m_keyToActionMap.remove(key);
     97
    9098    SetModifiedFlag(id, true);
    9199
    92     return true;           
     100    return true;
    93101}
    94102
    95103/** \fn ActionSet::Replace(const ActionID&,const QString&,const QString&)
     
    118126    m_keyToActionMap[newkey].push_back(id);
    119127    SetModifiedFlag(id, true);
    120128
    121     return true;           
     129    return true;
    122130}
    123131
    124132/** \fn ActionSet::SetModifiedFlag(const ActionID&, bool)
     
    242250    return keys;
    243251}
    244252
     253QStringList ActionSet::GetContextKeys(const QString & context_name) const
     254{
     255    QStringList keys;
     256    Context *c = m_contexts[context_name];
     257
     258    QDictIterator<Action> it(*c);
     259    for (;it.current(); ++it)
     260    {
     261        QStringList akeys = (*it)->GetKeys();
     262        for (size_t i = 0; i < akeys.size(); i++)
     263        {
     264                keys.append(akeys[i]);
     265        }
     266        keys.sort();
     267    }
     268
     269    return keys;
     270}
     271
     272/** \brief Get all keys (from every context) to which an action is bound.
     273 */
     274QStringList ActionSet::GetAllKeys(void) const
     275{
     276    QStringList keys;
     277
     278    QMap<QString, ActionList>::ConstIterator it;
     279
     280    for (it = m_keyToActionMap.begin(); it != m_keyToActionMap.end(); ++it)
     281        keys.push_back(it.key());
     282
     283    return keys;
     284}
     285
    245286/** \fn ActionSet::GetDescription(const ActionID&) const
    246287 *  \brief Returns the description of an action by its identifier.
    247288 *         (note: result not thread-safe)
  • mythcontrols/mythcontrols.h

     
    2929
    3030#include "keybindings.h"
    3131
    32 class Binding
     32
     33typedef enum { kActionsByContext, kKeysByContext, kContextsByKey, } ViewType;
     34
     35/** \class ViewMenu
     36 *  \brief Prompts the user to change the view.
     37 */
     38class ViewMenu : public MythPopupBox
    3339{
     40    Q_OBJECT
     41
    3442  public:
    35     Binding(const QString &_key,         const QString &_context,
    36             const QString &_contextFrom, const QString &_action,
    37             int            _bindlevel) :
    38         key(_key), context(_context),
    39         contextFrom(_contextFrom), action(_action), bindlevel(_bindlevel) {}
     43    ViewMenu(MythMainWindow *window, ViewType current);
    4044
    41   public:
    42     QString key;
    43     QString context;
    44     QString contextFrom;
    45     QString action;
    46     int     bindlevel;
     45    /// \brief Execute the option popup.
     46    int GetOption(void) { return ExecPopup(this, SLOT(Cancel())); }
     47
     48    /// \brief The available views
     49    enum actions { kContextAction, kContextKey, kKeyContext, kCancel, };
     50
     51  public slots:
     52    void ActionsByContext(void) { done(ViewMenu::kContextAction); }
     53    void KeysByContext(void)    { done(ViewMenu::kContextKey);    }
     54    void ContextsByKey(void)    { done(ViewMenu::kKeyContext);    }
     55    void Cancel(void)           { done(ViewMenu::kCancel);        }
    4756};
    48 typedef QPtrList<Binding> BindingList;
    4957
    5058/** \class MythControls
    5159 *  \brief The myth controls configuration class.
     
    7785    // Commands
    7886    bool    LoadUI(void);
    7987    void    RefreshKeyInformation(void);
    80     QString RefreshKeyInformationKeyList(void);
    81     void    RefreshRightList(void);
    82     void    UpdateLists(void);
    8388    void    LoadData(const QString &hostname);
    8489    void    ChangeButtonFocus(int direction);
    8590    void    ChangeListFocus(UIListBtnType *focus, UIListBtnType *unfocus);
    86     void    AddBindings(QDict<Binding> &bindings, const QString &context,
    87                         const QString &contextParent, int bindlevel);
     91    void    ChangeView(void);
     92    void    SetListContents(UIListBtnType *uilist,
     93                            const QStringList & contents,
     94                            bool arrows = false);
     95    void    UpdateRightList(void);
    8896
    8997    // Gets
    90     BindingList *GetKeyBindings(const QString &context);
    9198    uint         GetCurrentButton(void) const;
    9299
    93100    // Functions
     
    99106    void DeleteKey(void);
    100107    void LeftSelected(UIListBtnTypeItem *item);
    101108    void RightSelected(UIListBtnTypeItem *item);
    102     void SortKeyList(QStringList &keys);
    103     void RefreshKeyBindings(void);
    104109    bool JumpTo(QKeyEvent *e);
    105110    /// \brief Save the bindings to the Database.
    106111    void Save(void) { m_bindings->CommitChanges(); }
    107112
    108113  private:
     114    ViewType           m_currentView;
    109115    UIType            *m_focusedUIElement;
    110116    UIListBtnType     *m_leftList;
    111117    UIListBtnType     *m_rightList;
     
    117123    KeyBindings       *m_bindings;
    118124    LayerSet          *m_container;
    119125    QStringList        m_sortedContexts; ///< sorted list of contexts
    120     QStringList        m_sortedKeys;     ///< sorted list of keys
    121126    QDict<QStringList> m_contexts;       ///< actions for a given context
    122     QDict<BindingList> m_contextToBindingsMap;
    123     QDict<BindingList> m_keyToBindingsMap;
    124127    ListType           m_leftListType;
    125128    ListType           m_rightListType;
    126129};
  • mythcontrols/keybindings.h

     
    5959    void        CommitChanges(void);
    6060
    6161    // Gets
     62    QStringList GetKeys(void) const;
    6263    QStringList GetContexts(void) const;
    6364    QStringList GetActions(const QString &context) const;
    6465    void        GetKeyActions(const QString &key, ActionList &list) const;
    6566    QStringList GetActionKeys(const QString &context_name,
    6667                              const QString &action_name) const;
     68    QStringList GetContextKeys(const QString &context) const;
     69    QStringList GetKeyContexts(const QString &key) const;
    6770    QString     GetActionDescription(const QString &context_name,
    6871                                     const QString &action_name) const;
    6972    bool        HasMandatoryBindings(void) const;
  • mythcontrols/controls-ui.xml

     
    4646  <container name="controls">
    4747   <area>20,20,780,450</area>
    4848
    49    <textarea name="options" draworder="1" align="center">
    50     <font>options</font>
    51     <area>0,0,780,30</area>
    52     <value>(1) Contexts / Actions  (2) Contexts / Keys  (3) Keys / Contexts</value>
    53    </textarea>
    54 
    5549   <textarea name="leftdesc" draworder="1" align="center">
    5650    <font>info</font>
    57     <area>0,40,370,20</area>
     51    <area>0,0,370,20</area>
    5852    <value>Contexts</value>
    5953   </textarea>
    6054
    6155   <listbtnarea name="leftlist" draworder="0">
    62     <area>0,60,370,380</area>
     56    <area>0,30,370,420</area>
    6357    <gradient type="unselected" start="#505050" end="#000000" alpha="100"/>
    6458    <gradient type="selected" start="#52CA38" end="#349838" alpha="255"/>
    6559    <fcnfont name="active" function="active"/>
     
    6963
    7064   <textarea name="rightdesc" draworder="1" align="center">
    7165    <font>info</font>
    72     <area>390,40,370,20</area>
     66    <area>390,0,370,20</area>
    7367    <value>Actions</value>
    7468   </textarea>
    7569
    7670   <listbtnarea name="rightlist" draworder="0">
    77     <area>390,60,370,380</area>
     71    <area>390,30,370,420</area>
    7872    <gradient type="unselected" start="#505050" end="#000000" alpha="100"/>
    7973    <gradient type="selected" start="#52CA38" end="#349838" alpha="255"/>
    8074    <fcnfont name="active" function="active"/>
  • mythcontrols/keygrabber.cpp

     
    126126{
    127127    addLabel(tr("Options"), Large, false);
    128128    addButton(QObject::tr("Save"),   this, SLOT(Save()));
     129    addButton(QObject::tr("Change View"), this, SLOT(ChangeView()));
    129130    addButton(QObject::tr("Cancel"), this, SLOT(Cancel()))->setFocus();
    130131}
    131132