Ticket #2078: ui_and_logic_again.diff

File ui_and_logic_again.diff, 36.5 KB (added by mfgalizia, 15 years ago)

Fixes the logic and ui (again)

  • 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
     
    8082    static const QString kGlobalContext;
    8183
    8284  private:
    83     QMap<QString, ActionList> m_keyToActionMap;
    84     QDict<Context>            m_contexts;
    85     ActionList                m_modified;
     85    QMap<QString, ActionList>  m_keyToActionMap;
     86    QDict<Context>             m_contexts;
     87    ActionList                 m_modified;
    8688};
    8789
    8890#endif /* ACTIONSET_H */
  • mythcontrols/keygrabber.h

     
    2525// MythTV headers
    2626#include <mythtv/mythdialogs.h>
    2727
    28 
    2928/** \class KeyGrabPopupBox
    3029 *  \brief Captures a key.
    3130 *
     
    9493    Q_OBJECT
    9594
    9695  public:
    97     enum actions { kSave, kCancel, };
     96    enum actions { kSave, kChangeView, kCancel, };
    9897
    9998    /// \brief Create a new action window. Does not pop-up menu.
    10099    OptionsMenu(MythMainWindow *window);
     
    103102    int GetOption(void) { return ExecPopup(this,SLOT(Cancel())); }
    104103
    105104  public slots:
    106     void Save(void)     { done(OptionsMenu::kSave);   }
    107     void Cancel(void)   { done(OptionsMenu::kCancel); }
     105    void Save(void)       { done(OptionsMenu::kSave);   }
     106    void ChangeView(void) { done(OptionsMenu::kChangeView); }
     107    void Cancel(void)     { done(OptionsMenu::kCancel); }
    108108};
    109109
    110110
  • 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
     
    3737#include <mythtv/mythdialogs.h>
    3838
    3939// MythControls headers
    40 #include "mythcontrols.h"
    4140#include "keygrabber.h"
     41#include "mythcontrols.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"),
    56       m_focusedUIElement(NULL),
     53      m_currentView(kActionsByContext), m_focusedUIElement(NULL),
    5754      m_leftList(NULL),        m_rightList(NULL),
    5855      m_description(NULL),
    5956      m_leftDescription(NULL), m_rightDescription(NULL),
    60       m_bindings(NULL),     m_container(NULL)
     57      m_bindings(NULL),     m_container(NULL)     
    6158{
    6259    bzero(m_actionButtons, sizeof(void*) * Action::kMaximumNumberOfBindings);
    6360    m_contexts.setAutoDelete(true);
     
    7168    m_rightListType = kActionList;
    7269
    7370    LoadData(gContext->GetHostName());
    74     RefreshKeyInformation();
    7571
     72    /* start off with the actions by contexts view */
     73    m_currentView = kActionsByContext;
     74    SetListContents(m_leftList, m_bindings->GetContexts(), true);
     75    UpdateRightList();
     76
    7677    connect(m_leftList,  SIGNAL(itemSelected( UIListBtnTypeItem*)),
    7778            this,        SLOT(  LeftSelected( UIListBtnTypeItem*)));
    7879    connect(m_rightList, SIGNAL(itemSelected( UIListBtnTypeItem*)),
     
    221222    RefreshKeyInformation();
    222223}
    223224
     225/// \brief Chagne the view.
     226void MythControls::ChangeView(void)
     227{
     228    ViewMenu popup(gContext->GetMainWindow(), m_currentView);
     229    QStringList contents;
     230
     231    switch(popup.GetOption())
     232    {
     233    case ViewMenu::kContextAction:
     234        m_currentView = kActionsByContext;
     235        contents = m_bindings->GetContexts();
     236        break;
     237    case ViewMenu::kContextKey:
     238        m_currentView = kKeysByContext;
     239        contents = m_bindings->GetContexts();
     240        break;
     241    case ViewMenu::kKeyContext:
     242        m_currentView = kContextsByKey;
     243        contents = m_bindings->GetKeys();
     244        break;
     245    default:
     246        break;
     247    }
     248
     249    SetListContents(m_leftList, contents, true);
     250    RefreshKeyInformation();
     251    UpdateRightList();
     252
     253    if (m_focusedUIElement != m_leftList)
     254    {
     255        m_focusedUIElement->looseFocus();
     256        m_focusedUIElement = m_leftList;
     257        m_focusedUIElement->takeFocus();
     258    }
     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: Save();
     283                break;
     284            case OptionsMenu::kChangeView:
     285                ChangeView();
     286                break;
     287            default:
     288                break;
     289            }
     290
    244291            m_focusedUIElement->takeFocus();
    245292        }
    246293        else if (action == "SELECT")
     
    327374            else if (m_focusedUIElement == m_rightList)
    328375                m_rightList->MoveDown(UIListBtnType::MovePage);
    329376        }
    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         }
    393377        else
    394378        {
    395379            handled = false;
     
    397381    }
    398382
    399383    if (!handled)
    400     {
    401         handled |= (!escape && JumpTo(e));
    402         if (!handled)
    403384            MythThemedDialog::keyPressEvent(e);
    404     }
    405385}
    406386
    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 
    477387/** \fn MythControls::LeftSelected(UIListBtnTypeItem*)
    478388 *  \brief Refreshes the right list when an item in the
    479389 *         left list is selected
     
    482392{
    483393    m_leftList->refresh();
    484394    m_rightList->blockSignals(true);
    485     RefreshRightList();
     395    UpdateRightList();
    486396    m_rightList->blockSignals(false);
    487397    m_rightList->refresh();
    488398}
     
    497407    RefreshKeyInformation();
    498408}
    499409
    500 /** \fn MythControls::RefreshRightList(void)
    501  *  \brief Load the appropriate actions into the action list
     410
     411/** \brief Set the contents of a list.
     412 *  \param list The list being changed.
     413 *  \param contents The contents of the list.
     414 *  \param arrows True to draw with arrows, otherwise arrows are not drawn.
    502415 */
    503 void MythControls::RefreshRightList(void)
     416void MythControls::SetListContents(UIListBtnType *uilist,
     417                                   const QStringList & contents, bool arrows)
    504418{
    505     m_rightList->Reset();
     419    uilist->blockSignals(true);
    506420
    507     if (!m_leftList->GetItemCurrent())
    508         return;
     421    // remove all strings from the current list
     422    uilist->Reset();
    509423
    510     if (m_leftListType == kContextList)
    511     {
    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));
     424    // add each new string
     425    for (size_t i = 0; i < contents.size(); i++)
     426        (new UIListBtnTypeItem(uilist, contents[i]))->setDrawArrow(arrows);
    522427
    523                 return;
    524             }
     428    uilist->blockSignals(false);
     429    uilist->refresh();
    525430
    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         }
    551     }
    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         }
    562 
    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     }
    580431}
    581432
    582 QString MythControls::RefreshKeyInformationKeyList(void)
     433/** \brief Update the right list. */
     434void MythControls::UpdateRightList(void)
    583435{
    584     if ((m_leftListType != kKeyList) && (m_rightListType != kKeyList))
    585         return "";
     436    // get the selected item in the right list.
     437    QString rtstr = m_leftList->GetItemCurrent()->text();
    586438
    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)
     439    switch(m_currentView)
    597440    {
    598         list = m_keyToBindingsMap[display_to_key(GetCurrentKey())];
     441    case kActionsByContext:
     442        SetListContents(m_rightList, *(m_contexts[rtstr]));
     443        break;
     444    case kKeysByContext:
     445        SetListContents(m_rightList, m_bindings->GetContextKeys(rtstr));
     446        break;
     447    case kContextsByKey:
     448        SetListContents(m_rightList, m_bindings->GetKeyContexts(rtstr));
     449        break;
    599450    }
    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)
    643             break;
    644     }
    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;
    660451}
    661452
    662453/** \fn MythControls::RefreshKeyInformation(void)
     
    674465        return;
    675466    }
    676467
    677     if ((m_leftListType == kKeyList) || (m_rightListType == kKeyList))
    678     {
    679         m_description->SetText(RefreshKeyInformationKeyList());
    680         return;
    681     }
    682 
    683468    const QString context = GetCurrentContext();
    684469    const QString action  = GetCurrentAction();
    685470
     
    690475    for (uint i = 0; (i < keys.count()) &&
    691476             (i < Action::kMaximumNumberOfBindings); i++)
    692477    {
    693         m_actionButtons[i]->setText(key_to_display(keys[i]));
     478        m_actionButtons[i]->setText(keys[i]);
    694479    }
    695480}
    696481
     
    794579    return desc.mid(loc + 4);
    795580}
    796581
    797 /** \fn MythControls::LoadAll(const QString&)
     582/** \fn MythControls::Load(const QString&)
    798583 *  \brief Load the settings for a particular host.
    799584 *  \param hostname The host to load settings for.
    800585 */
     
    804589    m_bindings = new KeyBindings(hostname);
    805590    m_sortedContexts = m_bindings->GetContexts();
    806591
    807     m_sortedKeys.clear();
    808 
    809592    /* Alphabetic order, but jump and global at the top  */
    810593    m_sortedContexts.sort();
    811594    m_sortedContexts.remove(ActionSet::kJumpContext);
     
    822605        actions.sort();
    823606        m_contexts.insert(m_sortedContexts[i], new QStringList(actions));
    824607    }
    825 
    826     RefreshKeyBindings();
    827     UpdateLists();
    828608}
    829609
    830610/** \fn MythControls::DeleteKey(void)
     
    846626        return;
    847627    }
    848628
    849     BindingList *list = m_keyToBindingsMap[key];
    850     Binding *binding = NULL;
     629    ConfirmMenu popup(gContext->GetMainWindow(), tr("Delete this binding?"));
    851630
    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();
     631    if (popup.GetOption() != ConfirmMenu::kConfirm)
    863632        return;
    864     }
    865633
    866     if (binding->contextFrom != context)
     634    if (!m_bindings->RemoveActionKey(context, action, key))
    867635    {
    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     {
    886636        InvalidBindingPopup popup(gContext->GetMainWindow());
    887637        popup.GetOption();
    888638        return;
    889639    }
    890640
    891     RefreshKeyBindings();
    892641    RefreshKeyInformation();
    893642}
    894643
     
    977726        m_bindings->AddActionKey(context, action, key);
    978727    }
    979728
    980     RefreshKeyBindings();
    981729    RefreshKeyInformation();
    982730}
    983731
    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
     732/** \brief Create the view menu.
     733 *  \param window The main window.
     734 *  \param current The current view type.
    991735 */
    992 void MythControls::AddBindings(QDict<Binding> &bindings,
    993                                const QString    &context,
    994                                const QString    &contextParent,
    995                                int               bindlevel)
     736ViewMenu::ViewMenu(MythMainWindow *window, ViewType current)
     737    : MythPopupBox(window, "mcviewmenu")
    996738{
    997     QStringList actions = m_bindings->GetActions(context);
     739    addLabel(tr("Change View"), Large, false);
    998740
    999     for (uint i = 0; i < actions.size(); i++)
     741    switch(current)
    1000742    {
    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         }
     743    case kKeysByContext:
     744        addButton(tr("Actions By Context"),     this,   SLOT(ActionsByContext()));
     745        addButton(tr("Contexts By Key"),        this,   SLOT(ContextsByKey()));
     746        break;
     747    case kContextsByKey:
     748        addButton(tr("Actions By Context"),     this,   SLOT(ActionsByContext()));
     749        addButton(tr("Keys By Context"),        this,   SLOT(KeysByContext()));
     750        break;
     751    default:
     752        addButton(tr("Keys By Context"),        this,   SLOT(KeysByContext()));
     753        addButton(tr("Contexts By Key"),        this,   SLOT(ContextsByKey()));
     754        break; 
    1020755    }
    1021 }
    1022756
    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;
     757    addButton(tr("Cancel"), this, SLOT(Cancel()))->setFocus();
    1048758}
    1049759
    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");
    1134             break;
    1135         case kKeyList:
    1136             return tr("Keys");
    1137             break;
    1138         case kActionList:
    1139             return tr("Actions");
    1140             break;
    1141         default:
    1142             return "";
    1143     }
    1144 }
    1145 
    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));
    1189 }
    1190 
    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 
    1207760/* 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 = QDeepCopy<QStringList>(m_actionSet.GetContextStrings());
     65    ctxts.sort();
     66    return ctxts;
    5967}
    6068
    6169/** \fn KeyBindings::GetActions(const QString&) const
     
    95103        (m_actionSet.GetKeys(ActionID(context_name, action_name)));
    96104}
    97105
     106/** \fn KeyBindings::GetContextKeys(const QString &) const
     107 *  \brief Get the keys within a context.
     108 *  \param context The context name.
     109 *  \return A list of the keys in the context.
     110 */
     111QStringList     KeyBindings::GetContextKeys(const QString & context) const
     112{
     113     return m_actionSet.GetContextKeys(context);
     114}
     115
     116/** \fn KeyBindings::GetKeyContexts(const QString &) const
     117 *  \brief Get the context names in which a key is bound.
     118 *  \return A list of context names in which a key is bound.
     119 */
     120QStringList KeyBindings::GetKeyContexts(const QString &key) const
     121{
     122    ActionList actions = m_actionSet.GetActions(key);
     123    QStringList contexts;
     124
     125    for (size_t i = 0; i < actions.size(); i++)
     126    {
     127        QString context = actions[i].GetContext();
     128        if (!contexts.contains(context))
     129            contexts.push_back(context);
     130    }   
     131
     132    return contexts;
     133}
     134
    98135/** \fn KeyBindings::GetActionDescription(const QString&,const QString&) const
    99136 *  \brief Get an action's description.
    100137 *  \param context_name The name of the context.
  • mythcontrols/actionset.cpp

     
    6262
    6363    ActionList &ids = m_keyToActionMap[key];
    6464    ids.push_back(id);
     65
    6566    SetModifiedFlag(id, true); 
    6667
    6768    return true;
     
    7576 *
    7677 *  \param id The action identifier to remove from.
    7778 *  \param key The key to remove.
     79 *
     80 *  \todo Remove the actionlist from the m_keyToActionMap if the key
     81 *  is no longer bound to any actions.
    7882 */
    7983bool ActionSet::Remove(const ActionID &id, const QString &key)
    8084{
     
    8791        return false;
    8892
    8993    m_keyToActionMap[key].remove(id);
     94
     95    // remove the key if there isn't anything bound to it.
     96    if (m_keyToActionMap[key].isEmpty())
     97        m_keyToActionMap.remove(key);
     98
    9099    SetModifiedFlag(id, true);
    91100
    92101    return true;           
     
    242251    return keys;
    243252}
    244253
     254QStringList     ActionSet::GetContextKeys(const QString & context_name) const
     255{
     256    QStringList keys;
     257    Context *c = m_contexts[context_name];
     258
     259    QDictIterator<Action> it(*c);
     260    for (;it.current(); ++it)
     261    {
     262        QStringList akeys = (*it)->GetKeys();
     263        for (size_t i = 0; i < akeys.size(); i++)
     264        {
     265                keys.append(akeys[i]);
     266        }
     267        keys.sort();
     268    }
     269
     270    return keys;
     271}
     272
     273/** \brief Get all keys (from every context) to which an action is bound.
     274 */
     275QStringList ActionSet::GetAllKeys(void) const
     276{
     277    QStringList keys;
     278
     279    QMap<QString, ActionList>::ConstIterator it;
     280
     281    for (it = m_keyToActionMap.begin(); it != m_keyToActionMap.end(); ++it)
     282        keys.push_back(it.key());
     283
     284    return keys;
     285}
     286
     287
    245288/** \fn ActionSet::GetDescription(const ActionID&) const
    246289 *  \brief Returns the description of an action by its identifier.
    247290 *         (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{
    34   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) {}
     40    Q_OBJECT
    4041
    41   public:
    42     QString key;
    43     QString context;
    44     QString contextFrom;
    45     QString action;
    46     int     bindlevel;
     42public:
     43
     44    /// \brief The available views
     45    enum actions { kContextAction, kContextKey, kKeyContext, kCancel};
     46
     47    /** \brief Creates a new view dialog box.
     48     *  \param window The main MythTV window.
     49     *  \param first The first button's caption
     50     *  \param second The second button's caption
     51     */
     52    ViewMenu(MythMainWindow *window, ViewType current);
     53
     54    /// \brief Execute the option popup.
     55    int GetOption(void) { return ExecPopup(this,SLOT(Cancel())); }
     56
     57public slots:
     58
     59    void ActionsByContext(void) { done(ViewMenu::kContextAction); }
     60    void KeysByContext(void)    { done(ViewMenu::kContextKey); }
     61    void ContextsByKey(void)    { done(ViewMenu::kKeyContext); }
     62    void Cancel(void)                   { done(ViewMenu::kCancel); }
    4763};
    48 typedef QPtrList<Binding> BindingList;
    4964
    5065/** \class MythControls
    5166 *  \brief The myth controls configuration class.
     
    7792    // Commands
    7893    bool    LoadUI(void);
    7994    void    RefreshKeyInformation(void);
    80     QString RefreshKeyInformationKeyList(void);
    81     void    RefreshRightList(void);
    82     void    UpdateLists(void);
    8395    void    LoadData(const QString &hostname);
    8496    void    ChangeButtonFocus(int direction);
    8597    void    ChangeListFocus(UIListBtnType *focus, UIListBtnType *unfocus);
    86     void    AddBindings(QDict<Binding> &bindings, const QString &context,
    87                         const QString &contextParent, int bindlevel);
     98    void        ChangeView(void);
     99    void    SetListContents(UIListBtnType *uilist,
     100                            const QStringList & contents,
     101                            bool arrows = false);
     102    void    UpdateRightList(void);
    88103
    89104    // Gets
    90     BindingList *GetKeyBindings(const QString &context);
    91105    uint         GetCurrentButton(void) const;
    92106
    93107    // Functions
     
    99113    void DeleteKey(void);
    100114    void LeftSelected(UIListBtnTypeItem *item);
    101115    void RightSelected(UIListBtnTypeItem *item);
    102     void SortKeyList(QStringList &keys);
    103     void RefreshKeyBindings(void);
    104116    bool JumpTo(QKeyEvent *e);
    105117    /// \brief Save the bindings to the Database.
    106118    void Save(void) { m_bindings->CommitChanges(); }
    107119
    108120  private:
     121    ViewType           m_currentView;
    109122    UIType            *m_focusedUIElement;
    110123    UIListBtnType     *m_leftList;
    111124    UIListBtnType     *m_rightList;
     
    117130    KeyBindings       *m_bindings;
    118131    LayerSet          *m_container;
    119132    QStringList        m_sortedContexts; ///< sorted list of contexts
    120     QStringList        m_sortedKeys;     ///< sorted list of keys
    121133    QDict<QStringList> m_contexts;       ///< actions for a given context
    122     QDict<BindingList> m_contextToBindingsMap;
    123     QDict<BindingList> m_keyToBindingsMap;
    124134    ListType           m_leftListType;
    125135    ListType           m_rightListType;
    126136};
  • 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