Ticket #2078: 2078-v2.patch
File 2078-v2.patch, 37.6 KB (added by , 19 years ago) |
---|
-
mythcontrols/actionset.h
58 58 QStringList GetActionStrings(const QString &context_name) const; 59 59 QString GetKeyString(const ActionID &id) const; 60 60 QStringList GetKeys(const ActionID &id) const; 61 QStringList GetContextKeys(const QString &context_name) const; 62 QStringList GetAllKeys(void) const; 61 63 QString GetDescription(const ActionID &id) const; 62 64 const ActionList& GetActions(const QString &key) const; 63 65 /// \brief Returns the appropriate container of modified actions -
mythcontrols/keygrabber.h
94 94 Q_OBJECT 95 95 96 96 public: 97 enum actions { kSave, kC ancel, };97 enum actions { kSave, kChangeView, kCancel, }; 98 98 99 99 /// \brief Create a new action window. Does not pop-up menu. 100 100 OptionsMenu(MythMainWindow *window); … … 103 103 int GetOption(void) { return ExecPopup(this,SLOT(Cancel())); } 104 104 105 105 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); } 108 109 }; 109 110 110 111 -
mythcontrols/mythcontrols.cpp
2 2 /** 3 3 * @file mythcontrols.cpp 4 4 * @author Micah F. Galizia <mfgalizi@csd.uwo.ca> 5 * @brief Main header for mythcontrols.5 * @brief Main mythcontrols class. 6 6 * 7 7 * Note that the keybindings are fetched all at once, and cached for 8 8 * this host. This avoids pelting the database everytime the user … … 40 40 #include "mythcontrols.h" 41 41 #include "keygrabber.h" 42 42 43 static QString key_to_display(const QString &key);44 static QString display_to_key(const QString &key);45 46 43 #define LOC QString("MythControls: ") 47 44 #define LOC_ERR QString("MythControls, Error: ") 45 #define CAPTION_CONTEXT QString("Contexts") 46 #define CAPTION_ACTION QString("Actions") 47 #define CAPTION_KEY QString("Keys") 48 48 49 49 /** \fn MythControls::MythControls(MythMainWindow*, bool&) 50 50 * \brief Creates a new MythControls wizard … … 53 53 */ 54 54 MythControls::MythControls(MythMainWindow *parent, bool &ok) 55 55 : MythThemedDialog(parent, "controls", "controls-", "controls"), 56 m_currentView(kActionsByContext), 56 57 m_focusedUIElement(NULL), 57 58 m_leftList(NULL), m_rightList(NULL), 58 59 m_description(NULL), … … 71 72 m_rightListType = kActionList; 72 73 73 74 LoadData(gContext->GetHostName()); 74 RefreshKeyInformation();75 75 76 /* start off with the actions by contexts view */ 77 m_currentView = kActionsByContext; 78 SetListContents(m_leftList, m_bindings->GetContexts(), true); 79 UpdateRightList(); 80 76 81 connect(m_leftList, SIGNAL(itemSelected( UIListBtnTypeItem*)), 77 82 this, SLOT( LeftSelected( UIListBtnTypeItem*))); 78 83 connect(m_rightList, SIGNAL(itemSelected( UIListBtnTypeItem*)), … … 221 226 RefreshKeyInformation(); 222 227 } 223 228 229 /// \brief Chagne the view. 230 void MythControls::ChangeView(void) 231 { 232 ViewMenu popup(gContext->GetMainWindow()); 233 QStringList contents; 234 QString leftcaption, rightcaption; 235 236 switch(popup.GetOption()) 237 { 238 case ViewMenu::kContextAction: 239 leftcaption = tr(CAPTION_CONTEXT); 240 rightcaption = tr(CAPTION_ACTION); 241 m_currentView = kActionsByContext; 242 contents = m_bindings->GetContexts(); 243 break; 244 case ViewMenu::kContextKey: 245 leftcaption = tr(CAPTION_CONTEXT); 246 rightcaption = tr(CAPTION_KEY); 247 m_currentView = kKeysByContext; 248 contents = m_bindings->GetContexts(); 249 break; 250 case ViewMenu::kKeyContext: 251 leftcaption = tr(CAPTION_KEY); 252 rightcaption = tr(CAPTION_CONTEXT); 253 m_currentView = kContextsByKey; 254 contents = m_bindings->GetKeys(); 255 break; 256 default: 257 break; 258 } 259 260 m_leftDescription->SetText(leftcaption); 261 m_rightDescription->SetText(rightcaption); 262 263 SetListContents(m_leftList, contents, true); 264 RefreshKeyInformation(); 265 UpdateRightList(); 266 267 if (m_focusedUIElement != m_leftList) 268 { 269 m_focusedUIElement->looseFocus(); 270 m_focusedUIElement = m_leftList; 271 m_focusedUIElement->takeFocus(); 272 } 273 } 274 224 275 void MythControls::keyPressEvent(QKeyEvent *e) 225 276 { 226 277 bool handled = false; … … 238 289 m_focusedUIElement->looseFocus(); 239 290 240 291 OptionsMenu popup(gContext->GetMainWindow()); 241 if (OptionsMenu::kSave == popup.GetOption())242 Save();243 292 293 switch(popup.GetOption()) 294 { 295 case OptionsMenu::kSave: 296 Save(); 297 break; 298 case OptionsMenu::kChangeView: 299 ChangeView(); 300 break; 301 default: 302 break; 303 } 304 244 305 m_focusedUIElement->takeFocus(); 245 306 } 246 307 else if (action == "SELECT") … … 248 309 if (m_focusedUIElement == m_leftList) 249 310 ChangeListFocus(m_rightList, m_leftList); 250 311 else if (m_focusedUIElement == m_rightList) 251 ChangeButtonFocus(0); 312 { 313 if (m_currentView == kActionsByContext) 314 ChangeButtonFocus(0); 315 else 316 handled = false; 317 } 252 318 else 253 319 { 254 320 QString key = GetCurrentKey(); … … 327 393 else if (m_focusedUIElement == m_rightList) 328 394 m_rightList->MoveDown(UIListBtnType::MovePage); 329 395 } 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 else347 {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 else368 {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 else389 {390 handled = false;391 }392 }393 396 else 394 397 { 395 398 handled = false; … … 397 400 } 398 401 399 402 if (!handled) 400 { 401 handled |= (!escape && JumpTo(e)); 402 if (!handled) 403 MythThemedDialog::keyPressEvent(e); 404 } 403 MythThemedDialog::keyPressEvent(e); 405 404 } 406 405 407 /** \fn MythControls::JumpTo(QKeyEvent*)408 * \brief Jump to a particular key binding409 * \param e key event to use as jump410 */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 else429 {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; // infinity450 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 477 406 /** \fn MythControls::LeftSelected(UIListBtnTypeItem*) 478 407 * \brief Refreshes the right list when an item in the 479 408 * left list is selected … … 482 411 { 483 412 m_leftList->refresh(); 484 413 m_rightList->blockSignals(true); 485 RefreshRightList();414 UpdateRightList(); 486 415 m_rightList->blockSignals(false); 487 416 m_rightList->refresh(); 488 417 } … … 497 426 RefreshKeyInformation(); 498 427 } 499 428 500 /** \fn MythControls::RefreshRightList(void) 501 * \brief Load the appropriate actions into the action list 429 430 /** \brief Set the contents of a list. 431 * \param list The list being changed. 432 * \param contents The contents of the list. 433 * \param arrows True to draw with arrows, otherwise arrows are not drawn. 502 434 */ 503 void MythControls::RefreshRightList(void) 435 void MythControls::SetListContents( 436 UIListBtnType *uilist, const QStringList &contents, bool arrows) 504 437 { 505 m_rightList->Reset();438 uilist->blockSignals(true); 506 439 507 if (!m_leftList->GetItemCurrent())508 return;440 // remove all strings from the current list 441 uilist->Reset(); 509 442 510 if (m_leftListType == kContextList) 443 // add each new string 444 for (size_t i = 0; i < contents.size(); i++) 511 445 { 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 } 446 UIListBtnTypeItem *item = new UIListBtnTypeItem(uilist, contents[i]); 447 item->setDrawArrow(arrows); 551 448 } 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 449 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 } 450 uilist->blockSignals(false); 451 uilist->refresh(); 580 452 } 581 453 582 QString MythControls::RefreshKeyInformationKeyList(void) 454 /** \brief Update the right list. */ 455 void MythControls::UpdateRightList(void) 583 456 { 584 if ((m_leftListType != kKeyList) && (m_rightListType != kKeyList))585 return "";457 // get the selected item in the right list. 458 UIListBtnTypeItem *item = m_leftList->GetItemCurrent(); 586 459 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) 460 if (item != NULL) 597 461 { 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 } 462 QString rtstr = item->text(); 604 463 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) 464 switch(m_currentView) 627 465 { 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) 466 case kActionsByContext: 467 SetListContents(m_rightList, *(m_contexts[rtstr])); 643 468 break; 469 case kKeysByContext: 470 SetListContents(m_rightList, m_bindings->GetContextKeys(rtstr)); 471 break; 472 case kContextsByKey: 473 SetListContents(m_rightList, m_bindings->GetKeyContexts(rtstr)); 474 break; 475 } 644 476 } 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; 477 else 478 VERBOSE(VB_IMPORTANT, QString("Left List Returned Null!")); 660 479 } 661 480 662 481 /** \fn MythControls::RefreshKeyInformation(void) … … 674 493 return; 675 494 } 676 495 677 if ((m_leftListType == kKeyList) || (m_rightListType == kKeyList))678 {679 m_description->SetText(RefreshKeyInformationKeyList());680 return;681 }682 683 496 const QString context = GetCurrentContext(); 684 497 const QString action = GetCurrentAction(); 685 498 … … 690 503 for (uint i = 0; (i < keys.count()) && 691 504 (i < Action::kMaximumNumberOfBindings); i++) 692 505 { 693 m_actionButtons[i]->setText(key _to_display(keys[i]));506 m_actionButtons[i]->setText(keys[i]); 694 507 } 695 508 } 696 509 … … 731 544 QString MythControls::GetCurrentAction(void) const 732 545 { 733 546 if (m_leftListType == kActionList) 734 return m_leftList->GetItemCurrent()->text(); 547 { 548 if (m_leftList && m_leftList->GetItemCurrent()) 549 return QDeepCopy<QString>(m_leftList->GetItemCurrent()->text()); 550 return QString::null; 551 } 735 552 736 553 if (m_focusedUIElement == m_leftList) 737 554 return QString::null; 738 555 556 if (!m_rightList || !m_rightList->GetItemCurrent()) 557 return QString::null; 558 739 559 QString desc = m_rightList->GetItemCurrent()->text(); 740 560 if (m_leftListType == kContextList && m_rightListType == kActionList) 741 return desc;561 return QDeepCopy<QString>(desc); 742 562 743 563 int loc = desc.find(" => "); 744 564 if (loc == -1) … … 794 614 return desc.mid(loc + 4); 795 615 } 796 616 797 /** \fn MythControls::Load All(const QString&)617 /** \fn MythControls::LoadData(const QString&) 798 618 * \brief Load the settings for a particular host. 799 619 * \param hostname The host to load settings for. 800 620 */ … … 804 624 m_bindings = new KeyBindings(hostname); 805 625 m_sortedContexts = m_bindings->GetContexts(); 806 626 807 m_sortedKeys.clear();808 809 627 /* Alphabetic order, but jump and global at the top */ 810 628 m_sortedContexts.sort(); 811 629 m_sortedContexts.remove(ActionSet::kJumpContext); … … 822 640 actions.sort(); 823 641 m_contexts.insert(m_sortedContexts[i], new QStringList(actions)); 824 642 } 825 826 RefreshKeyBindings();827 UpdateLists();828 643 } 829 644 830 645 /** \fn MythControls::DeleteKey(void) … … 846 661 return; 847 662 } 848 663 849 BindingList *list = m_keyToBindingsMap[key]; 850 Binding *binding = NULL; 664 ConfirmMenu popup(gContext->GetMainWindow(), tr("Delete this binding?")); 851 665 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(); 666 if (popup.GetOption() != ConfirmMenu::kConfirm) 863 667 return; 864 }865 668 866 if ( binding->contextFrom != context)669 if (!m_bindings->RemoveActionKey(context, action, key)) 867 670 { 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 else876 {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 {886 671 InvalidBindingPopup popup(gContext->GetMainWindow()); 887 672 popup.GetOption(); 888 673 return; 889 674 } 890 675 891 RefreshKeyBindings();892 676 RefreshKeyInformation(); 893 677 } 894 678 … … 977 761 m_bindings->AddActionKey(context, action, key); 978 762 } 979 763 980 RefreshKeyBindings();981 764 RefreshKeyInformation(); 982 765 } 983 766 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 767 /** \fn ViewMenu::ViewMenu(MythMainWindow*, ViewType) 768 * \brief Creates a new view dialog box. 769 * \param window The main MythTV window. 991 770 */ 992 void MythControls::AddBindings(QDict<Binding> &bindings, 993 const QString &context, 994 const QString &contextParent, 995 int bindlevel) 771 ViewMenu::ViewMenu(MythMainWindow *window) : 772 MythPopupBox(window, "mcviewmenu") 996 773 { 997 QStringList actions = m_bindings->GetActions(context); 998 999 for (uint i = 0; i < actions.size(); i++) 1000 { 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 } 774 addLabel(tr("Change View"), Large, false); 775 addButton(tr("Actions By Context"), this, SLOT(ActionsByContext())); 776 addButton(tr("Contexts By Key"), this, SLOT(ContextsByKey())); 777 addButton(tr("Keys By Context"), this, SLOT(KeysByContext())); 778 addButton(tr("Cancel"), this, SLOT(Cancel()))->setFocus(); 1021 779 } 1022 780 1023 /** \fn MythControls::GetKeyBindings(const QString&)1024 * \brief Create a BindingList for the specified context1025 * \param context the context for which a BindingList should be created1026 * \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 information1052 */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 duplicates1087 * \param keys the list of keys to sort1088 */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) const1129 {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 1207 781 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
mythcontrols/keybindings.cpp
49 49 LoadJumppoints(); 50 50 } 51 51 52 /** \brief Returns a list of all keys bound to an action. */ 53 QStringList KeyBindings::GetKeys(void) const 54 { 55 return m_actionSet.GetAllKeys(); 56 } 57 52 58 /** \fn KeyBindings::GetContexts(void) const 53 59 * \brief Returns a list of the context names. 54 60 * \note The returned list is a copy and can be modified without side-effects. 55 61 */ 56 62 QStringList KeyBindings::GetContexts(void) const 57 63 { 58 return QDeepCopy<QStringList>(m_actionSet.GetContextStrings()); 64 QStringList ctxts = 65 QDeepCopy<QStringList>(m_actionSet.GetContextStrings()); 66 ctxts.sort(); 67 return ctxts; 59 68 } 60 69 61 70 /** \fn KeyBindings::GetActions(const QString&) const … … 95 104 (m_actionSet.GetKeys(ActionID(context_name, action_name))); 96 105 } 97 106 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 */ 112 QStringList 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 */ 121 QStringList 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 98 136 /** \fn KeyBindings::GetActionDescription(const QString&,const QString&) const 99 137 * \brief Get an action's description. 100 138 * \param context_name The name of the context. -
mythcontrols/actionset.cpp
62 62 63 63 ActionList &ids = m_keyToActionMap[key]; 64 64 ids.push_back(id); 65 SetModifiedFlag(id, true); 65 SetModifiedFlag(id, true); 66 66 67 67 return true; 68 68 } … … 75 75 * 76 76 * \param id The action identifier to remove from. 77 77 * \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. 78 81 */ 79 82 bool ActionSet::Remove(const ActionID &id, const QString &key) 80 83 { … … 87 90 return false; 88 91 89 92 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 90 98 SetModifiedFlag(id, true); 91 99 92 return true; 100 return true; 93 101 } 94 102 95 103 /** \fn ActionSet::Replace(const ActionID&,const QString&,const QString&) … … 118 126 m_keyToActionMap[newkey].push_back(id); 119 127 SetModifiedFlag(id, true); 120 128 121 return true; 129 return true; 122 130 } 123 131 124 132 /** \fn ActionSet::SetModifiedFlag(const ActionID&, bool) … … 242 250 return keys; 243 251 } 244 252 253 QStringList 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 */ 274 QStringList 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 245 286 /** \fn ActionSet::GetDescription(const ActionID&) const 246 287 * \brief Returns the description of an action by its identifier. 247 288 * (note: result not thread-safe) -
mythcontrols/mythcontrols.h
29 29 30 30 #include "keybindings.h" 31 31 32 class Binding 32 33 typedef enum { kActionsByContext, kKeysByContext, kContextsByKey, } ViewType; 34 35 /** \class ViewMenu 36 * \brief Prompts the user to change the view. 37 */ 38 class ViewMenu : public MythPopupBox 33 39 { 40 Q_OBJECT 41 34 42 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); 40 44 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); } 47 56 }; 48 typedef QPtrList<Binding> BindingList;49 57 50 58 /** \class MythControls 51 59 * \brief The myth controls configuration class. … … 77 85 // Commands 78 86 bool LoadUI(void); 79 87 void RefreshKeyInformation(void); 80 QString RefreshKeyInformationKeyList(void);81 void RefreshRightList(void);82 void UpdateLists(void);83 88 void LoadData(const QString &hostname); 84 89 void ChangeButtonFocus(int direction); 85 90 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); 88 96 89 97 // Gets 90 BindingList *GetKeyBindings(const QString &context);91 98 uint GetCurrentButton(void) const; 92 99 93 100 // Functions … … 99 106 void DeleteKey(void); 100 107 void LeftSelected(UIListBtnTypeItem *item); 101 108 void RightSelected(UIListBtnTypeItem *item); 102 void SortKeyList(QStringList &keys);103 void RefreshKeyBindings(void);104 109 bool JumpTo(QKeyEvent *e); 105 110 /// \brief Save the bindings to the Database. 106 111 void Save(void) { m_bindings->CommitChanges(); } 107 112 108 113 private: 114 ViewType m_currentView; 109 115 UIType *m_focusedUIElement; 110 116 UIListBtnType *m_leftList; 111 117 UIListBtnType *m_rightList; … … 117 123 KeyBindings *m_bindings; 118 124 LayerSet *m_container; 119 125 QStringList m_sortedContexts; ///< sorted list of contexts 120 QStringList m_sortedKeys; ///< sorted list of keys121 126 QDict<QStringList> m_contexts; ///< actions for a given context 122 QDict<BindingList> m_contextToBindingsMap;123 QDict<BindingList> m_keyToBindingsMap;124 127 ListType m_leftListType; 125 128 ListType m_rightListType; 126 129 }; -
mythcontrols/keybindings.h
59 59 void CommitChanges(void); 60 60 61 61 // Gets 62 QStringList GetKeys(void) const; 62 63 QStringList GetContexts(void) const; 63 64 QStringList GetActions(const QString &context) const; 64 65 void GetKeyActions(const QString &key, ActionList &list) const; 65 66 QStringList GetActionKeys(const QString &context_name, 66 67 const QString &action_name) const; 68 QStringList GetContextKeys(const QString &context) const; 69 QStringList GetKeyContexts(const QString &key) const; 67 70 QString GetActionDescription(const QString &context_name, 68 71 const QString &action_name) const; 69 72 bool HasMandatoryBindings(void) const; -
mythcontrols/controls-ui.xml
46 46 <container name="controls"> 47 47 <area>20,20,780,450</area> 48 48 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 55 49 <textarea name="leftdesc" draworder="1" align="center"> 56 50 <font>info</font> 57 <area>0, 40,370,20</area>51 <area>0,0,370,20</area> 58 52 <value>Contexts</value> 59 53 </textarea> 60 54 61 55 <listbtnarea name="leftlist" draworder="0"> 62 <area>0, 60,370,380</area>56 <area>0,30,370,420</area> 63 57 <gradient type="unselected" start="#505050" end="#000000" alpha="100"/> 64 58 <gradient type="selected" start="#52CA38" end="#349838" alpha="255"/> 65 59 <fcnfont name="active" function="active"/> … … 69 63 70 64 <textarea name="rightdesc" draworder="1" align="center"> 71 65 <font>info</font> 72 <area>390, 40,370,20</area>66 <area>390,0,370,20</area> 73 67 <value>Actions</value> 74 68 </textarea> 75 69 76 70 <listbtnarea name="rightlist" draworder="0"> 77 <area>390, 60,370,380</area>71 <area>390,30,370,420</area> 78 72 <gradient type="unselected" start="#505050" end="#000000" alpha="100"/> 79 73 <gradient type="selected" start="#52CA38" end="#349838" alpha="255"/> 80 74 <fcnfont name="active" function="active"/> -
mythcontrols/keygrabber.cpp
126 126 { 127 127 addLabel(tr("Options"), Large, false); 128 128 addButton(QObject::tr("Save"), this, SLOT(Save())); 129 addButton(QObject::tr("Change View"), this, SLOT(ChangeView())); 129 130 addButton(QObject::tr("Cancel"), this, SLOT(Cancel()))->setFocus(); 130 131 } 131 132