Ticket #590: mythcontrols-usedkeys3.patch
File mythcontrols-usedkeys3.patch, 39.8 KB (added by , 18 years ago) |
---|
-
mythcontrols.cpp
46 46 #include "keygrabber.h" 47 47 48 48 49 static QMap<int,QString> FindContexts(const QString &context) 50 { 51 QMap<int,QString> retval; 52 retval.clear(); 53 if (context != JUMP_CONTEXT) retval[-1] = JUMP_CONTEXT; 54 retval[0] = context; 55 if (context != JUMP_CONTEXT && context != GLOBAL_CONTEXT) 56 { 57 if (context == "TV Editting") 58 retval[1] = "TV Playback"; 59 retval[2] = GLOBAL_CONTEXT; 60 if (context != "qt") 61 retval[3] = "qt"; 62 } 63 return retval; 64 } 49 65 66 static const QString KeyToDisplay(const QString key) 67 { 68 if (key.left(6) == "remote") 69 return "[" + key.mid(6) + "]"; 70 else 71 return key; 72 } 73 74 static const QString DisplayToKey(const QString key) 75 { 76 if (key.left(1) == "[" && key != "[") 77 return "remote" + key.mid(1,key.length()-2); 78 else 79 return key; 80 } 81 50 82 /* comments in header */ 51 83 MythControls::MythControls (MythMainWindow *parent, bool& ui_ok) 52 84 :MythThemedDialog(parent, "controls", "controls-", "controls") … … 60 92 /* load up the ui components */ 61 93 if ((ui_ok = loadUI())) 62 94 { 95 leftType = kContextList; 96 rightType = kActionList; 97 63 98 /* for starters, load this host */ 64 99 loadHost(gContext->GetHostName()); 65 100 … … 67 102 refreshKeyInformation(); 68 103 69 104 /* capture the signals we want */ 70 connect( ContextList, SIGNAL(itemSelected(UIListBtnTypeItem*)),71 this, SLOT( contextSelected(UIListBtnTypeItem*)));72 connect( ActionList, SIGNAL(itemSelected(UIListBtnTypeItem*)),73 this, SLOT( actionSelected(UIListBtnTypeItem*)));105 connect(LeftList, SIGNAL(itemSelected(UIListBtnTypeItem*)), 106 this, SLOT(leftSelected(UIListBtnTypeItem*))); 107 connect(RightList, SIGNAL(itemSelected(UIListBtnTypeItem*)), 108 this, SLOT(rightSelected(UIListBtnTypeItem*))); 74 109 75 110 } 76 111 } … … 99 134 VERBOSE(VB_ALL, "MythControls: No controls container in theme"); 100 135 retval = false; 101 136 } 102 else if (( ContextList = getUIListBtnType("contextlist")) == NULL) {103 VERBOSE(VB_ALL, "MythControls: No context_list in theme");137 else if ((LeftList = getUIListBtnType("leftlist")) == NULL) { 138 VERBOSE(VB_ALL, "MythControls: No leftlist in theme"); 104 139 retval = false; 105 140 } 106 else if (( ActionList = getUIListBtnType("actionlist")) == NULL) {107 VERBOSE(VB_ALL, "MythControls: No ActionList in theme");141 else if ((RightList = getUIListBtnType("rightlist")) == NULL) { 142 VERBOSE(VB_ALL, "MythControls: No rightList in theme"); 108 143 retval = false; 109 144 } 110 145 else { 146 LeftDesc = getUITextType("leftdesc"); 147 RightDesc = getUITextType("rightdesc"); 111 148 /* focus the context list by default */ 112 focused = ContextList;113 ContextList->calculateScreenArea();114 ContextList->SetActive(true);115 ActionList->calculateScreenArea();116 ActionList->SetActive(false);149 focused = LeftList; 150 LeftList->calculateScreenArea(); 151 LeftList->SetActive(true); 152 RightList->calculateScreenArea(); 153 RightList->SetActive(false); 117 154 } 118 155 119 156 /* Check that all the buttons are there */ … … 155 192 156 193 void MythControls::focusButton(int direction) 157 194 { 195 if (leftType != kContextList || rightType != kActionList) 196 return; 158 197 if (direction == 0) 159 198 { 160 199 focused = ActionButtons[0]; 161 200 ActionButtons[0]->takeFocus(); 162 ActionList->looseFocus();163 ActionList->SetActive(false);201 RightList->looseFocus(); 202 RightList->SetActive(false); 164 203 } 165 204 else 166 205 { … … 203 242 refreshKeyInformation(); 204 243 } 205 244 206 207 208 245 void MythControls::keyPressEvent(QKeyEvent *e) 209 246 { 210 247 bool handled = false; 248 bool escape = false; 211 249 QStringList actions; 212 250 gContext->GetMainWindow()->TranslateKeyPress("Controls", e, actions); 213 251 … … 218 256 219 257 if (action == "MENU" || action == "INFO") 220 258 { 259 focused->looseFocus(); 221 260 OptionsMenu popup(gContext->GetMainWindow()); 222 if (popup.getOption() == OptionsMenu::SAVE) save(); 261 int a = (int)popup.getOption(); 262 switch (a) { 263 case (int)OptionsMenu::SAVE: 264 save(); 265 break; 266 } 267 focused->takeFocus(); 268 // if (popup.getOption() == OptionsMenu::SAVE) save(); 223 269 } 224 270 else if (action == "SELECT") 225 271 { 226 if (focused == ContextList)227 switchListFocus( ActionList, ContextList);228 else if (focused == ActionList)272 if (focused == LeftList) 273 switchListFocus(RightList, LeftList); 274 else if (focused == RightList) 229 275 focusButton(0); 230 276 else { 231 ActionMenu popup(gContext->GetMainWindow()); 232 int result = popup.getOption(); 233 if (result == ActionMenu::SET) addKeyToAction(); 234 else if (result == ActionMenu::REMOVE) deleteKey(); 277 QString key = getCurrentKey(); 278 if (!key.isEmpty()) 279 { 280 ActionMenu popup(gContext->GetMainWindow()); 281 int result = popup.getOption(); 282 if (result == ActionMenu::SET) addKeyToAction(); 283 else if (result == ActionMenu::REMOVE) deleteKey(); 284 } else // for blank keys, no reason to ask what to do 285 addKeyToAction(); 235 286 } 236 287 } 237 288 else if (action == "ESCAPE") 238 289 { 239 if (focused == ContextList) 290 escape = true; 291 if (focused == LeftList) 240 292 { 241 293 handled = false; 242 294 if (key_bindings->hasChanges()) … … 249 301 } 250 302 } 251 303 } 252 else if (focused == ActionList)253 switchListFocus( ContextList, ActionList);304 else if (focused == RightList) 305 switchListFocus(LeftList, RightList); 254 306 else 255 switchListFocus( ActionList, NULL);307 switchListFocus(RightList, NULL); 256 308 } 257 309 else if (action == "UP") 258 310 { 259 if (focused == ContextList)260 ContextList->MoveUp();261 else if (focused == ActionList)262 ActionList->MoveUp();311 if (focused == LeftList) 312 LeftList->MoveUp(); 313 else if (focused == RightList) 314 RightList->MoveUp(); 263 315 } 264 316 else if (action == "DOWN") 265 317 { 266 if (focused == ContextList)267 ContextList->MoveDown();268 else if (focused == ActionList)269 ActionList->MoveDown();318 if (focused == LeftList) 319 LeftList->MoveDown(); 320 else if (focused == RightList) 321 RightList->MoveDown(); 270 322 } 271 323 else if (action == "LEFT") 272 324 { 273 if (focused== ActionList)274 switchListFocus( ContextList, ActionList);275 else if (focused != ContextList)325 if (focused==RightList) 326 switchListFocus(LeftList, RightList); 327 else if (focused != LeftList) 276 328 focusButton(-1); 277 329 } 278 330 else if (action == "RIGHT") 279 331 { 280 if (focused == ContextList)281 switchListFocus( ActionList, ContextList);282 else if (focused != ActionList)332 if (focused == LeftList) 333 switchListFocus(RightList, LeftList); 334 else if (focused != RightList) 283 335 focusButton(1); 284 336 } 285 337 else if (action == "PAGEUP") 286 338 { 287 if (focused == ContextList)288 ContextList->MoveUp(UIListBtnType::MovePage);289 else if (focused == ActionList)290 ActionList->MoveUp(UIListBtnType::MovePage);339 if (focused == LeftList) 340 LeftList->MoveUp(UIListBtnType::MovePage); 341 else if (focused == RightList) 342 RightList->MoveUp(UIListBtnType::MovePage); 291 343 } 292 344 else if (action == "PAGEDOWN") 293 345 { 294 if (focused == ContextList)295 ContextList->MoveDown(UIListBtnType::MovePage);296 else if (focused == ActionList)297 ActionList->MoveDown(UIListBtnType::MovePage);346 if (focused == LeftList) 347 LeftList->MoveDown(UIListBtnType::MovePage); 348 else if (focused == RightList) 349 RightList->MoveDown(UIListBtnType::MovePage); 298 350 } 351 else if (action == "1") 352 { 353 if (leftType != kContextList || rightType != kActionList) 354 { 355 leftType = kContextList; 356 rightType = kActionList; 357 updateLists(); 358 if (focused != LeftList) 359 switchListFocus(LeftList, 360 (focused == RightList) ? RightList : NULL); 361 } else handled = false; 362 } 363 else if (action == "2") 364 { 365 if (leftType != kContextList || rightType != kKeyList) 366 { 367 leftType = kContextList; 368 rightType = kKeyList; 369 updateLists(); 370 if (focused != LeftList) 371 switchListFocus(LeftList, 372 (focused == RightList) ? RightList : NULL); 373 } else handled = false; 374 } 375 else if (action == "3") 376 { 377 if (leftType != kKeyList || rightType != kContextList) 378 { 379 leftType = kKeyList; 380 rightType = kContextList; 381 updateLists(); 382 if (focused != LeftList) 383 switchListFocus(LeftList, 384 (focused == RightList) ? RightList : NULL); 385 } else handled = false; 386 } 299 387 else handled = false; 300 388 } 301 389 390 if (handled) return; 391 392 if (!escape && JumpTo(e)) handled = true; 393 302 394 if (!handled) 303 395 MythThemedDialog::keyPressEvent(e); 304 396 } 305 397 306 void MythControls::contextSelected(UIListBtnTypeItem *item)398 bool MythControls::JumpTo(QKeyEvent *e) 307 399 { 308 ContextList->refresh(); 400 UIListBtnType *list = NULL; 401 if (focused == LeftList && leftType == kKeyList) list = LeftList; 402 if (focused == RightList && rightType == kKeyList) list = RightList; 403 if (!list) return false; 309 404 310 ActionList->blockSignals(true); 311 refreshActionList(getCurrentContext()); 312 ActionList->blockSignals(false); 405 QString key = e->text(); 406 if (key.left(6) == "remote") { 407 key = KeyToDisplay(key); 408 } else { 409 key = QString(QKeySequence(e->key())); 410 if (key.isEmpty()) return false; 411 QString modifiers = ""; 412 if (e->state()&Qt::ShiftButton) modifiers+="Shift+"; 413 if (e->state()&Qt::ControlButton) modifiers+="Ctrl+"; 414 if (e->state()&Qt::AltButton) modifiers+="Alt+"; 415 if (e->state()&Qt::MetaButton) modifiers+="Meta+"; 416 key = modifiers + key; 417 } 313 418 314 ActionList->refresh(); 419 UIListBtnTypeItem *b; 420 uint len = 1024; // infinity 421 if (list == RightList) 422 { 423 key = key + " "; 424 len = key.length(); 425 } 426 427 for (b = list->GetItemFirst(); b; b = list->GetItemNext(b)) 428 if (b->text().left(len) == key) break; 429 if (!b) return false; 430 431 int curpos = list->GetItemPos(list->GetItemCurrent()); 432 int newpos = list->GetItemPos(b); 433 434 if (newpos > curpos) 435 list->MoveDown(newpos - curpos); 436 else if (newpos < curpos) 437 list->MoveUp(curpos - newpos); 438 return true; 315 439 } 316 440 317 void MythControls::actionSelected(UIListBtnTypeItem *item) 441 442 void MythControls::leftSelected(UIListBtnTypeItem*) 318 443 { 319 ContextList->refresh(); 444 LeftList->refresh(); 445 RightList->blockSignals(true); 446 refreshRightList(); 447 RightList->blockSignals(false); 448 RightList->refresh(); 449 } 450 451 void MythControls::rightSelected(UIListBtnTypeItem*) 452 { 453 RightList->refresh(); 320 454 refreshKeyInformation(); 321 455 } 322 456 323 457 324 458 325 459 /* method description in header */ 326 void MythControls::refresh ActionList(const QString & context)460 void MythControls::refreshRightList() 327 461 { 328 ActionList->Reset();462 RightList->Reset(); 329 463 330 /* add all of the actions to the context list */ 331 QStringList *actions = m_contexts[getCurrentContext()]; 332 UIListBtnTypeItem *item; 333 for (size_t i = 0; i < actions->size(); i++) 334 item = new UIListBtnTypeItem(ActionList, (*actions)[i]); 464 if (LeftList->GetItemCurrent() == NULL) 465 return; 466 467 if (leftType == kContextList) 468 { 469 if (rightType == kActionList) 470 { 471 /* add all of the actions to the context list */ 472 QString context = LeftList->GetItemCurrent()->text(); 473 QStringList *actions = m_contexts[context]; 474 if (actions == NULL) 475 { 476 VERBOSE(VB_ALL, QString("MythControls: Unable to find actions for context %1").arg(context)); 477 return; 478 } 479 UIListBtnTypeItem *item; 480 for (size_t i = 0; i < actions->size(); i++) 481 item = new UIListBtnTypeItem(RightList, (*actions)[i]); 482 } 483 else if (rightType == kKeyList) 484 { 485 /* add all of the actions to the context list */ 486 QString context = LeftList->GetItemCurrent()->text(); 487 BindingList *list = contextKeys[context]; 488 if (list == NULL) 489 { 490 VERBOSE(VB_ALL, QString("MythControls: Unable to find keys for context %1").arg(context)); 491 return; 492 } 493 UIListBtnTypeItem *item; 494 for (BindingList::iterator it = list->begin(); it != list->end(); ++it) 495 { 496 binding_t *b = *it; 497 item = new UIListBtnTypeItem(RightList, KeyToDisplay(b->key) + " => " + b->action); 498 } 499 } 500 } else if (leftType == kKeyList && rightType == kContextList) 501 { 502 QString key = DisplayToKey(LeftList->GetItemCurrent()->text()); 503 BindingList *list = keyActions[key]; 504 if (list == NULL) 505 { 506 VERBOSE(VB_ALL, QString("MythControls: Unable to find actions for key %1").arg(key)); 507 return; 508 } 509 UIListBtnTypeItem *item; 510 BindingList::iterator it = list->begin(); 511 binding_t *b = *it; 512 for (size_t i = 0; i < contexts.size(); i++) 513 { 514 QString context = contexts[i]; 515 QString action = "<none>"; 516 if (b && b->context == context) 517 { 518 action = b->action; 519 ++it; 520 if (it != list->end()) b = *it; 521 else b = NULL; 522 } 523 item = new UIListBtnTypeItem(RightList, context + " => " + action); 524 } 525 } 335 526 } 336 527 337 528 338 339 529 /* comments in header */ 340 530 void MythControls::refreshKeyInformation() 341 531 { 342 532 /* get the description of the current action */ 343 533 QString desc; 344 534 345 if (focused == ContextList)535 if (focused == LeftList) 346 536 { 347 537 /* blank all keys on the context */ 348 538 for (size_t i = 0; i < Action::MAX_KEYS; i++) 349 539 ActionButtons[i]->setText(""); 350 540 } 351 else 352 { 541 else if (leftType == kKeyList || rightType == kKeyList) 542 { // Should show appropriate description 543 QString action = getCurrentAction(); 544 QString context = getCurrentContext(); 545 /* blank all keys on the context */ 546 for (size_t i = 0; i < Action::MAX_KEYS; i++) 547 ActionButtons[i]->setText(""); 548 if (!action.isEmpty()) 549 { 550 551 desc = key_bindings->getActionDescription(context, action); 552 553 BindingList *list = NULL; 554 if (leftType == kKeyList && rightType == kContextList) 555 { 556 QString key = getCurrentKey(); 557 list = keyActions[DisplayToKey(key)]; 558 } 559 else if (leftType == kContextList && rightType == kKeyList) 560 list = contextKeys[context]; 561 if (list) 562 { 563 QString searchKey; 564 if (rightType == kContextList) 565 searchKey = context; 566 else if (rightType == kActionList) 567 searchKey = action; 568 else if (rightType == kKeyList) 569 searchKey = DisplayToKey(getCurrentKey()); 570 binding_t *binding = NULL; 571 for (BindingList::iterator it = list->begin(); it != list->end(); ++it) 572 { 573 binding_t *b = *it; 574 switch (rightType) 575 { 576 case kContextList: 577 if (b->context == searchKey) binding = b; 578 break; 579 case kActionList: 580 if (b->action == searchKey) binding = b; 581 break; 582 case kKeyList: 583 if (b->key == searchKey) binding = b; 584 break; 585 } 586 if (binding) break; 587 } 588 589 if (binding) 590 { 591 if (desc.isEmpty() && context != binding->contextFrom) 592 desc = key_bindings->getActionDescription(binding->contextFrom, action); 593 desc += "\n" + tr("Binding comes from %1 context") 594 .arg(binding->contextFrom); 595 } 596 } 597 } 598 } else { 599 QString context = getCurrentContext(); 600 QString action = getCurrentAction(); 353 601 /* set the description */ 354 602 desc = key_bindings->getActionDescription(getCurrentContext(), 355 603 getCurrentAction()); … … 362 610 363 611 /* fill existing keys */ 364 612 for (i = 0; i < keys.count(); i++) 365 ActionButtons[i]->setText( keys[i]);613 ActionButtons[i]->setText(KeyToDisplay(keys[i])); 366 614 367 615 /* blank the other ones */ 368 616 for (; i < Action::MAX_KEYS; i++) … … 378 626 /* comments in header */ 379 627 QString MythControls::getCurrentContext(void) const 380 628 { 381 return ContextList->GetItemCurrent()->text(); 629 if (leftType == kContextList) 630 return LeftList->GetItemCurrent()->text(); 631 if (focused == LeftList) return ""; 632 633 QString desc = RightList->GetItemCurrent()->text(); 634 int loc = desc.find(" => "); 635 if (loc == -1) return ""; // Should not happen 636 if (rightType == kContextList) return desc.left(loc); 637 else return desc.mid(loc+4); 382 638 } 383 639 640 /* comments in header */ 641 QString MythControls::getCurrentAction(void) const 642 { 643 if (leftType == kActionList) 644 return LeftList->GetItemCurrent()->text(); 645 if (focused == LeftList) return ""; 384 646 647 QString desc = RightList->GetItemCurrent()->text(); 648 if (leftType == kContextList && rightType == kActionList) 649 return desc; 650 int loc = desc.find(" => "); 651 if (loc == -1) return ""; // Should not happen 652 if (rightType == kActionList) return desc.left(loc); 653 else 654 { 655 QString rv = desc.mid(loc+4); 656 if (rv == "<none>") return ""; 657 else return rv; 658 } 659 } 385 660 386 661 /* comments in header */ 387 QString MythControls::getCurrent Action(void) const662 QString MythControls::getCurrentKey(void) const 388 663 { 389 return (focused != ContextList) ? ActionList->GetItemCurrent()->text() : ""; 664 if (leftType == kKeyList) 665 return LeftList->GetItemCurrent()->text(); 666 if (focused == LeftList) return ""; 667 668 if (leftType == kContextList && rightType == kActionList) 669 { 670 QString context = getCurrentContext(); 671 QString action = getCurrentAction(); 672 size_t b = focusedButton(); 673 QStringList keys = key_bindings->getActionKeys(context, action); 674 if (b < keys.count()) return keys[b]; 675 else return ""; 676 } 677 678 QString desc = RightList->GetItemCurrent()->text(); 679 int loc = desc.find(" => "); 680 if (loc == -1) return ""; // Should not happen 681 if (rightType == kKeyList) return desc.left(loc); 682 else return desc.mid(loc+4); 390 683 } 391 684 392 685 393 394 686 /* comments in header */ 395 687 void MythControls::loadHost(const QString & hostname) { 396 688 397 689 /* create the key bindings and the tree */ 398 690 key_bindings = new KeyBindings(hostname); 399 QStringList * context_names =key_bindings->getContexts();691 contexts = *key_bindings->getContexts(); 400 692 693 keys.clear(); 694 401 695 /* Alphabetic order, but jump and global at the top */ 402 context _names->sort();403 context _names->remove(JUMP_CONTEXT);404 context _names->remove(GLOBAL_CONTEXT);405 context _names->insert(context_names->begin(), 1, GLOBAL_CONTEXT);406 context _names->insert(context_names->begin(), 1, JUMP_CONTEXT);696 contexts.sort(); 697 contexts.remove(JUMP_CONTEXT); 698 contexts.remove(GLOBAL_CONTEXT); 699 contexts.insert(contexts.begin(), 1, GLOBAL_CONTEXT); 700 contexts.insert(contexts.begin(), 1, JUMP_CONTEXT); 407 701 408 UIListBtnTypeItem *item;409 702 QStringList *actions; 410 for (size_t i = 0; i < context _names->size(); i++)703 for (size_t i = 0; i < contexts.size(); i++) 411 704 { 412 item = new UIListBtnTypeItem(ContextList, (*context_names)[i]); 413 item->setDrawArrow(true); 414 actions = key_bindings->getActions((*context_names)[i]); 705 actions = key_bindings->getActions(contexts[i]); 415 706 actions->sort(); 416 m_contexts.insert( (*context_names)[i], actions);707 m_contexts.insert(contexts[i], actions); 417 708 } 418 709 419 refresh ActionList((*context_names)[0]);420 free(context_names);710 refreshKeyBindings(); 711 updateLists(); 421 712 } 422 713 423 714 … … 425 716 /* comments in header */ 426 717 void MythControls::deleteKey() 427 718 { 428 size_t b = focusedButton(); 429 QString action = getCurrentAction(), context = getCurrentContext(); 430 QStringList keys = key_bindings->getActionKeys(context, action); 431 if (b < keys.count()) 719 // This code needs work to support deleteKey in any mode exc. Context/Action 720 QString context = getCurrentContext(); 721 QString key = getCurrentKey(); 722 QString action = getCurrentAction(); 723 if (context.isEmpty() || key.isEmpty() || action.isEmpty()) 432 724 { 433 if (!key_bindings->removeActionKey(context, action, keys[b])) 434 { 435 InvalidBindingPopup popup(gContext->GetMainWindow()); 436 popup.getOption(); 437 } 438 else refreshKeyInformation(); 725 InvalidBindingPopup popup(gContext->GetMainWindow()); 726 popup.getOption(); 727 return; 439 728 } 440 }441 729 730 BindingList *list = keyActions[key]; 731 binding_t *binding = NULL; 732 for (BindingList::iterator it = list->begin(); it != list->end(); ++it) 733 { 734 binding_t *b = *it; 735 if (b->context == context) binding = b; 736 } 737 if (!binding) 738 { 739 InvalidBindingPopup popup(gContext->GetMainWindow()); 740 popup.getOption(); 741 return; 742 } 442 743 744 if (binding->contextFrom != context) 745 { 746 ConfirmMenu popup(gContext->GetMainWindow(), tr("Delete this key binding from context %1?").arg(binding->contextFrom)); 747 if (popup.getOption() != ConfirmMenu::CONFIRM) return; 748 } else { 749 ConfirmMenu popup(gContext->GetMainWindow(), tr("Delete this binding?")); 750 if (popup.getOption() != ConfirmMenu::CONFIRM) return; 751 } 443 752 753 if (!key_bindings->removeActionKey(binding->contextFrom, action, key)) 754 { 755 InvalidBindingPopup popup(gContext->GetMainWindow()); 756 popup.getOption(); 757 return; 758 } 759 760 // refreshing everything is overkill. I tried incrementally updating, but the 761 // code was ugly. Since this is quick in my experience, overkill away! 762 refreshKeyBindings(); 763 refreshKeyInformation(); 764 } 765 444 766 /* method description in header */ 445 767 bool MythControls::resolveConflict(ActionID *conflict, int level) 446 768 { … … 475 797 /* method description in header */ 476 798 void MythControls::addKeyToAction(void) 477 799 { 800 // This code needs work to support deleteKey in any mode exc. Context/Action 478 801 /* grab a key from the user */ 479 802 KeyGrabPopupBox *kg = new KeyGrabPopupBox(gContext->GetMainWindow()); 480 803 int result = kg->ExecPopup(kg,SLOT(cancel())); … … 511 834 else 512 835 key_bindings->addActionKey(context, action, key); 513 836 837 refreshKeyBindings(); 514 838 refreshKeyInformation(); 515 839 } 516 840 841 void MythControls::addBindings(QDict<binding_t> &bindings, const QString &context, const QString &contextParent, int bindlevel) 842 { 843 QStringList *actions = key_bindings->getActions(context); 844 845 for (size_t i = 0; i < actions->size(); i++) 846 { 847 QString action = (*actions)[i]; 848 QStringList keys = key_bindings->getActionKeys(context, action); 849 850 for (size_t j = 0; j < keys.size(); j++) 851 { 852 QString key = keys[j]; 853 854 binding_t *b = bindings.find(key); 855 if (!b) 856 { 857 b = new(binding_t); 858 b->key = key; 859 b->action = action; 860 b->context = contextParent; 861 b->contextFrom = context; 862 b->bindlevel = bindlevel; 863 bindings.insert(key, b); 864 } 865 else if (b->bindlevel == bindlevel) 866 { 867 b->action += ", " + action; 868 } 869 } 870 } 871 } 872 873 BindingList *MythControls::getKeyBindings(const QString &context) 874 { 875 QDict<binding_t> bindings; 876 bindings.clear(); 877 878 QMap<int,QString> contextList = FindContexts(context); 879 for (QMap<int,QString>::iterator it = contextList.begin(); it != contextList.end(); ++it) 880 { 881 int level = it.key(); 882 QString curcontext = it.data(); 883 addBindings(bindings, curcontext, context, level); 884 } 885 886 QStringList keys; 887 888 for (QDictIterator<binding_t> it(bindings); it.current(); ++it) 889 { 890 QString key = it.currentKey(); 891 keys.append(key); 892 } 893 894 sortKeyList(keys); 895 896 BindingList *retval = new BindingList; 897 retval->clear(); 898 899 for (QStringList::Iterator kit = keys.begin(); kit != keys.end(); ++kit) 900 { 901 QString key = *kit; 902 retval->append(bindings[key]); 903 } 904 retval->setAutoDelete(true); 905 return retval; 906 } 907 908 void MythControls::refreshKeyBindings() 909 { 910 contextKeys.clear(); 911 keyActions.clear(); 912 for (size_t i = 0; i < contexts.size(); i++) 913 { 914 QString context = contexts[i]; 915 BindingList *list = getKeyBindings(context); 916 contextKeys.insert(context, list); 917 for (BindingList::iterator it = list->begin(); it != list->end(); ++it) 918 { 919 binding_t *b = *it; 920 BindingList *list = keyActions.find(b->key); 921 if (!list) 922 { 923 list = new BindingList; 924 list->clear(); 925 keyActions.insert(b->key, list); 926 } 927 keys.append(b->key); 928 list->append(b); 929 } 930 } 931 contextKeys.setAutoDelete(true); 932 keyActions.setAutoDelete(true); 933 934 sortKeyList(keys); 935 } 936 937 void MythControls::sortKeyList(QStringList &keys) 938 { 939 QStringList t; 940 t.clear(); 941 942 for ( QStringList::Iterator it = keys.begin(); it != keys.end(); ++it ) 943 { 944 QString key = *it; 945 946 QString keydesc = "3 "; 947 if (key.left(6) == "remote") 948 { 949 keydesc = "0 "; 950 } 951 else if (key.length() == 1) 952 { 953 switch (key[0].category()) 954 { 955 case QChar::Letter_Uppercase: 956 keydesc = "2 "; 957 break; 958 case QChar::Number_DecimalDigit: 959 keydesc = "1 "; 960 break; 961 } 962 } 963 else if (key.find("+", 1) != -1) 964 keydesc = "4 "; 965 966 t.push_back(keydesc + key); 967 } 968 t.sort(); 969 970 QString prev = ""; 971 972 keys.clear(); 973 for (QStringList::Iterator kit = t.begin(); kit != t.end(); ++kit) 974 { 975 QString cur = (*kit).mid(2); 976 if (cur != prev) 977 { 978 keys.append(cur); 979 prev = cur; 980 } 981 } 982 } 983 984 QString MythControls::getTypeDesc(ListType type) 985 { 986 switch (type) 987 { 988 case kContextList: 989 return tr("Contexts"); 990 break; 991 case kKeyList: 992 return tr("Keys"); 993 break; 994 case kActionList: 995 return tr("Actions"); 996 break; 997 default: 998 return ""; 999 } 1000 } 1001 1002 void MythControls::updateLists() 1003 { 1004 RightList->blockSignals(true); 1005 LeftList->blockSignals(true); 1006 LeftList->Reset(); 1007 if (leftType == kContextList) 1008 { 1009 UIListBtnTypeItem *item; 1010 for (size_t i = 0; i < contexts.size(); i++) 1011 { 1012 item = new UIListBtnTypeItem(LeftList, contexts[i]); 1013 item->setDrawArrow(true); 1014 } 1015 } else if (leftType == kKeyList) 1016 { 1017 UIListBtnTypeItem *item; 1018 for (size_t i = 0; i < keys.size(); i++) 1019 { 1020 QString key = KeyToDisplay(keys[i]); 1021 item = new UIListBtnTypeItem(LeftList, key); 1022 item->setDrawArrow(true); 1023 } 1024 } 1025 refreshRightList(); 1026 RightList->blockSignals(false); 1027 LeftList->blockSignals(false); 1028 LeftList->refresh(); 1029 RightList->refresh(); 1030 1031 if (LeftDesc != NULL) 1032 LeftDesc->SetText(getTypeDesc(leftType)); 1033 if (RightDesc != NULL) 1034 RightDesc->SetText(getTypeDesc(rightType)); 1035 } 1036 1037 517 1038 #endif /* MYTHCONTROLS_CPP */ 1039 1040 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
mythcontrols.h
29 29 30 30 #include "keybindings.h" 31 31 32 typedef struct 33 { 34 QString key; 35 QString context; 36 QString contextFrom; 37 QString action; 38 int bindlevel; 39 } binding_t; 32 40 41 typedef QPtrList<binding_t> BindingList; 42 33 43 /** 34 44 * @class MythControls 35 45 * @brief The myth controls configuration class. … … 71 81 */ 72 82 QString getCurrentAction(void) const; 73 83 84 /** 85 * @brief Get the currently selected key string 86 * @return The currently selected key string 87 * 88 * If no context is selected, an empty string is returned. 89 */ 90 QString getCurrentKey(void) const; 91 74 92 75 93 76 94 protected: … … 105 123 * @param context The context, from which actions will be 106 124 * displayed. 107 125 */ 108 void refresh ActionList(const QString & context);126 void refreshRightList(void); 109 127 110 128 /** 129 * @brief Redisplay both the left and right lists and fix focus 130 */ 131 void updateLists(void); 132 133 /** 111 134 * @brief Load the settings for a particular host. 112 135 * @param hostname The host to load settings for. 113 136 */ … … 143 166 */ 144 167 void switchListFocus(UIListBtnType *focus, UIListBtnType *unfocus); 145 168 169 /** 170 * @brief Add bindings to QDict<binding_t> for specified context 171 * @param bindings the QDict to which to add the bindings 172 * @param context the context to grab keybindings from 173 * @param contextParent the context whose keybindings are being calculated 174 * @param bindlevel the bind level associated with this context 175 */ 176 void addBindings(QDict<binding_t> &bindings, const QString &context, const QString &contextParent, int bindlevel); 177 178 /** 179 * @brief Create a BindingList for the specified context 180 * @param context the context for which a BindingList should be created 181 */ 182 BindingList *getKeyBindings(const QString &context); 183 146 184 private slots: 147 185 148 186 /** … … 161 199 inline void save(void) { key_bindings->commitChanges(); } 162 200 163 201 /** 164 * @brief Recieves a signal when an item in the context list is202 * @brief Recieves a signal when an item in the left list is 165 203 * selected. 166 204 * @param item The selected item. 167 205 */ 168 void contextSelected(UIListBtnTypeItem *item);206 void leftSelected(UIListBtnTypeItem *item); 169 207 170 208 /** 171 * @brief Recieves a signal when an item in the actionlist is209 * @brief Recieves a signal when an item in the right list is 172 210 * selected. 173 211 * @param item The selected item. 174 212 */ 175 void actionSelected(UIListBtnTypeItem *item);213 void rightSelected(UIListBtnTypeItem *item); 176 214 215 /** 216 * @brief Sort a list of keys, removing duplicates 217 * @param keys the list of keys to sort 218 */ 219 void sortKeyList(QStringList &keys); 220 221 /** 222 * @brief Refresh binding information 223 */ 224 void refreshKeyBindings(); 225 226 /** 227 * @brief Jump to a particular key binding 228 * @param e key event to use as jump 229 */ 230 bool JumpTo(QKeyEvent *e); 231 177 232 private: 178 233 179 234 UIType *focused; 180 UIListBtnType * ContextList;181 UIListBtnType * ActionList;182 UITextType *description ;235 UIListBtnType *LeftList; 236 UIListBtnType *RightList; 237 UITextType *description, *LeftDesc, *RightDesc; 183 238 UITextButtonType * ActionButtons[Action::MAX_KEYS]; 184 239 KeyBindings *key_bindings; 185 240 LayerSet *container; 186 QDict<QStringList> m_contexts; 241 242 QStringList contexts; ///< sorted list of contexts 243 QStringList keys; ///< sorted list of keys 244 245 QDict<QStringList> m_contexts; ///< actions for a given context 246 QDict<BindingList> contextKeys; ///< key bindings for a given context 247 QDict<BindingList> keyActions; ///< actions in each context for a given key 248 249 typedef enum { kContextList, kKeyList, kActionList } ListType; 250 ListType leftType, rightType; 251 252 QString getTypeDesc(ListType type); 253 187 254 }; 188 255 189 256 -
keybindings.h
84 84 } 85 85 86 86 /** 87 * @brief Get a list of the actions in a context. 88 * @param context The name of the context. 89 * @return A list of action (names) for the target context. 90 * @note Store this instead of calling repeatedly. Every time you 91 * do, ActionSet has to iterate over all contexts and actions. 92 */ 93 inline void getKeyActions(const QString &key, ActionList &list) const 94 { 95 list = actionset.getActions(key); 96 } 97 98 /** 87 99 * @brief Get an action's keys. 88 100 * @param context_name The name of the context. 89 101 * @param action_name The name of the action. -
keygrabber.cpp
153 153 addButton(tr("Save"), this, SLOT(save()))->setFocus(); 154 154 addButton(tr("Exit"), this, SLOT(cancel())); 155 155 } 156 157 ConfirmMenu::ConfirmMenu(MythMainWindow *window, QString msg) 158 : MythPopupBox(window, "unsavedmenu") 159 { 160 addLabel(tr("Confirm"), Large, false); 161 addLabel(msg); 162 addButton(tr("Confirm"), this, SLOT(confirm()))->setFocus(); 163 addButton(tr("Cancel"), this, SLOT(cancel())); 164 } -
keygrabber.h
141 141 142 142 public: 143 143 144 enum act ons { SAVE, CANCEL };144 enum actions { SAVE, CANCEL }; 145 145 146 146 /** 147 147 * @brief Create a new action window. … … 180 180 181 181 public: 182 182 183 enum act ons { SET, REMOVE, CANCEL };183 enum actions { SET, REMOVE, CANCEL }; 184 184 185 185 /** 186 186 * @brief Create a new action window. … … 222 222 223 223 public: 224 224 225 enum act ons { SAVE, EXIT };225 enum actions { SAVE, EXIT }; 226 226 227 227 /** 228 228 * @brief Create a new action window. … … 247 247 inline void cancel(void) { done(UnsavedMenu::EXIT); } 248 248 249 249 }; 250 251 /** 252 * @class ConfirmMenu 253 * @brief A popup confirming an action 254 */ 255 class ConfirmMenu : public MythPopupBox 256 { 257 258 Q_OBJECT; 259 260 public: 261 262 enum actions { CONFIRM, CANCEL }; 263 264 /** 265 * @brief Create a new action window. 266 */ 267 ConfirmMenu(MythMainWindow *window, QString msg); 268 269 /** 270 * @brief Execute the option popup. 271 */ 272 inline int getOption(void) { return ExecPopup(this,SLOT(cancel())); } 273 274 public slots: 275 276 /** 277 * @brief Slot to connect to when the save button is pressed. 278 */ 279 inline void confirm(void) { done(UnsavedMenu::SAVE); } 280 281 /** 282 * @brief Slot to connect to when the cancel button is pressed. 283 */ 284 inline void cancel(void) { done(UnsavedMenu::EXIT); } 285 286 }; -
controls-ui.xml
29 29 <bold>yes</bold> 30 30 </font> 31 31 32 <font name="options" face="Arial"> 33 <color>#ffffff</color> 34 <size>24</size> 35 <bold>yes</bold> 36 </font> 37 38 32 39 <font name="infotitle" face="Arial"> 33 40 <color>#ffffff</color> 34 <size>2 4</size>41 <size>20</size> 35 42 <shadow>10,10</shadow> 36 43 <bold>yes</bold> 37 44 </font> 38 45 39 46 <container name="controls"> 40 <area>20,20,780, 380</area>47 <area>20,20,780,450</area> 41 48 42 <listbtnarea name="contextlist" draworder="0"> 43 <area>0,0,370,360</area> 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 <textarea name="leftdesc" draworder="1" align="center"> 56 <font>info</font> 57 <area>0,40,370,20</area> 58 <value>Contexts</value> 59 </textarea> 60 61 <listbtnarea name="leftlist" draworder="0"> 62 <area>0,60,370,380</area> 44 63 <gradient type="unselected" start="#505050" end="#000000" alpha="100"/> 45 64 <gradient type="selected" start="#52CA38" end="#349838" alpha="255"/> 46 65 <fcnfont name="active" function="active"/> … … 48 67 <showarrow>no</showarrow> 49 68 </listbtnarea> 50 69 51 <listbtnarea name="actionlist" draworder="0"> 52 <area>390,0,370,360</area> 70 <textarea name="rightdesc" draworder="1" align="center"> 71 <font>info</font> 72 <area>390,40,370,20</area> 73 <value>Actions</value> 74 </textarea> 75 76 <listbtnarea name="rightlist" draworder="0"> 77 <area>390,60,370,380</area> 53 78 <gradient type="unselected" start="#505050" end="#000000" alpha="100"/> 54 79 <gradient type="selected" start="#52CA38" end="#349838" alpha="255"/> 55 80 <fcnfont name="active" function="active"/> … … 60 85 </container> 61 86 62 87 <container name="keys_layer"> 63 <area>20,4 00,780,180</area>88 <area>20,450,780,210</area> 64 89 <textbutton name="action_one" draworder="0"> 65 <position>20, 20</position>90 <position>20,0</position> 66 91 <image function="on" filename="kb-button-on.png"/> 67 92 <image function="off" filename="kb-button-off.png"/> 68 93 <font>keys</font> 69 94 </textbutton> 70 95 71 96 <textbutton name="action_two" draworder="0"> 72 <position>200, 20</position>97 <position>200,0</position> 73 98 <image function="on" filename="kb-button-on.png"/> 74 99 <image function="off" filename="kb-button-off.png"/> 75 100 <font>keys</font> 76 101 </textbutton> 77 102 78 103 <textbutton name="action_three" draworder="0"> 79 <position>390, 20</position>104 <position>390,0</position> 80 105 <image function="on" filename="kb-button-on.png"/> 81 106 <image function="off" filename="kb-button-off.png"/> 82 107 <font>keys</font> 83 108 </textbutton> 84 109 85 110 <textbutton name="action_four" draworder="0"> 86 <position>580, 20</position>111 <position>580,0</position> 87 112 <image function="on" filename="kb-button-on.png"/> 88 113 <image function="off" filename="kb-button-off.png"/> 89 114 <font>keys</font> … … 91 116 92 117 <textarea name="description" draworder="1" allign="left"> 93 118 <font>info</font> 94 <area>30, 100,740,140</area>119 <area>30,70,740,110</area> 95 120 <multiline>yes</multiline> 96 121 </textarea> 97 122